Skip to content

[CL] v1 인프라 구성 문서화

Sanghyun Jun edited this page Jun 1, 2025 · 3 revisions

1. GCP 프로젝트 준비

1.1. GCP 프로젝트 생성

  • 새 프로젝트 생성 → 프로젝트 이름: nemo

1.2. IAM(팀원 권한) 세팅

  • 팀원 추가
    • 구성원 추가 → 이메일 입력 → 권한 지정 → 저장
    • 권한 설정
      • 인프라: 소유자
      • 개발팀: 편집자
스크린샷 2025-04-27 오후 7 48 06
  • 💳 GCP 결제 전략: 결제 대표자 권한 중심 운영

    • 하나의 팀원(GCP 계정)을 결제 대표자로 지정
    • 해당 계정의 **GCP 크레딧(무료 또는 프로모션 크레딧)**을 중심으로 프로젝트 운영
    • 한 계정 크레딧 또는 기간 만료시 결제 대표자 변경

    👤 결제 대표자 구성 방식

    역할 계정 (이메일) 설명
    💰 결제 대표자 yourname@gmail.com GCP Billing Account를 보유, 모든 프로젝트의 비용 발생 주체
    👥 프로젝트 담당자 여러 명 GCP IAM 권한으로 프로젝트 접근 및 리소스 생성 가능. 결제는 대표자의 Billing으로 통합됨

1.3. 리전/존/리소스 네이밍 규칙

  1. 리전/존: 서울(asia-northeast3-a)
  2. 명명 규칙: 모든 자원에 prod , dev 태그, 설명, 주석 필요
    • VM 인스턴스
      • 운영: v1-prod-vm
      • 개발: v1-dev-vm
    • Static IP
      • prod-ip , dev-ip
    • 방화벽
      • prod-fw , dev-fw
    • 도메인
      • 운영: nemo.ai.kr / 34.64.57.185
      • 개발: dev.nemo.ai.kr / 34.64.223.96

2. 네트워크/보안 세팅

2.1. VPC 및 서브넷 구조 설계

  1. VPC 생성
    • 좌측 메뉴 → “VPC 네트워크” → “VPC 네트워크 만들기”
    • 이름: v1-nemo-vpc
  2. 서브넷 생성
    1. 퍼블릭 서브넷 (운영 및 개발용)
      • 이름: prod-public-subnet(운영), dev-subnet(개발)
      • 리전: asia-northeast-3
      • IP 스택: IPv4(단일 스택)
      • 기본 IPv4 범위
        • 운영: 10.0.1.0/24
        • 개발: 10.0.3.0/24
      • 나머지 기본값 세팅
    2. 프라이빗 서브넷 (운영 DB용)
      • 이름: prod-private-subnet
      • 리전: asia-northeast-3
      • IP 스택: IPv4(단일 스택)
      • 기본 IPv4 범위: 10.0.2.0/24
      • 나머지 기본값 세팅
스크린샷 2025-04-26 오후 10 29 09

2.2. 방화벽 규칙 확인 및 추가

1. 서비스별 포트 정리

포트 서비스 설명 및 역할
22 SSH 서버 원격 접속 (운영/개발 모두), 필수
80 HTTP 웹 (Next.js, 프론트, 정적 웹 등)
443 HTTPS 보안 웹 (SSL, 운영 환경에서 필수)
3000 Next.js / FE 프론트엔드 개발/운영 (Next.js 기본 포트)
8080 Spring Boot 백엔드 (Spring Boot 기본 포트)
8000 FastAPI / AI AI 서버 (FastAPI, Python 등)
3306 MySQL 관계형 DB (MySQL 기본 포트)
6379 Redis 인메모리 DB / 캐시 (Redis 기본 포트)
5000 ChromaDB 벡터 DB, AI 임베딩용 DB 등

2. 방화벽 규칙 예시

스크린샷 2025-06-01 오후 2 09 14 (1)
항목 운영 서버 운영 DB 서버 개발 서버
이름 nemo-vpc-allow-app nemo-vpc-allow-db v1-nemo-vpc-allow-dev
설명 운영 앱 서버 포트 오픈 운영 DB 내부 접근 허용 개발 인스턴스 포트 오픈
네트워크 nemo-vpc nemo-vpc nemo-vpc
우선순위 1000 1000 1000
트래픽 방향 인그레스 인그레스 인그레스
일치 시 작업 허용 허용 허용
대상 지정된 대상 태그 지정된 대상 태그 지정된 대상 태그
대상 태그 prod-app prod-db dev
소스 필터 IPv4 범위 IPv4 범위 IPv4 범위
소스 IP 0.0.0.0/0 10.0.1.0/24 (Bastion) 0.0.0.0/0
포트/프로토콜 TCP: 22,80,443,3000,8080,5000 TCP: 3306,6379,8000,22 TCP: 22,80,3000,8080,5000,3306,6379,8000

