ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Study-Mate] HTTPS로 전환하기
    NextJS 2026. 4. 5. 21:50

     

     

    1. 왜 HTTPS가 필요한가

    • TLS(SSL)인증으로 인한 보안성 증가
    • 암호화/복호화 비용이 발생하지만 비싸지 않고, HTTP2의 멀티플렉싱과 헤더압축으로 HTTP와 비슷하거나 더 빠른 속도 보장
    • 신뢰성 증가로 인한 구글 랭킹 증가와 Lighthouse SEO 점수 증가 

    2. 사전 준비

    • 배포 서버(기존에 AWS EC2에 배포한 서버 + docker compose 컨테이너 기반(프로젝트,nginx포함) 배포)
    • 도메인(기존에 가지고 있던 GoDaddy 도메인 준비)
    • 배포 서버에 Node.js 설치
      Node.js를 설치 방법으로 크게 apt, nodesource, nvm 방식이 있다는 것을 알았다.
      apt는 최신 노드버전을 쓰지 못하기 때문에 제외했고 추후 Git Actions로 배포자동화를 할 때를 대비하여 전역 환경변수로 node를 설치는 nodesource 방식으로 설치를 진행하였다.(nvm은 로컬 환경변수 설치)
      더보기
      curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
      sudo apt install -y nodejs

    3. SSL 인증서 발급

    • HTTPS로 전환하기 위해 인증서 발급을 진행하였다.

    # certbot 설치
    sudo apt install certbot -y
    
    # 인증서 발급 (standalone 모드 - nginx 잠깐 내려야 함)
    sudo docker compose down
    sudo certbot certonly --standalone -d w-neocode.com
    
    # 발급 확인
    sudo ls /etc/letsencrypt/live/w-neocode.com/
    • 가장 일반적인 방법은 웹 서버 플러그인을 사용한 방법
      - sudo certbot --nginx : 기본 자동 설정 -> 나는 docker 컨테이너로 nginx 설정을 포함하여 배포하였기 때문에 standalone 방식으로 수동으로 인증을 진행하였다.
    • 웹 서버 플러그인 없이 수동으로 발급 방법
      1) webroot
      2) standalon
      3) dns challange
    • 참고

    4. 설정 파일 변경

    • nginx/default.conf 수정 ( 도메인명 + HTTPS 설정 추가 )
    server {
        listen 80;
        server_name w-neocode.com;
    
        # HTTP → HTTPS 리다이렉트
        return 301 https://$host$request_uri;
    }
    
    server {
        listen 443 ssl;
        server_name w-neocode.com;
    
        ssl_certificate /etc/letsencrypt/live/w-neocode.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/w-neocode.com/privkey.pem;
    
        client_max_body_size 10M;
    
        location / {
            proxy_pass http://app:3000;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection 'upgrade';
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_cache_bypass $http_upgrade;
    
            proxy_connect_timeout 60s;
            proxy_send_timeout 60s;
            proxy_read_timeout 60s;
        }
    
        location /_next/static {
            proxy_pass http://app:3000;
            proxy_http_version 1.1;
            proxy_set_header Host $host;
            add_header Cache-Control "public, max-age=31536000, immutable";
        }
    }

     

    • docker-compose.yml 수정 ( 443 포트 + 인증서 볼륨 추가 )
    services:
        app:
            build:
                context: .
                dockerfile: Dockerfile
                args:
                    NEXT_PUBLIC_SUPABASE_URL: ${NEXT_PUBLIC_SUPABASE_URL}
                    NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY: ${NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY}
                    NEXT_PUBLIC_STORAGE_BUCKET_POST: ${NEXT_PUBLIC_STORAGE_BUCKET_POST}
                    NEXT_PUBLIC_STORAGE_BUCKET_PROFILE: ${NEXT_PUBLIC_STORAGE_BUCKET_PROFILE}
            container_name: study-mate-app
            restart: unless-stopped
            env_file: .env
            environment:
                - NODE_ENV=production
    
        nginx:
            image: nginx:alpine
            container_name: study-mate-nginx
            ports:
                - '80:80'
                - '443:443'
            volumes:
                - ./nginx/default.conf:/etc/nginx/conf.d/default.conf
                - /etc/letsencrypt:/etc/letsencrypt:ro
            depends_on:
                - app
            restart: unless-stopped

    5. 결과

Designed by Tistory.