본문 바로가기
프로젝트

영화 추천 시스템 - (3) Docker Compose를 이용하여 React + Django 개발환경 구축하기

by Antraxmin 2024. 12. 16.

https://antraxmin.tistory.com/102

언제 끝나지

이 글을 쓰고 있는 시점에도 TMDB 영화 상세 데이터 수집은 여전히 진행중이다. 7시간 동안 18%이면.. 100% 채우는데 1~2일 더 걸릴 가능성이 커서 적당한 수준에서 타협하고 전처리 로직을 변경하던지 해야 할 것 같다. 

 

이번 포스팅에서는 개발환경에서 Docker Compose를 사용해 리액트 프론트엔드와 장고 백엔드를 동시에 실행하는 방법을 다룰 것이다.

 

Docker Compose 작동 원리 

Docker Compose는 다중 컨테이너 애플리케이션의 정의와 실행을 관리하는 도구로, YAML 파일을 통해 서비스, 네트워크, 볼륨을 선언적으로 구성한다. 개발 환경에서 Docker Compose는 프론트엔드와 백엔드 컨테이너를 독립된 네트워크 공간에서 실행하며, 각 컨테이너의 빌드 프로세스, 환경 변수, 포트 매핑, 볼륨 마운트를 자동화한다. 

docker compose를 사용하여 구성한 로컬 개발환경

프론트엔드 컨테이너(포트 3000)에서는 Node.js 런타임을 기반으로 React 애플리케이션이 실행되며, npm start 명령을 통해 Webpack Dev Server가 구동된다. Webpack Dev Server는 소스 코드를 실시간으로 감시하면서 Babel을 통한 트랜스파일링과 HMR을 수행하여 개발자가 코드를 수정할 때마다 브라우저를 자동으로 갱신한다.

백엔드 컨테이너(포트 8000)에서는 Python 환경에서 Django 개발 서버가 실행되며, WSGI 프로토콜을 통해 웹 서버와 Python 애플리케이션 간의 통신을 표준화한다. HTTP 요청이 들어오면 WSGI 서버가 이를 처리하여 Django의 미들웨어 계층으로 전달하고, URL 라우팅을 거쳐 적절한 뷰 함수가 호출되어 비즈니스 로직을 수행하게 된다.

 

프론트엔드에서 백엔드 API를 호출할 때는 Docker Compose가 생성한 내부 네트워크를 통해 컨테이너 간 통신이 이루어지며, 개발 환경에서는 CORS 설정을 통해 교차 출처 리소스 공유를 허용한다. Docker Compose는 docker-compose.yml 파일의 정의에 따라  모든 컨테이너들의 생명주기를 관리하며, docker-compose up 명령어 하나로 전체 개발 환경을 구성하고 docker-compose down 명령으로 정리할 수 있게 해준다. 

 

프로젝트 세팅 

먼저 프로젝트 루트 디렉토리에 두 개의 폴더(frontend, backend)를 만들어 리액트와 장고 앱을 각각 설정한다. 이러한 모노레포 구조는 프로젝트의 모든 코드를 하나의 저장소에서 관리할 수 있게 해주며, 개발과 배포 프로세스를 단순화할 수 있다는 장점이 있다.

movie-recommendation-system/
├── frontend/               
│   ├── public/            
│   ├── src/                
│   ├── package.json        
│   ├── .gitignore          
│   └── README.md           
├── backend/                
│   ├── movie_recommender/      
│   │   ├── settings.py     
│   │   ├── urls.py    
│   │   ├── asgi.py 
│   │   ├── wsgi.py         
│   │   └── ...          
│   ├── manage.py 
│   ├── requirements.txt   
│   ├── .gitignore          
│   └── README.md           
├── .gitignore              
└── README.md

 

React Dockerfile 설정 

리액트 앱을 컨테이너화하려면 frontend 폴더 안에 Dockerfile을 작성해야 한다. 이 Dockerfile은 리액트 앱을 빌드하고 실행하는 방법을 정의한다. 

FROM node:18

WORKDIR /app

COPY package.json package-lock.json ./

RUN npm install

COPY . .

RUN npm run build

EXPOSE 3000

CMD ["npm", "start"]

 

