4단계: 도메인 설정 및 HTTPS

← 이전: Laravel 배포 메인으로 다음: 성능 최적화 →

이제 도메인을 연결하고 무료 SSL 인증서를 설치해서 HTTPS를 적용해봅시다! demo.jinyerp.com 같은 멋진 주소로 여러분의 Laravel 앱에 접속할 수 있게 될 거예요.

이 단계에서 배울 내용

  • 도메인 DNS 설정하기
  • Nginx 가상 호스트 구성
  • HTTP로 기본 접속 테스트
  • Let’s Encrypt SSL 인증서 발급 (무료!)
  • HTTPS 적용 및 자동 리다이렉트 설정
  • SSL 보안 강화
  • 방화벽 최종 설정

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

⚠️ 도메인이 없다면?: IP 주소로도 테스트할 수 있지만, SSL 인증서는 도메인이 필요해요. 무료 도메인(Freenom 등)이나 저렴한 도메인(.xyz 등)을 고려해보세요.


4.1 도메인 DNS 설정하기

서버 IP 주소 확인

먼저 서버의 공인 IP 주소를 확인해요:

# 서버 IP 주소 확인
curl ifconfig.me

# 또는
curl icanhazip.com

# 출력 예시: 123.456.78.90

이 IP 주소를 어딘가에 메모해두세요!

DNS 설정이란?

DNS는 도메인 이름(demo.jinyerp.com)을 서버 IP 주소(123.456.78.90)로 변환해주는 서비스예요. 마치 주소록 같은 거죠!

도메인 업체에서 DNS 설정하기

일반적인 도메인 업체 (가비아, 후이즈, GoDaddy 등)

  1. 도메인 업체 웹사이트 로그인
  2. DNS 관리 또는 네임서버 관리 메뉴 찾기
  3. A 레코드 추가:
    Type: A
    Host: demo (또는 @, subdomain)
    Value: 123.456.78.90 (서버 IP)
    TTL: 300 (5분) 또는 기본값
    

CloudFlare를 사용하는 경우

CloudFlare는 무료이면서 추가 기능이 많아요:

  1. CloudFlare Dashboard 접속
  2. 도메인 선택
  3. DNS 탭 클릭
  4. Add record 클릭:
    Type: A
    Name: demo
    IPv4 address: 123.456.78.90
    TTL: Auto
    Proxy status: DNS only (회색 구름 - 중요!)
    

💡 왜 Proxy를 끄나요? SSL 인증서를 발급받으려면 Let’s Encrypt가 직접 서버에 접근해야 해서 CloudFlare Proxy를 꺼야 해요.

예시 설정

레코드 타입 호스트명 값 (IP) TTL
A demo 123.456.78.90 300
A www.demo 123.456.78.90 300

DNS 전파 확인

DNS 설정 후 전파되는데 시간이 걸려요 (보통 5-30분):

# DNS 설정 확인
nslookup demo.jinyerp.com

# 또는 dig 명령어
dig demo.jinyerp.com A

# 결과 예시:
# demo.jinyerp.com.    300    IN    A    123.456.78.90

IP 주소가 제대로 나오면 DNS 전파 완료! 🎉

⏰ 기다리는 동안: DNS가 전파되는 동안 Nginx 설정을 먼저 준비할 수 있어요.


4.2 Nginx 가상 호스트 설정하기

가상 호스트가 뭔가요?

하나의 서버에서 여러 도메인을 호스팅할 수 있게 해주는 기능이에요.

Nginx 사이트 설정 파일 생성

# Nginx 사이트 설정 파일 생성
sudo nano /etc/nginx/sites-available/demo.jinyerp.com

초기 HTTP 설정 작성

먼저 HTTP(80번 포트)로만 설정해요. SSL 인증서는 나중에 추가할게요:

# /etc/nginx/sites-available/demo.jinyerp.com
server {
    listen 80;
    listen [::]:80;

    server_name demo.jinyerp.com www.demo.jinyerp.com;
    root /var/www/jinyerp_demo_01/public;

    # Laravel 인덱스 파일 설정
    index index.php index.html index.htm;

    # 문자 인코딩
    charset utf-8;

    # Laravel 라우팅 설정
    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    # PHP 파일 처리
    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/var/run/php/php8.4-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        include fastcgi_params;

        # PHP-FPM 타임아웃 설정
        fastcgi_connect_timeout 300;
        fastcgi_send_timeout 300;
        fastcgi_read_timeout 300;
    }

    # 정적 파일 최적화
    location ~* \.(css|js|png|jpg|jpeg|gif|ico|svg|webp|woff|woff2|ttf|eot)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
        add_header Vary Accept-Encoding;
        access_log off;
    }

    # 숨김 파일 보호
    location ~ /\.(?!well-known).* {
        deny all;
        access_log off;
        log_not_found off;
    }

    # 파비콘, robots.txt 로그 제외
    location = /favicon.ico {
        access_log off;
        log_not_found off;
        expires 1y;
    }

    location = /robots.txt  {
        access_log off;
        log_not_found off;
    }

    # 보안 헤더
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-XSS-Protection "1; mode=block" always;
    add_header Referrer-Policy "no-referrer-when-downgrade" always;

    # 404 에러를 Laravel로 전달
    error_page 404 /index.php;

    # 로그 설정
    access_log /var/log/nginx/demo.jinyerp.com.access.log;
    error_log /var/log/nginx/demo.jinyerp.com.error.log;
}