운영 DB 서버의 소스 IPv4 범위가 10.0.1.0/24로 고정된 이유는?

  • 운영 DB 서버는 프라이빗 서브넷에 위치하며 외부에서 직접 접근할 수 없습니다.
  • 따라서 유일한 진입점인 **Bastion Host(10.0.1.0/24 대역)**에서만 접근을 허용해야 하므로 보안을 위해 범위 제한이 필요합니다.

2.3. Static IP 예약

  1. 목적

    : 도메인 연결, 외부 서비스 연동, SSH 접속 주소 고정 등 VM의 퍼블릭 IP가 변하지 않게 하기 위해서 Static IP 예약 필요

  2. 실무 플로우

    1. 네트워크/VPC/방화벽 규칙 생성
    2. Static IP 예약 → 나중에 VM 인스턴스에 할당
    3. VM 인스턴스 생성 → 생성 시 예약한 IP 붙임
    4. 나중에 도메인/SSL/외부 연동 작업에도 해당 고정 IP를 사용하면 됨
  3. IP 예약 순서: VPC 네트워크 → IP 주소 → 외부 고정 IP 주소 예약

    • 이름: prod-ip : 34.64.57.185
    • 이름: dev-ip : 34.64.223.96
    • 리전: asia-northeast3 (서울)
  4. 가이드

    • 운영/개발 VM에 붙어 있는 Static IP는 무료

    • VM이 없는데 Static IP만 남아 있으면 1개당 한 달 약 4,000원씩 과금

    • 장기 방치만 피하면 부담 없음

    • Static IP 주소를 만들때 무조건 “공유”는 안함으로 해야합니다.

      🚫 언제 공유하지 말아야 하는가?

      • VM 인스턴스 하나에만 독점적으로 쓰고 싶을 때 (예: Bastion, 단독 NAT용 등)
      • ssh, 고정 도메인 연결 등으로 명확한 1:1 매핑이 필요한 경우

3. Compute Engine(VM) 인스턴스 생성

  • 머신 타입/영역/OS(예: Ubuntu 20.04) 선택
  • SSH 키/계정 세팅

3.1. 인스턴스 스펙 선정

항목 운영용(prod-vm) 운영 DB(prod-db-vm) 개발용(dev-vm) Bastion Host (bastion-host) 근거
이름 prod-vm prod-db-vm v1-dev-vm v1-bastion-host 역할 구분 명확하게
리전/존 asia-northeast3-a asia-northeast3-a asia-northeast3-a asia-northeast3-a 서울 리전, 하나의 존에서 관리
머신 타입 e2-standard-2 (vCPU 2개, 메모리 8GB) e2-custom-2-4096 (vCPU 2개, 메모리 4GB) n2-custom-4-8192 (vCPU 4개, 메모리 8GB) e2-small(2vCPU 2GB) 가성비 기준으로 안정적
디스크 Ubuntu 22.04 LTSBalanced 30GB Ubuntu 22.04 LTSBalanced 50GB Ubuntu 22.04 LTSBalanced 50GB Ubuntu 22.04 LTSBalanced 20GB 범용성/안정성/성능 고려
가동 시간 730시간(24시간 × 30일) 730시간(24시간 × 30일) 510시간(하루 17시간 × 30일) 510시간(하루 17시간 × 30일) 개발 서버는 부분 가동
외부 IP Static IP 내부 IP Only Static IP Static IP 보안 원칙에 따라 DB는 비공개
서브넷 prod-public-subnet prod-private-subnet dev-subnet prod-public-subnet 네트워크 분리로 보안 강화
방화벽 설정 HTTP/HTTPS 허용 없음 HTTP/HTTPS 허용 HTTP/HTTPS 허용 서비스별 접근 통제

https://cloud.google.com/products/calculator?dl=CjhDaVF4TWpRNE5XRTNPQzFoWkdKbUxUUTVORFF0T1Rjek1TMWtOVGsyTmpVNU1HTXhPV1FRQVE9PRAIGiQzQzJGREFBNS04QUM5LTQzREEtQjM1MC0zMjY1Q0NBMTNEOEI&hl=ko

