3단계: Laravel 프로젝트 배포

← 이전: 서버 환경 설정 메인으로 다음: 도메인/HTTPS 설정 →

이제 드디어 Laravel 프로젝트를 서버에 배포할 차례예요! GitHub에서 코드를 가져와서 실제로 동작하도록 만들어봅시다.

이 단계에서 배울 내용

  • GitHub 저장소 준비 및 접근 설정
  • 서버로 프로젝트 클론하기
  • Composer로 의존성 설치
  • .env 파일 설정하기
  • 데이터베이스 마이그레이션 실행
  • Laravel 캐시 최적화
  • 파일 권한 설정
  • 프론트엔드 에셋 빌드

💡 예상 소요 시간: 30-40분 정도 걸려요.


3.1 GitHub 저장소 준비하기

GitHub에 프로젝트가 있나요?

아직 GitHub에 프로젝트를 올리지 않으셨다면, 먼저 올려주세요. 로컬에서 다음 명령어를 실행하세요:

# 로컬 프로젝트 디렉토리에서
git init
git add .
git commit -m "Initial commit"
git branch -M main
git remote add origin https://github.com/your-username/jinyerp_demo_01.git
git push -u origin main

저장소 타입 확인

저장소가 공개(Public)인가요, 비공개(Private)인가요?

공개 저장소인 경우

  • 추가 설정 불필요
  • HTTPS로 바로 클론 가능

비공개 저장소인 경우

  • Personal Access Token 또는 SSH 키 필요
  • 아래 방법 중 하나 선택

3.2 서버에서 GitHub 접근 설정하기

방법 1: SSH 키 사용 (권장)

SSH 키를 사용하면 매번 비밀번호를 입력할 필요가 없어요.

1단계: SSH 키 생성

서버에서 다음 명령어 실행:

# SSH 키 생성
ssh-keygen -t rsa -b 4096 -C "deploy@example.com"

# Enter 키를 3번 누르세요 (기본 경로, 비밀번호 없음)

2단계: 공개 키 복사

# 공개 키 내용 출력
cat ~/.ssh/id_rsa.pub

출력된 내용을 전부 복사하세요 (ssh-rsa로 시작하는 긴 문자열)

3단계: GitHub에 SSH 키 등록

  1. GitHub 웹사이트 접속
  2. SettingsSSH and GPG keys 메뉴
  3. New SSH key 클릭
  4. Title: “Laravel Server” (알아보기 쉬운 이름)
  5. Key: 복사한 공개 키 붙여넣기
  6. Add SSH key 클릭

4단계: SSH 연결 테스트

# GitHub SSH 연결 테스트
ssh -T git@github.com

# 출력:
# Hi username! You've successfully authenticated...

방법 2: Personal Access Token (간단한 방법)

1단계: Token 생성

  1. GitHub SettingsDeveloper settingsPersonal access tokensTokens (classic)
  2. Generate new token (classic) 클릭
  3. Note: “Laravel Deploy Server”
  4. Expiration: 90 days (또는 원하는 기간)
  5. Select scopes: repo 체크
  6. Generate token 클릭
  7. 생성된 토큰 복사 (다시 볼 수 없어요!)

2단계: Token 저장

# 토큰을 안전한 곳에 저장
echo "ghp_xxxxxxxxxxxxxxxxxxxx" > ~/.github_token
chmod 600 ~/.github_token

3.3 프로젝트 클론하기

웹 루트 디렉토리로 이동

# 웹 루트 디렉토리로 이동
cd /var/www

# 현재 디렉토리 확인
ls -la

GitHub에서 프로젝트 클론

SSH 방식 (권장)

# SSH로 클론 (비공개/공개 저장소 모두 가능)
sudo git clone git@github.com:your-username/jinyerp_demo_01.git

HTTPS 방식 (공개 저장소)

# HTTPS로 클론 (공개 저장소)
sudo git clone https://github.com/your-username/jinyerp_demo_01.git

HTTPS + Token 방식 (비공개 저장소)

# HTTPS + Token으로 클론 (비공개 저장소)
sudo git clone https://ghp_your_token@github.com/your-username/jinyerp_demo_01.git

💡 팁: your-usernamejinyerp_demo_01을 실제 저장소 정보로 바꿔주세요!

클론 완료 확인

# 클론된 디렉토리 확인
ls -la /var/www/

# 프로젝트 구조 확인
ls -la /var/www/jinyerp_demo_01