💡 설정 설명:

  • server_name: 여러분의 도메인으로 변경하세요
  • root: Laravel의 public 디렉토리
  • try_files: Laravel 라우팅 지원
  • fastcgi_pass: PHP-FPM 연결

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

Nginx 메인 설정 최적화 (1GB RAM용)

# Nginx 메인 설정 편집
sudo nano /etc/nginx/nginx.conf

다음 설정들을 확인하거나 추가해주세요:

# http 블록 안에 추가
http {
    # 작업자 프로세스 수
    worker_processes 1;  # 1GB RAM에서는 1개

    # 이벤트 설정
    events {
        worker_connections 512;
        use epoll;
    }

    # 기본 설정
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 15;
    types_hash_max_size 2048;

    # 서버 토큰 숨기기
    server_tokens off;

    # Gzip 압축
    gzip on;
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_min_length 1000;
    gzip_types
        application/javascript
        application/json
        application/xml
        text/css
        text/plain
        text/xml;

    # 클라이언트 요청 제한
    client_max_body_size 64M;
    client_body_buffer_size 1K;
    client_header_buffer_size 1k;
    large_client_header_buffers 2 1k;

    # 기존 설정 포함
    include /etc/nginx/mime.types;
    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}

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


4.3 사이트 활성화 및 HTTP 테스트

사이트 활성화

# 심볼릭 링크 생성 (사이트 활성화)
sudo ln -s /etc/nginx/sites-available/demo.jinyerp.com /etc/nginx/sites-enabled/

# 기본 사이트 비활성화 (포트 충돌 방지)
sudo rm -f /etc/nginx/sites-enabled/default

Nginx 설정 검증

# Nginx 설정 문법 검사
sudo nginx -t

# 출력 예시:
# nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
# nginx: configuration file /etc/nginx/nginx.conf test is successful

에러가 없으면 계속 진행!

Nginx 서비스 재시작

# Nginx 설정 다시 로드
sudo systemctl reload nginx

# 또는 재시작
sudo systemctl restart nginx

# 서비스 상태 확인
sudo systemctl status nginx

HTTP 접속 테스트

로컬에서 테스트

# 서버에서 자체 테스트
curl -H "Host: demo.jinyerp.com" http://localhost

# 또는 실제 도메인으로 (DNS 전파 후)
curl -I http://demo.jinyerp.com

브라우저에서 테스트

웹 브라우저를 열고 접속해보세요:

http://demo.jinyerp.com

Laravel 페이지가 보이면 성공! 🎉

⚠️ 아직 HTTPS가 아니에요: 주소창에 “안전하지 않음” 경고가 나오는 건 정상이에요. 이제 SSL을 설정할 거예요.


4.4 Let’s Encrypt SSL 인증서 설치

Let’s Encrypt가 뭔가요?

무료 SSL 인증서를 제공하는 서비스예요! 자동으로 갱신되고, 믿을 수 있는 인증 기관입니다.

Certbot 설치

Ubuntu 25.10에서는 snap을 통해 설치해요:

# Snapd 상태 확인
sudo systemctl status snapd

# Certbot 설치
sudo snap install core
sudo snap refresh core
sudo snap install --classic certbot

# Certbot 명령어 링크 생성
sudo ln -s /snap/bin/certbot /usr/bin/certbot

# 설치 확인
certbot --version

SSL 인증서 발급

DNS가 완전히 전파된 후 실행하세요 (보통 10-30분):

# Nginx 자동 설정으로 SSL 인증서 발급
sudo certbot --nginx -d demo.jinyerp.com -d www.demo.jinyerp.com

💡 -d 옵션: 인증서에 포함할 도메인을 지정해요. 여러 개 추가 가능합니다.

Certbot 설정 과정

차례대로 나오는 질문에 답해주세요:

1. Enter email address (for urgent renewal and security notices)
   → your-email@example.com 입력

2. Please read the Terms of Service
   → Y (동의)

3. Would you be willing to share your email address?
   → N (선택사항)

4. Select the appropriate number [1-2] then [enter]
   1: No redirect
   2: Redirect (HTTP to HTTPS)
   → 2 선택 (HTTPS로 자동 리다이렉트)

발급 완료!

성공 메시지가 나타나요:

Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/demo.jinyerp.com/fullchain.pem
Key is saved at: /etc/letsencrypt/live/demo.jinyerp.com/privkey.pem

SSL 인증서 확인

# 인증서 상태 확인
sudo certbot certificates

# Nginx 설정 파일 확인 (자동 수정됨)
cat /etc/nginx/sites-available/demo.jinyerp.com

Certbot이 자동으로 HTTPS 설정을 추가해줬어요!


4.5 HTTPS 설정 확인 및 최적화

HTTPS 접속 테스트

명령어로 테스트

# HTTP → HTTPS 리다이렉트 확인
curl -I http://demo.jinyerp.com

# HTTPS 직접 접속 확인
curl -I https://demo.jinyerp.com

# SSL 인증서 정보 확인
openssl s_client -connect demo.jinyerp.com:443 -servername demo.jinyerp.com < /dev/null

브라우저로 테스트

웹 브라우저를 열고:

https://demo.jinyerp.com

주소창에 자물쇠 🔒 아이콘이 보이면 성공!

SSL 설정 강화

더 강력한 보안을 위해 SSL 설정을 최적화해요:

# SSL 설정 파일 생성
sudo nano /etc/nginx/conf.d/ssl.conf

다음 내용을 추가:

# /etc/nginx/conf.d/ssl.conf

# SSL 프로토콜 설정 (TLS 1.2, 1.3만 허용)
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;

# SSL 세션 설정
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;

# SSL 스테이플링 (OCSP)
ssl_stapling on;
ssl_stapling_verify on;

# 보안 헤더 - HSTS (엄격한 전송 보안)
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;

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

Nginx 재시작

# 설정 문법 확인
sudo nginx -t

# Nginx 재시작
sudo systemctl reload nginx

4.6 Laravel HTTPS 설정 업데이트

.env 파일 업데이트

# .env 파일 편집
sudo nano /var/www/jinyerp_demo_01/.env

다음 줄을 찾아서 수정:

# HTTPS URL로 변경
APP_URL=https://demo.jinyerp.com

# 세션 도메인 설정
SESSION_DOMAIN=demo.jinyerp.com

# Sanctum 도메인 설정 (API 사용 시)
SANCTUM_STATEFUL_DOMAINS=demo.jinyerp.com

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

Laravel 캐시 재생성

# 설정 캐시 재생성
cd /var/www/jinyerp_demo_01
sudo -u www-data php artisan config:clear
sudo -u www-data php artisan config:cache
sudo -u www-data php artisan route:cache

4.7 자동 인증서 갱신 설정

Let’s Encrypt 인증서는 90일마다 만료돼요

자동 갱신이 설정되어 있는지 확인해봅시다:

# 자동 갱신 테스트 (실제 갱신은 안 함)
sudo certbot renew --dry-run

에러 없이 완료되면 자동 갱신 준비 완료!

자동 갱신 타이머 확인

# Certbot 갱신 타이머 상태 확인
sudo systemctl status snap.certbot.renew.timer

# 타이머 활성화 (보통 자동으로 됨)
sudo systemctl enable snap.certbot.renew.timer

수동 갱신 크론잡 추가 (선택사항)

더 확실하게 하려면 크론잡을 추가할 수 있어요:

# 크론탭 편집
sudo crontab -e

다음 줄 추가:

# 매일 새벽 2시에 인증서 갱신 시도
0 2 * * * /usr/bin/certbot renew --quiet

저장하고 종료


4.8 방화벽 최종 설정

UFW 규칙 정리

# 현재 방화벽 상태 확인
sudo ufw status verbose

Nginx Full 프로파일 허용

# Nginx Full 프로파일 허용 (HTTP + HTTPS)
sudo ufw allow 'Nginx Full'

# 기존 HTTP만 허용하는 규칙 제거 (있다면)
sudo ufw status numbered
sudo ufw delete [번호]  # HTTP만 허용하는 규칙 번호

# 또는 직접 삭제
sudo ufw delete allow 80

최종 방화벽 상태 확인

# 최종 방화벽 규칙 확인
sudo ufw status numbered

출력 예시:

Status: active

     To                         Action      From
     --                         ------      ----