💻 버전 1 기준 200,000원 예상 but 추후 부하테스트 이후 변동 가능성 존재

3.2. Bastion Host 운영 전략

  1. 도입 배경
    • GCP의 보안 원칙상 프라이빗 서브넷에 위치한 VM 인스턴스 는 외부 IP가 없어 직접 SSH 접속 불가
    • 보안을 유지하면서도 내부 리소스에 접근할 수 있는 "중간 관문" 역할이 필요
    • VPN은 장기적 대안이 될 수 있지만, 단기적으로는 인스턴스만 설정하면 된다는 간편함과 높은 안전성을 고려하여 Bastion Host가 유리하다고 판단하였습니다.
  2. 운영 목적
목적 설명
SSH 터널링 프라이빗 인스턴스에 SSH 접속 시 중간 서버 역할
접근 제어 외부에서 오직 Bastion Host만 접근 허용 (방화벽 22번 포트 제한)
보안 강화 데이터베이스, 내부 서버 등의 직접적인 외부 노출 방지
  1. 구성 원칙
  • 위치: 퍼블릭 서브넷 (prod-public-subnet)
  • 외부 IP: Static IP 부여 (SSH 고정 접속 주소 확보)
  • 머신 타입: e2-small (저사양, 저비용으로 충분)
  • 방화벽: 22 포트만 열고, 특정 IP 혹은 팀원만 접근 가능하도록 제한
  • 태그: bastion (방화벽 규칙에 활용)
  1. 보안 고려사항
  • 반드시 SSH 공개키 기반 인증 사용 (패스워드 로그인 비활성화)

❗️ 🔐 SSH키는 왜 Bastion에는 자동 등록되고, DB VM엔 안 되나?

  • GCP는 외부 IP가 있는 VM에만 자동 SSH 키 등록을 해주지만 프라이빗 IP만 있는 VM은 자동 키 등록 대상이 아니므로 수동 등록 필수

    onurivit01@v1-bastion-host:~$ ssh-keygen -t rsa -f ~/.ssh/id_rsa -C "ubuntu"
    Generating public/private rsa key pair.
    /home/onurivit01/.ssh/id_rsa already exists.
    Overwrite (y/n)? y
    Enter passphrase (empty for no passphrase): 
    Enter same passphrase again: 
    Your identification has been saved in /home/onurivit01/.ssh/id_rsa
    Your public key has been saved in /home/onurivit01/.ssh/id_rsa.pub
    The key fingerprint is:
    SHA256:r7cb6LpYOWbpofZTyd2atOzvtr4UZfrFRNWSL5ariiw ubuntu
    The key's randomart image is:
    +---[RSA 3072]----+
    |               .=|
    |              o..|
    |              o+.|
    |             ++o.|
    |       .So .o. oo|
    |       o+oo .o.. |
    |      O..oo+...  |
    |    .BE= o*oo    |
    |   .o.===o=O*o   |
    +----[SHA256]-----+
    onurivit01@v1-bastion-host:~$ cat ~/.ssh/id_rsa.pub

4. VM 인스턴스 최초 접속 및 환경 준비

4.1. 각 서비스별 버전 확인 필요

  • FE: node --version , npm --version
  • BE: java -version , Spring Boot 버전 build.gradle , MySQL
  • AI: 추후 요청