Laravel 프로젝트 파일들(app, config, routes 등)이 보이면 성공! 🎉


3.4 파일 소유권 및 권한 설정

웹서버 사용자로 소유권 변경

Nginx는 www-data 사용자로 실행되므로 소유권을 변경해야 해요:

# 전체 프로젝트 소유권을 www-data로 변경
sudo chown -R www-data:www-data /var/www/jinyerp_demo_01

기본 권한 설정

# 기본 파일 권한 설정
sudo chmod -R 755 /var/www/jinyerp_demo_01

Laravel 특수 디렉토리 권한

Laravel의 storage와 bootstrap/cache 디렉토리는 쓰기 권한이 필요해요:

# storage 디렉토리 쓰기 권한
sudo chmod -R 775 /var/www/jinyerp_demo_01/storage

# bootstrap/cache 디렉토리 쓰기 권한
sudo chmod -R 775 /var/www/jinyerp_demo_01/bootstrap/cache

3.5 Composer 의존성 설치

composer.json 파일 확인

# 프로젝트 디렉토리로 이동
cd /var/www/jinyerp_demo_01

# composer.json 파일 확인
cat composer.json

의존성 설치

# www-data 사용자로 Composer 의존성 설치
sudo -u www-data composer install --optimize-autoloader --no-dev

💡 옵션 설명:

  • --optimize-autoloader: 성능 최적화
  • --no-dev: 개발용 패키지 제외 (프로덕션 환경)

1GB RAM 서버에서 메모리 부족 시

메모리가 부족하다는 에러가 나오면:

# 스크립트 실행 없이 설치
sudo -u www-data composer install --optimize-autoloader --no-dev --no-scripts

# 스크립트 따로 실행
sudo -u www-data composer run-script post-autoload-dump

설치 확인

# Composer 의존성 확인
sudo -u www-data composer check-platform-reqs

# vendor 디렉토리 확인
ls -la vendor/

# Laravel 명령어 테스트
sudo -u www-data php artisan --version

Laravel 버전이 출력되면 성공! 🎉


3.6 환경 설정 파일 구성

.env 파일 생성

# .env.example에서 .env 생성
sudo -u www-data cp .env.example .env

.env 파일 편집

# .env 파일 편집
sudo nano .env

다음 내용을 찾아서 수정해주세요:

# 애플리케이션 기본 설정
APP_NAME="Jiny ERP Demo"
APP_ENV=production
APP_DEBUG=false
APP_KEY=
APP_TIMEZONE=Asia/Seoul
APP_URL=http://your-server-ip

# 데이터베이스 설정
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=jinyerp_demo
DB_USERNAME=jinyerp
DB_PASSWORD=your_mysql_password_here

# 캐시 설정
CACHE_STORE=redis
SESSION_DRIVER=redis
SESSION_LIFETIME=120
QUEUE_CONNECTION=redis

# Redis 설정
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=your_redis_password_here
REDIS_PORT=6379
REDIS_DB=0

# 로그 설정
LOG_CHANNEL=stack
LOG_LEVEL=error

# 파일 시스템
FILESYSTEM_DISK=local

# 브로드캐스트
BROADCAST_DRIVER=log

🔒 중요:

  • DB_PASSWORD: MySQL 사용자 비밀번호 (2단계에서 설정한 것)
  • REDIS_PASSWORD: Redis 비밀번호 (2단계에서 설정한 것)
  • APP_URL: 현재는 IP 주소, 4단계에서 도메인으로 변경

저장하고 종료: Ctrl + X, Y, Enter

.env 파일 보안 설정

# .env 파일 권한 제한 (중요!)
sudo chmod 600 /var/www/jinyerp_demo_01/.env
sudo chown www-data:www-data /var/www/jinyerp_demo_01/.env

🔒 보안: .env 파일에는 중요한 정보가 들어있어서 읽기 권한을 제한해야 해요.

주요 Laravel 설정 파일 경로

나중에 필요할 때를 위해:

  • 환경 설정: /var/www/jinyerp_demo_01/.env
  • 설정 디렉토리: /var/www/jinyerp_demo_01/config/
  • 라우트 파일: /var/www/jinyerp_demo_01/routes/web.php
  • 로그 디렉토리: /var/www/jinyerp_demo_01/storage/logs/

3.7 Laravel 애플리케이션 초기화

애플리케이션 키 생성

Laravel의 암호화에 사용되는 고유한 키를 생성해요:

# 애플리케이션 키 생성
sudo -u www-data php artisan key:generate

# 출력:
# Application key set successfully.

생성된 키 확인

# .env 파일에서 APP_KEY 확인
grep APP_KEY /var/www/jinyerp_demo_01/.env

# 출력 예시:
# APP_KEY=base64:xxxxxxxxxxxxxxxxxxxxxxxxxx

3.8 데이터베이스 마이그레이션

데이터베이스 연결 테스트

# 마이그레이션 상태 확인 (연결 테스트)
sudo -u www-data php artisan migrate:status

에러 없이 마이그레이션 목록이 나오면 데이터베이스 연결 성공!

마이그레이션 실행

# 프로덕션 환경에서 마이그레이션 실행
sudo -u www-data php artisan migrate --force

💡 --force 옵션: 프로덕션 환경에서는 확인 메시지 없이 실행하기 위해 필요해요.

시드 데이터 실행 (선택사항)

초기 데이터가 있다면:

# 모든 시더 실행
sudo -u www-data php artisan db:seed --force

# 또는 특정 시더만 실행
sudo -u www-data php artisan db:seed --class=UserSeeder --force

마이그레이션 확인

# 다시 상태 확인
sudo -u www-data php artisan migrate:status

# 데이터베이스 테이블 확인
mysql -u jinyerp -p jinyerp_demo -e "SHOW TABLES;"

3.9 Laravel 저장소 및 캐시 설정

Storage 심볼릭 링크 생성

업로드된 파일이 public에서 접근 가능하도록:

# storage를 public으로 링크
sudo -u www-data php artisan storage:link

# 출력:
# The [public/storage] link has been connected to [storage/app/public].

캐시 생성 (성능 향상)

Laravel의 설정 파일들을 캐싱하면 성능이 크게 향상돼요:

# 설정 캐시 생성
sudo -u www-data php artisan config:cache

# 라우트 캐시 생성
sudo -u www-data php artisan route:cache

# 뷰 캐시 생성
sudo -u www-data php artisan view:cache

# 이벤트 캐시 생성
sudo -u www-data php artisan event:cache

💡 언제 캐시를 재생성하나요? 설정 파일, 라우트, 뷰를 수정한 후에는 해당 캐시를 다시 생성해야 해요.

캐시 확인

# 캐시 파일 확인
ls -la bootstrap/cache/

config.php, routes-v7.php 등의 파일이 보이면 성공!


3.10 파일 권한 최종 설정

전체 소유권 재설정

# Laravel 전체 디렉토리 소유권
sudo chown -R www-data:www-data /var/www/jinyerp_demo_01

일반 파일 및 디렉토리 권한

# 일반 파일 권한 (644)
sudo find /var/www/jinyerp_demo_01 -type f -exec chmod 644 {} \;

# 디렉토리 권한 (755)
sudo find /var/www/jinyerp_demo_01 -type d -exec chmod 755 {} \;

쓰기 권한 필요한 디렉토리

# storage 디렉토리 (로그, 세션, 캐시)
sudo chmod -R 775 /var/www/jinyerp_demo_01/storage

# bootstrap/cache 디렉토리
sudo chmod -R 775 /var/www/jinyerp_demo_01/bootstrap/cache

artisan 실행 권한

# artisan 명령어 실행 권한
sudo chmod 755 /var/www/jinyerp_demo_01/artisan

권한 설정 확인

# 주요 디렉토리 권한 확인
ls -la /var/www/jinyerp_demo_01/ | grep -E "storage|bootstrap"

3.11 프론트엔드 빌드 (선택사항)

Laravel 프로젝트에 프론트엔드 에셋이 있다면 빌드해야 해요.

package.json 확인

# package.json 파일 확인
cat /var/www/jinyerp_demo_01/package.json

package.json이 없다면 이 단계를 건너뛰세요.

Node.js 의존성 설치

# 프로젝트 디렉토리로 이동
cd /var/www/jinyerp_demo_01

# Node.js 의존성 설치 (1GB RAM 환경)
sudo -u www-data env NODE_OPTIONS="--max-old-space-size=512" npm ci

💡 npm ci가 뭔가요? npm install보다 빠르고 클린한 설치 방법이에요. CI/CD 환경에 최적화되어 있습니다.

프론트엔드 빌드

# 프로덕션 빌드
sudo -u www-data npm run build

빌드가 완료될 때까지 기다려주세요 (3-5분 소요)

