카테고리 없음

🐳 Docker & Nginx로 React + FastAPI 풀스택 환경 한방에 구축하기 (Feat. 트러블슈팅)

일찍자기 2025. 11. 21. 17:29

오늘은 React(Frontend), FastAPI(Backend), 그리고 **DB(PostgreSQL, Elasticsearch)**까지 복잡한 풀스택 환경을 DockerNginx를 이용해 깔끔하게 정리하는 방법을 소개합니다.

특히, 정적 파일 서빙 시 발생하는 500 Error 해결법과 실제 주식 분석 대시보드(StockPulse) 구축 사례를 통해 실무 적용 팁까지 알려드릴게요!


1. 아키텍처 구조 잡기

우리가 만들 구조는 다음과 같습니다. 모든 서비스는 my_network라는 도커 네트워크 안에서 서로 통신합니다.

  • Frontend: React (Node.js로 빌드 -> Nginx로 서빙)
  • Backend: FastAPI
  • Database: PostgreSQL, Elasticsearch

2. Dockerfile: React 빌드와 Nginx 서빙을 동시에! (Multi-stage Build)

가장 중요한 프론트엔드 설정입니다. 단순히 Node.js 컨테이너를 띄우는 게 아니라, 빌드(Build) 단계와 실행(Run) 단계를 나누는 것이 핵심입니다. 이렇게 하면 이미지 용량을 획기적으로 줄일 수 있습니다.

📄 Frontend Dockerfile 예시

Dockerfile
 
# 1단계: Builder (Node.js 환경)
FROM node:18-alpine AS builder
WORKDIR /app

# pnpm 설치 및 의존성 설치
RUN npm install -g pnpm
COPY package.json pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile

# 소스 코드 복사 및 빌드
COPY . .
RUN pnpm build

# 2단계: Runner (Nginx 환경)
FROM nginx:alpine

# Nginx 설정 파일 덮어쓰기 (커스텀 설정 필요 시)
COPY nginx.conf /etc/nginx/conf.d/default.conf

# 1단계에서 빌드된 결과물(dist)을 Nginx의 서빙 디렉토리로 복사
COPY --from=builder /app/dist /usr/share/nginx/html

# 권한 설정 (매우 중요! ★★★)
# Nginx가 파일에 접근할 수 있도록 권한을 부여해야 500 에러를 방지함
RUN chmod -R 755 /usr/share/nginx/html

EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

💡 핵심 포인트: COPY --from=builder를 사용해 빌드된 정적 파일만 쏙 빼와서 Nginx로 옮겼습니다. 이것이 가볍고 빠른 컨테이너의 비결입니다.


3. Docker Compose: 모든 서비스를 한 곳에서 (Orchestration)

이제 docker-compose.yml을 통해 DB, 백엔드, 프론트엔드를 하나로 묶습니다.

📄 docker-compose.yml 예시

YAML
 
version: '3.8'

services:
  # 1. 데이터베이스 (PostgreSQL)
  db:
    image: postgres:15
    environment:
      POSTGRES_USER: user
      POSTGRES_PASSWORD: password
      POSTGRES_DB: stock_db
    networks:
      - my_network

  # 2. 검색 엔진 (Elasticsearch)
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:8.11.1
    environment:
      - discovery.type=single-node
    networks:
      - my_network

  # 3. 백엔드 (FastAPI)
  backend:
    build: ./backend
    ports:
      - "8000:8000"
    depends_on:
      - db
      - elasticsearch
    networks:
      - my_network

  # 4. 프론트엔드 (React + Nginx)
  frontend:
    build: ./frontend
    ports:
      - "80:80" # 호스트 80포트를 컨테이너 80포트(Nginx)로 연결
    depends_on:
      - backend
    networks:
      - my_network

networks:
  my_network:
    driver: bridge

4. 🚨 트러블슈팅: 이것만 알면 에러 탈출!

대화 내용에서 발생했던 주요 에러와 해결책을 정리했습니다.

❌ 상황 1: Nginx 500 Internal Server Error

  • 증상: 배포 후 페이지 접속 시 ERR_FAILED 500 발생.
  • 원인: Nginx가 /usr/share/nginx/html 내부의 파일을 읽으려는데 권한이 없을 때 발생합니다.
  • ✅ 해결: Dockerfile 내부에 권한 부여 명령어 추가.또한, Nginx 설정 파일(nginx.conf)에서 로그 경로가 올바른지, root 경로가 정확히 dist 파일들이 있는 곳을 가리키는지 확인해야 합니다.
  • Dockerfile
     
    RUN chmod -R 755 /usr/share/nginx/html
    

❌ 상황 2: Service 'frontend' failed to build

  • 증상: docker-compose up 실행 시 빌드 실패.
  • 원인: 주로 pnpm install 과정에서 네트워크 이슈나 package.json 경로 문제, 혹은 백엔드 서비스가 아직 준비되지 않았는데 연결을 시도할 때 발생합니다.
  • ✅ 해결:
    1. Docker Compose의 depends_on을 확인하여 실행 순서 보장.
    2. 로컬의 node_modules가 컨테이너로 복사되지 않도록 .dockerignore 파일 설정 필수.