4.2. 최초 세팅 스크립트

  1. prod-vm (FE/BE/AI 실행 환경 + Nginx)

    ### 1. 시스템 패키지 업데이트
    sudo apt update && sudo apt upgrade -y
    sudo apt install net-tools # 네트워크 관련 설치
    
    ### 2. Node.js 22.14.0 + pnpm
    curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
    source ~/.bashrc
    nvm install 22.14.0
    nvm use 22.14.0
    nvm alias default 22.14.0
    node -v # 22.14.0
    node -v # 10.9.2
    
    # pnpm 설치
    npm install -g pnpm@10.10.0
    pnpm setup
    source ~/.bashrc
    pnpm -v # 10.10.0
    nvm alias # 22.14.0
    
    ### 3. Java 21.0.5
    wget https://download.oracle.com/java/21/archive/jdk-21.0.5_linux-x64_bin.deb
    sudo apt install ./jdk-21.0.5_linux-x64_bin.deb
    echo 'export JAVA_HOME=/usr/lib/jvm/jdk-21.0.5' | sudo tee -a /etc/profile
    echo 'export PATH=$JAVA_HOME/bin:$PATH' | sudo tee -a /etc/profile
    source /etc/profile
    
    ### 4. Python 3.13.3
    sudo apt install -y build-essential libssl-dev zlib1g-dev libncurses5-dev \
    libreadline-dev libsqlite3-dev libgdbm-dev libbz2-dev libexpat1-dev \
    liblzma-dev tk-dev uuid-dev wget
    
    cd /usr/src
    sudo wget https://www.python.org/ftp/python/3.13.3/Python-3.13.3.tgz
    sudo tar xzf Python-3.13.3.tgz
    cd Python-3.13.3
    sudo ./configure --enable-optimizations
    sudo make -j$(nproc)
    sudo make altinstall
    
    python3.13 --version
    python3.13 -m ensurepip
    python3.13 -m pip install --upgrade pip==25.1
    
    ### 5. NGINX 설치
    sudo apt install -y nginx
    sudo systemctl enable nginx
    sudo systemctl start nginx
    nginx -v
    
    ### 6. PM2 설치 및 설정
    pnpm install -g pm2
    pm2 startup
  2. prod-db-vm (MySQL)

    • Bastion에서 .deb 파일 5개를 다운로드
    • DB 는 외부 Internet Gateway와의 연결이 없으므로 Bastion Host에서 다운로 드 후, scp 또는 gcloud compute scp로 프라이빗 DB VM에 복사
    • DB VM에서 sudo dpkg -i로 설치
    onurivit01@v1-bastion-host:~$ scp mysql-*.deb ubuntu@10.0.2.2:/home/ubuntu/
    mysql-common_8.0.36-1ubuntu22.04_amd64.deb                 100%   66KB  28.6MB/s   00:00    
    mysql-community-client-core_8.0.36-1ubuntu22.04_amd64.deb  100% 2076KB  60.9MB/s   00:00    
    mysql-community-client_8.0.36-1ubuntu22.04_amd64.deb       100% 2147KB  48.0MB/s   00:00    
    mysql-community-server-core_8.0.36-1ubuntu22.04_amd64.deb  100%   24MB  71.4MB/s   00:00    
    mysql-community-server_8.0.36-1ubuntu22.04_amd64.deb       100%   77KB  71.4MB/s   00:00    
    onurivit01@v1-bastion-host:~$ ssh ubuntu@10.0.2.2
    Welcome to Ubuntu 22.04.5 LTS (GNU/Linux 6.8.0-1029-gcp x86_64)
    
     * Documentation:  https://help.ubuntu.com
     * Management:     https://landscape.canonical.com
     * Support:        https://ubuntu.com/pro
    
    This system has been minimized by removing packages and content that are
    not required on a system that users do not log into.
    
    To restore this content, you can run the 'unminimize' command.
    
    Expanded Security Maintenance for Applications is not enabled.
    
    0 updates can be applied immediately.
    
    Enable ESM Apps to receive additional future security updates.
    See https://ubuntu.com/esm or run: sudo pro status
    
    The list of available updates is more than a week old.
    To check for new updates run: sudo apt update
    Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings
    
    Last login: Sun May 11 08:24:13 2025 from 10.0.1.3
    ubuntu@v1-prod-db-vm:~$ cd /home/ubuntu
    ubuntu@v1-prod-db-vm:~$ ls -al
    total 28700
    -rw-rw-r-- 1 ubuntu ubuntu    67862 May 11 08:35 mysql-common_8.0.36-1ubuntu22.04_amd64.deb
    -rw-rw-r-- 1 ubuntu ubuntu  2126260 May 11 08:35 mysql-community-client-core_8.0.36-1ubuntu22.04_amd64.deb
    -rw-rw-r-- 1 ubuntu ubuntu  2198886 May 11 08:35 mysql-community-client_8.0.36-1ubuntu22.04_amd64.deb
    -rw-rw-r-- 1 ubuntu ubuntu 24872128 May 11 08:35 mysql-community-server-core_8.0.36-1ubuntu22.04_amd64.deb
    -rw-rw-r-- 1 ubuntu ubuntu    78368 May 11 08:35 mysql-community-server_8.0.36-1ubuntu22.04_amd64.deb
    
    # MySQL 시작
    sudo systemctl start mysql
    sudo systemctl enable mysql
    mysql --version
    
    ### 5.1 MySQL 기본 설정
    # 1. root 비밀번호 설정
    sudo mysql <<EOF
    ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'nemo1234!';
    FLUSH PRIVILEGES;
    EOF
    
    ###2. prod db 생성 
    sudo mysql -u root -p'nemo1234!' <<EOF
    CREATE DATABASE proddb;
    CREATE USER 'prod'@'10.0.1.%' IDENTIFIED BY 'Prod1234!';
    GRANT ALL PRIVILEGES ON proddb.* TO 'prod'@'10.0.1.%';
    FLUSH PRIVILEGES;
    EOF
    
  3. dev-vm (모든 서비스)

    ### 1. 시스템 패키지 업데이트
    sudo apt update && sudo apt upgrade -y
    sudo apt install net-tools # 네트워크 관련 설치
    
    ### 2. Node.js 22.14.0 + pnpm
    curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
    source ~/.bashrc
    nvm install 22.14.0
    nvm use 22.14.0
    nvm alias default 22.14.0
    node -v # 22.14.0
    node -v # 10.9.2
    
    # pnpm 설치
    npm install -g pnpm@10.10.0
    pnpm setup
    source ~/.bashrc
    pnpm -v # 10.10.0
    nvm alias # 22.14.0
    
    ### 3. Java 21.0.5
    wget https://download.oracle.com/java/21/archive/jdk-21.0.5_linux-x64_bin.deb
    sudo apt install ./jdk-21.0.5_linux-x64_bin.deb
    echo 'export JAVA_HOME=/usr/lib/jvm/jdk-21.0.5' | sudo tee -a /etc/profile
    echo 'export PATH=$JAVA_HOME/bin:$PATH' | sudo tee -a /etc/profile
    source /etc/profile
    
    ### 4. Python 3.13.3
    sudo apt install -y build-essential libssl-dev zlib1g-dev libncurses5-dev \
    libreadline-dev libsqlite3-dev libgdbm-dev libbz2-dev libexpat1-dev \
    liblzma-dev tk-dev uuid-dev wget
    
    cd /usr/src
    sudo wget https://www.python.org/ftp/python/3.13.3/Python-3.13.3.tgz
    sudo tar xzf Python-3.13.3.tgz
    cd Python-3.13.3
    sudo ./configure --enable-optimizations
    sudo make -j$(nproc)
    sudo make altinstall
    
    python3.13 --version
    python3.13 -m ensurepip
    python3.13 -m pip install --upgrade pip==25.1
    
    ### 5. MySQL 8.0.36 설치
    # .deb 파일 다운로드
    wget https://downloads.mysql.com/archives/get/p/23/file/mysql-common_8.0.36-1ubuntu22.04_amd64.deb
    wget https://downloads.mysql.com/archives/get/p/23/file/mysql-community-client-core_8.0.36-1ubuntu22.04_amd64.deb
    wget https://downloads.mysql.com/archives/get/p/23/file/mysql-community-client_8.0.36-1ubuntu22.04_amd64.deb
    wget https://downloads.mysql.com/archives/get/p/23/file/mysql-community-server-core_8.0.36-1ubuntu22.04_amd64.deb
    wget https://downloads.mysql.com/archives/get/p/23/file/mysql-community-server_8.0.36-1ubuntu22.04_amd64.deb
    
    # 설치
    sudo dpkg -i mysql-common_8.0.36-1ubuntu22.04_amd64.deb
    sudo dpkg -i mysql-community-client-core_8.0.36-1ubuntu22.04_amd64.deb
    sudo dpkg -i mysql-community-client_8.0.36-1ubuntu22.04_amd64.deb
    sudo dpkg -i mysql-community-server-core_8.0.36-1ubuntu22.04_amd64.deb
    sudo dpkg -i mysql-community-server_8.0.36-1ubuntu22.04_amd64.deb
    
    # MySQL 시작
    sudo systemctl start mysql
    sudo systemctl enable mysql
    mysql --version
    
    ### 5.1 MySQL 기본 설정
    # 1. root 비밀번호 설정
    sudo mysql <<EOF
    ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'nemo1234!';
    FLUSH PRIVILEGES;
    EOF
    
    # 2. 사용자 및 devdb 생성
    sudo mysql -u root -p nemo1234! <<EOF
    CREATE DATABASE devdb;
    CREATE USER 'dev'@'%' IDENTIFIED BY 'Dev1234!';
    GRANT ALL PRIVILEGES ON devdb.* TO 'dev'@'%';
    FLUSH PRIVILEGES;
    EOF
    
    mysql -u root -p
    mysql -u dev -p -h 34.64.57.185
    
    sudo systemctl status mysql
    
    # (선택) 외부에서 접속하려면 bind-address 수정 및 포트 오픈 필요
    
    ### 6. .env 설정 예시 (Spring, Node 등)
    # 내부용
    DB_URL=jdbc:mysql://127.0.0.1:3306/devdb
    # 외부용
    DB_URL=jdbc:mysql://<서버IP>:3306/devdb
    DB_USER=dev
    DB_PASSWORD=Dev1234!
    
    ### 7. NGINX 설치
    sudo apt install -y nginx
    sudo systemctl enable nginx
    sudo systemctl start nginx
    nginx -v
    
    ### 8. PM2 설치 및 설정
    pnpm install -g pm2
    pm2 startup