빌드 결과 확인

# 빌드된 파일 확인
ls -la public/build/

manifest.json과 assets 디렉토리가 있으면 성공!


3.12 Laravel 설정 검증

애플리케이션 상태 확인

# Laravel 버전 확인
sudo -u www-data php artisan --version

# 환경 정보 확인
sudo -u www-data php artisan env

# 라우트 목록 확인
sudo -u www-data php artisan route:list

데이터베이스 연결 테스트

# 마이그레이션 상태 재확인
sudo -u www-data php artisan migrate:status

# Tinker로 데이터베이스 테스트
sudo -u www-data php artisan tinker

Tinker가 실행되면:

// 데이터베이스 연결 테스트
DB::connection()->getPdo();

// 테이블 확인
DB::select('SHOW TABLES');

// 종료
exit

로그 확인

# Laravel 로그 디렉토리 확인
ls -la /var/www/jinyerp_demo_01/storage/logs/

# 현재 로그 확인 (실시간)
sudo tail -f /var/www/jinyerp_demo_01/storage/logs/laravel.log

Ctrl + C로 종료


✅ 3단계 완료 체크리스트

모든 단계를 완료하셨나요? 체크리스트로 확인해봅시다!

  • GitHub 저장소 접근 설정 (SSH 키 또는 Token)
  • 프로젝트 정상 클론
  • 파일 소유권 www-data로 변경
  • Composer 의존성 설치 완료
  • .env 파일 생성 및 설정
  • .env 파일 보안 권한 설정
  • 애플리케이션 키 생성
  • 데이터베이스 마이그레이션 완료
  • Storage 심볼릭 링크 생성
  • Laravel 캐시 설정 (config, route, view)
  • 파일 권한 최종 설정
  • 프론트엔드 빌드 (선택사항)
  • 애플리케이션 상태 검증

최종 확인 명령어

# 모든 설정 한 번에 확인
echo "=== Laravel Version ===" && sudo -u www-data php artisan --version
echo "=== Database ===" && sudo -u www-data php artisan migrate:status
echo "=== Storage Link ===" && ls -la public/ | grep storage
echo "=== Permissions ===" && ls -la storage/ | head -3
echo "=== Cache ===" && ls -la bootstrap/cache/ | grep -E "config|routes"

문제 해결

문제 1: Composer install 실패 (메모리 부족)

Allowed memory size exhausted

해결 방법:

# 스왑 파일 생성 (아직 안 만들었다면)
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile

# 다시 설치
sudo -u www-data composer install --no-scripts
sudo -u www-data composer run-script post-autoload-dump

문제 2: 데이터베이스 연결 실패

SQLSTATE[HY000] [1045] Access denied

해결 방법:

# .env 파일 확인
cat .env | grep -E "DB_"

# MySQL 사용자 권한 재확인
mysql -u root -p -e "SHOW GRANTS FOR 'jinyerp'@'localhost';"

# 비밀번호가 틀렸다면 재설정
mysql -u root -p -e "ALTER USER 'jinyerp'@'localhost' IDENTIFIED BY 'new_password';"

문제 3: 권한 문제

failed to open stream: Permission denied

해결 방법:

# 소유권 재설정
sudo chown -R www-data:www-data /var/www/jinyerp_demo_01

# storage 권한 재설정
sudo chmod -R 775 /var/www/jinyerp_demo_01/storage
sudo chmod -R 775 /var/www/jinyerp_demo_01/bootstrap/cache

문제 4: 캐시 문제

Configuration cache file does not exist

해결 방법:

# 모든 캐시 삭제
sudo -u www-data php artisan cache:clear
sudo -u www-data php artisan config:clear
sudo -u www-data php artisan route:clear
sudo -u www-data php artisan view:clear

# 캐시 재생성
sudo -u www-data php artisan config:cache
sudo -u www-data php artisan route:cache
sudo -u www-data php artisan view:cache

문제 5: Storage 링크 에러

symlink(): File exists

해결 방법:

# 기존 링크 삭제
sudo rm /var/www/jinyerp_demo_01/public/storage

# 링크 재생성
sudo -u www-data php artisan storage:link

다음 단계

축하합니다! 3단계를 완료하셨어요! 🎉

Laravel 애플리케이션이 서버에 배포되었어요. 이제 도메인을 연결하고 HTTPS를 설정할 차례입니다!


← 이전: 서버 환경 설정 메인으로 다음: 도메인/HTTPS 설정 →