[ 1] 22/tcp                     ALLOW IN    Anywhere
[ 2] Nginx Full                 ALLOW IN    Anywhere

4.9 종합 테스트 및 검증

모든 서비스 상태 확인

# 모든 관련 서비스 상태 확인
sudo systemctl status nginx php8.4-fpm mysql redis-server --no-pager

포트 사용 상황 확인

# 사용 중인 포트 확인
sudo netstat -tlnp | grep -E ':80|:443|:3306|:6379'

웹사이트 접속 테스트

1. HTTP → HTTPS 리다이렉트 테스트

curl -I http://demo.jinyerp.com
# 301 Moved Permanently 확인

2. HTTPS 직접 접속

curl -I https://demo.jinyerp.com
# 200 OK 확인

3. SSL 등급 테스트

온라인 SSL 테스트 도구 사용:

  • SSL Labs에 접속
  • 도메인 입력: demo.jinyerp.com
  • A 또는 A+ 등급이 나오면 완벽!

Laravel 로그 확인

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

# Nginx 로그 확인
sudo tail -f /var/log/nginx/demo.jinyerp.com.access.log
sudo tail -f /var/log/nginx/demo.jinyerp.com.error.log

Ctrl + C로 종료

브라우저 종합 테스트

  1. https://demo.jinyerp.com 접속
  2. SSL 인증서 확인 (주소창 자물쇠 클릭)
  3. HTTP → HTTPS 자동 리다이렉트 확인
  4. Laravel 페이지 정상 작동 확인
  5. 로그인/회원가입 테스트 (세션이 제대로 작동하는지)

✅ 4단계 완료 체크리스트

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

  • 서버 IP 주소 확인
  • 도메인 DNS A 레코드 설정
  • DNS 전파 확인 (nslookup)
  • Nginx 가상 호스트 설정 파일 작성
  • Nginx 사이트 활성화
  • HTTP 기본 접속 테스트
  • Certbot 설치
  • SSL 인증서 발급 (Let’s Encrypt)
  • HTTPS 접속 확인
  • HTTP → HTTPS 자동 리다이렉트 확인
  • Laravel .env 파일 APP_URL 업데이트
  • Laravel 캐시 재생성
  • SSL 자동 갱신 설정 확인
  • 방화벽 최종 설정
  • 브라우저 종합 테스트

문제 해결

문제 1: DNS가 전파 안 돼요

nslookup: can't resolve 'demo.jinyerp.com'

해결 방법:

  • DNS 설정 재확인 (도메인 업체)
  • 더 기다리기 (최대 24-48시간)
  • 다른 DNS 서버로 테스트: nslookup demo.jinyerp.com 8.8.8.8
  • 로컬 hosts 파일 임시 설정 (테스트용)

문제 2: Certbot SSL 발급 실패

Failed authorization procedure

해결 방법:

# DNS 전파 재확인
nslookup demo.jinyerp.com

# Nginx가 80번 포트에서 응답하는지 확인
curl -I http://demo.jinyerp.com

# 방화벽에서 80번 포트 열려있는지 확인
sudo ufw status | grep 80

# CloudFlare Proxy 꺼져있는지 확인 (회색 구름)

문제 3: HTTPS는 되는데 HTTP가 리다이렉트 안 돼요

해결 방법:

# Nginx 설정 파일 확인
cat /etc/nginx/sites-available/demo.jinyerp.com

# Certbot이 자동으로 추가한 리다이렉트 확인
# 다음 줄이 있어야 함:
# return 301 https://$server_name$request_uri;

# Nginx 재시작
sudo systemctl reload nginx

문제 4: 502 Bad Gateway 에러

해결 방법:

# PHP-FPM 상태 확인
sudo systemctl status php8.4-fpm

# PHP-FPM 재시작
sudo systemctl restart php8.4-fpm

# Nginx 에러 로그 확인
sudo tail -f /var/log/nginx/demo.jinyerp.com.error.log

# PHP-FPM 소켓 파일 확인
ls -la /var/run/php/php8.4-fpm.sock

문제 5: Mixed Content 경고

브라우저 콘솔에 “Mixed Content” 경고가 나타나요.

해결 방법:

# .env 파일 확인
cat .env | grep APP_URL
# https://로 시작하는지 확인

# Laravel 캐시 재생성
php artisan config:clear
php artisan config:cache

# 하드코딩된 http:// URL 찾기
grep -r "http://" resources/views/

다음 단계

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

이제 여러분의 Laravel 앱이 HTTPS로 안전하게 접속 가능해요! 마지막으로 성능 최적화와 모니터링 방법을 배워봅시다.


← 이전: Laravel 배포 메인으로 다음: 성능 최적화 →