5. 🌐 NGINX Reverse Proxy 구성 (nemo.ai.kr/dev.nemo.ai.kr)

sudo vi /etc/nginx/sites-available/default # 설정 파일 열기
sudo nginx -t # 문법 검사
sudo systemctl restart nginx # 다시 시작
sudo nginx -s reload # 🔄 설정 반영
server {
    server_name dev.nemo.ai.kr;

    client_max_body_size 10M;

    location ~ /\.env {
        deny all;
        return 404;
    }

    location /auth/ {
        proxy_pass http://localhost:8080;
        proxy_http_version 1.1;
        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;
    }

    # 1. API는 백엔드(Spring Boot)로
    location /api/ {
        proxy_pass http://localhost:8080;
        proxy_http_version 1.1;
        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;
    }

    # Swagger
    location /swagger-ui/ {
        proxy_pass http://localhost:8080/swagger-ui/; 
        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;
    }

    location /v3/ {
        proxy_pass http://localhost:8080/v3/;
        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;
    }

    location /swagger-resources/ {
        proxy_pass http://localhost:8080/swagger-resources/;
        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;
    }

    # 2. AI API는 FastAPI로
    location /ai/ {
        proxy_pass http://localhost:8000;
        proxy_http_version 1.1;
        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;
    }

    # 정적 파일 (Next.js 빌드 결과) 처리
    location ~ ^/_next/ {
        proxy_pass http://localhost:3000;
        proxy_http_version 1.1;
        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;
    }

    # 3. 그 외(모든 경로)는 SSR 서버(Next.js 3000)로
    location / {
        proxy_pass http://localhost:3000;
        proxy_http_version 1.1;
        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;
    }

    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/dev.nemo.ai.kr/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/dev.nemo.ai.kr/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

}