이 Dockerfile은 개발 환경에 최적화되어 있으며, 핫 리로딩을 지원하여 코드 변경 시 즉시 반영될 수 있도록 설정되어 있다. 프로덕션 환경에서는 멀티스테이지 빌드를 사용하여 최종 이미지 크기를 최적화할 수 있다.

 

 

Django Dockerfile 설정

마찬가지로 장고 백엔드도 Docker 컨테이너로 실행하기 위해 backend 폴더 안에 Dockerfile을 작성한다.

FROM python:3.10

WORKDIR /app

COPY requirements.txt .

RUN pip install -r requirements.txt

COPY . .

EXPOSE 8000

CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]

 

이 Dockerfile은 Python 이미지를 사용하여 장고 애플리케이션을 실행할 수 있는 환경을 정의한다. requirements.txt에서 필요한 패키지를 설치하고, runserver 명령어로 장고 개발 서버를 실행한다. 개발 환경에서는 runserver를 사용하지만 프로덕션 환경에서는 gunicorn과 같은 WSGI 서버를 사용하는 것이 바람직하다.

 

Docker Compose 설정

Docker Compose를 사용하면 여러 컨테이너를 효율적으로 관리할 수 있다. 특히 개발 환경에서 frontend와 backend 서비스를 쉽게 연동할 수 있다는 장점이 있다. 이제 두 애플리케이션을 동시에 실행할 수 있도록 docker-compose.yml 파일을 설정한다. docker-compose.yml은 여러 컨테이너를 함께 실행하고 네트워크를 연결하는 데 사용된다. 

version: '3'

services:
  frontend:
    build: ./frontend
    ports:
      - "3000:3000"  # 리액트 앱의 포트
    volumes:
      - ./frontend:/app  
    networks:
      - my_network

  backend:
    build: ./backend
    ports:
      - "8000:8000"  # 장고 앱의 포트
    volumes:
      - ./backend:/app  
    environment:
      - DJANGO_SETTINGS_MODULE=backend.settings
    networks:
      - my_network

networks:
  my_network:
    driver: bridge

 

이 설정에서는 볼륨 마운트를 통해 로컬 개발 환경의 코드 변경이 컨테이너에 즉시 반영되도록 했으며, 두 서비스가 같은 네트워크에서 통신할 수 있도록 설정했다.

 

Docker Compose로 애플리케이션 실행

이제 모든 설정이 완료되었다. 로컬 환경에서 두 애플리케이션을 동시에 실행하려면 docker-compose 명령어를 입력하면 된다.

docker-compose up --build

 

Docker 컨테이너 로그를 통해 두 애플리케이션이 제대로 실행되고 있는지 확인할 수 있다. 

docker-compose logs frontend  
docker-compose logs backend

리액트, 장고 애플리케이션 각각의 로그 확인
실행 중인 컨테이너 확인 (docker ps)

 

이렇게 Docker Compose를 사용하면 애플리케이션의 배포가 매우 간단해진다. Docker 이미지를 생성하고 docker-compose.yml 파일만 있으면 한 번의 명령어로 여러 서비스가 동시에 실행된다는 것이 장점이다. 

 

아쉽지만 이번 프로젝트에서는 로컬 개발환경 구성에 Docker Compose를 사용하고, 배포 시에는 설계 단계에서 결정한 것과 같이 ECR + ECS + Fargate를 사용하고자 한다. Docker Compose는 로컬 환경에서 리액트와 장고 앱을 간편하게 실행하고 테스트할 수 있지만, 기본적으로 단일 서버에 모든 서비스를 배포하는 방식이기에 EC2 인스턴스 하나에서 운영하기에는 한계가 있다고 판단했다. 

 

반면 ECS + Fargate는 서버리스 컨테이너 서비스로, 인프라 관리 없이도 컨테이너를 손쉽게 확장할 수 있다는 장점이 있다. 특히 트래픽이 증가하거나 감소할 때 자동으로 용량을 조절할 수 있으며 각 서비스를 독립적으로 관리하고 모니터링할 수 있다. ECR은 도커 이미지를 안전하게 저장하고 버전 관리할 수 있게 해주므로, CI/CD 파이프라인 구축에도 용이하다. 결론적으로 개발 단계에서는 Docker Compose의 편리함을 활용하되 프로덕션 환경에서는 더 안정적이고 확장 가능한 AWS 리소스를 활용하는 것이 현재로써 최선의 선택이라고 판단하였다.