server {
    if ($host = dev.nemo.ai.kr) {
        return 301 https://$host$request_uri;
    } # managed by Certbot

    server_name dev.nemo.ai.kr;
    listen 80;
    return 404; # managed by Certbot
}

5-2. 세부 분기 사항

경로 패턴 서비스 내부 포트 설명
/api/, /auth/, /swagger-ui/, /v3/, /swagger-resources/ 백엔드(Spring Boot) 8080 REST API 및 Swagger 문서 라우팅
/ai/ AI 서버(FastAPI) 8000 AI 서비스 라우팅
/_next/, / 프론트엔드(Next.js SSR) 3000 정적 리소스 및 SSR 처리
/\.env - - 보안상 차단 처리
443, 80 HTTPS 및 HTTP - SSL 인증서 관리 및 리디렉션
  • 도메인 nemo.ai.kr에 접근한 클라이언트 요청을 내부 서비스로 분기
  • 백엔드(Spring Boot), AI 서비스(FastAPI), 프론트엔드(Next.js)를 각기 다른 포트에서 처리
  • Let’s Encrypt 기반 HTTPS 적용 및 SSL 인증서 관리

5-3. 보안 설정

  • .env 파일 접근 차단:

    location ~ /\.env {
        deny all;
        return 404;
    }
    
  • 클라이언트 파일 업로드 크기 제한:

    client_max_body_size 10M;
    
  • Reverse proxy 헤더 설정

    모든 proxy_pass 블록에 공통적으로 다음 헤더로 설정 → 클라이언트 IP와 원래 요청 정보를 내부 서버가 인식하도록 함.

    proxy_http_version 1.1;
    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;
    

5-4. SSL 설정 (Let’s Encrypt + Certbot)

  • 443 포트에서 HTTPS 처리
  • Certbot 자동화로 관리되는 경로 사용:
ssl_certificate /etc/letsencrypt/live/dev.nemo.ai.kr/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/dev.nemo.ai.kr/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

5-5. 🌐 HTTP → HTTPS 리디렉션

server {
    if ($host = dev.nemo.ai.kr) {
        return 301 https://$host$request_uri;
    }

    server_name dev.nemo.ai.kr;
    listen 80;
    return 404;
}

Clone this wiki locally