튜토리얼

Docker Compose 로컬 개발 환경 구축: 데이터베이스, 백엔드, 프론트엔드 통합 완벽 가이드

강코의 코딩 일기 2026. 4. 6. 13:28

Docker Compose를 활용하여 데이터베이스, 백엔드, 프론트엔드 통합 로컬 개발 환경을 효율적으로 구축하는 방법을 상세히 안내합니다. 풀스택 개발 생산성 향상을 위한 필수 가이드.

Docker Compose를 활용한 로컬 개발 환경 구축: 데이터베이스, 백엔드, 프론트엔드 통합 가이드 - money, profit, finance, business, return, yield, financial, cash, currency, investment, banking, wealth, coin, economy, success, loan, salary, rich, credit, payment, savings, save, deposit, growth, income

Image by nattanan23 on Pixabay

로컬 개발 환경의 복잡성 해결: Docker Compose의 필요성

소프트웨어 개발 과정에서 로컬 개발 환경 설정은 종종 예상치 못한 난관에 부딪히는 지점이 됩니다. 운영체제마다 다른 의존성 관리 방식, 특정 라이브러리 버전 충돌, 그리고 팀원 간의 환경 불일치는 개발 생산성을 저해하는 주요 원인으로 작용합니다. 데이터베이스, 백엔드 서버, 프론트엔드 애플리케이션 등 여러 컴포넌트로 구성된 풀스택 개발 환경에서는 이러한 복잡성이 더욱 증대됩니다. 각 컴포넌트를 개별적으로 설치하고 구성하는 작업은 시간 소모적이며 오류 발생 가능성이 높습니다. 이러한 문제에 직면했을 때, 개발자는 어떻게 하면 일관되고 효율적인 개발 환경을 구축할 수 있을까요?

이러한 문제에 대한 강력한 해결책으로 Docker Compose가 부상하고 있습니다. Docker Compose는 여러 개의 도커 컨테이너를 단일 명령으로 정의하고 실행할 수 있도록 지원하는 도구입니다. 이를 통해 개발자는 복잡한 애플리케이션 스택을 코드 형태로 정의하고, 언제 어디서든 동일한 환경을 재현할 수 있게 됩니다. 즉, '내 컴퓨터에서는 잘 되는데...'와 같은 상황을 미연에 방지하고, 팀 전체의 개발 생산성을 혁신적으로 향상시킬 수 있습니다. 본 가이드에서는 Docker Compose를 활용하여 데이터베이스, 백엔드, 프론트엔드를 통합하는 로컬 개발 환경을 구축하는 방법을 상세히 다룹니다.

Docker Compose 기본 개념과 핵심 요소 이해

Docker Compose는 기본적으로 docker-compose.yml이라는 YAML 파일을 통해 애플리케이션의 서비스들을 구성합니다. 이 파일은 각 서비스에 대한 도커 이미지, 환경 변수, 포트 매핑, 볼륨 마운트, 네트워크 설정 등을 선언적으로 정의합니다. Docker Compose는 이 정의 파일을 기반으로 필요한 컨테이너들을 생성하고 연결하여 하나의 통합된 애플리케이션으로 동작하도록 합니다.

docker-compose.yml 파일의 주요 구성 요소

  • services: 애플리케이션을 구성하는 각 컴포넌트(예: 데이터베이스, 백엔드 API, 프론트엔드 웹 서버)를 정의합니다. 각 서비스는 독립적인 컨테이너로 실행됩니다.
  • networks: 컨테이너 간의 통신을 위한 네트워크를 정의합니다. Docker Compose는 기본적으로 하나의 브릿지 네트워크를 생성하지만, 필요에 따라 사용자 정의 네트워크를 구성할 수 있습니다.
  • volumes: 컨테이너의 데이터를 호스트 머신에 영구적으로 저장하기 위한 볼륨을 정의합니다. 이는 컨테이너가 삭제되더라도 데이터가 보존될 수 있도록 합니다.

Docker Compose의 핵심 명령어는 다음과 같습니다.

docker-compose up    # 백그라운드에서 모든 서비스 컨테이너 실행 및 로그 출력
docker-compose up -d # 백그라운드에서 모든 서비스 컨테이너 실행 (detached mode)
docker-compose down  # 모든 서비스 컨테이너 중지 및 제거
docker-compose build # Dockerfile을 사용하여 서비스 이미지 빌드
docker-compose ps    # 현재 실행 중인 서비스 컨테이너 목록 확인

이러한 명령어를 통해 개발자는 복잡한 멀티 컨테이너 애플리케이션을 단 몇 줄의 명령으로 손쉽게 관리할 수 있습니다. 이는 개발 환경 설정 및 유지 보수 비용을 크게 절감하는 효과를 가져옵니다.

데이터베이스 서비스 구축: MySQL/PostgreSQL 예시

로컬 개발 환경에서 데이터베이스는 백엔드 애플리케이션의 핵심 의존성입니다. Docker Compose를 사용하면 데이터베이스를 호스트 시스템에 직접 설치할 필요 없이, 격리된 컨테이너 환경에서 손쉽게 구동할 수 있습니다. 여기서는 널리 사용되는 MySQL과 PostgreSQL을 예시로 들어 설명합니다.

MySQL 데이터베이스 서비스 설정

다음은 docker-compose.yml 파일에 MySQL 데이터베이스를 추가하는 예시입니다.

version: '3.8'

services:
  mysql:
    image: mysql:8.0 # MySQL 8.0 버전을 사용합니다.
    environment:
      MYSQL_ROOT_PASSWORD: root_password # root 사용자 비밀번호 설정
      MYSQL_DATABASE: my_database       # 생성할 데이터베이스 이름
      MYSQL_USER: user                  # 생성할 사용자 이름
      MYSQL_PASSWORD: password          # 생성할 사용자 비밀번호
    ports:
      - "3306:3306" # 호스트의 3306 포트를 컨테이너의 3306 포트에 연결합니다.
    volumes:
      - mysql_data:/var/lib/mysql # 데이터 지속성을 위한 볼륨 마운트
    healthcheck: # 데이터베이스 준비 상태 확인
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "user", "-puser"]
      interval: 10s
      timeout: 5s
      retries: 5

volumes:
  mysql_data: # mysql_data라는 이름의 볼륨을 정의합니다.

이 설정에서 volumes 섹션은 매우 중요합니다. mysql_data:/var/lib/mysql은 컨테이너 내부의 MySQL 데이터 디렉토리를 호스트 머신의 명명된 볼륨(mysql_data)에 연결하여, 컨테이너가 중지되거나 제거되어도 데이터가 손실되지 않도록 데이터 지속성을 확보합니다. ports 설정을 통해 호스트 머신에서 3306 포트로 MySQL에 직접 접근할 수 있습니다.

MySQL과 PostgreSQL 비교

MySQL과 PostgreSQL은 관계형 데이터베이스 관리 시스템(RDBMS)의 양대 산맥으로 불립니다. 각각의 특성을 이해하고 프로젝트 요구사항에 맞춰 선택하는 것이 중요합니다.

특징 MySQL PostgreSQL
라이선스 오픈 소스 (GPL), 상업용 (Oracle) 오픈 소스 (PostgreSQL License)
성능 및 확장성 읽기 작업에 강하며, 웹 애플리케이션에 최적화 복잡한 쿼리, 대용량 데이터 처리, 엔터프라이즈 환경에 적합
데이터 타입 및 기능 일반적인 RDBMS 기능 제공 JSONB, 배열, 사용자 정의 타입 등 고급 기능 및 확장성 우수
커뮤니티 및 생태계 매우 크고 활발한 커뮤니티, 광범위한 도구 지원 전문적이고 기술 중심적인 커뮤니티, 견고한 생태계
주요 사용처 블로그, 웹사이트, 소규모 애플리케이션 데이터 웨어하우스, GIS, 복잡한 비즈니스 로직 애플리케이션

PostgreSQL 사용 시에도 MySQL과 유사하게 image: postgres:14와 같은 이미지를 사용하고, POSTGRES_DB, POSTGRES_USER, POSTGRES_PASSWORD와 같은 환경 변수를 설정하여 컨테이너를 구성할 수 있습니다.

Docker Compose를 활용한 로컬 개발 환경 구축: 데이터베이스, 백엔드, 프론트엔드 통합 가이드 - stones, waterfalls, balance, rock balancing, stack, stone balancing, rock stacking, stone stacking, stone stack, stack of stones, stones, stones, waterfalls, balance, balance, balance, balance, balance

Image by Cao135 on Pixabay

백엔드 서비스 통합: Node.js/Spring Boot 예시

데이터베이스 설정이 완료되었다면, 이제 백엔드 애플리케이션을 Docker Compose 환경에 통합할 차례입니다. 백엔드 서비스는 자체 도커 이미지로 빌드되어야 하며, 데이터베이스 서비스와 통신할 수 있도록 설정해야 합니다.

Node.js 백엔드 Dockerfile 예시

다음은 간단한 Node.js Express 애플리케이션을 위한 Dockerfile 예시입니다.

# Dockerfile (backend 폴더 내)
FROM node:18-alpine # Node.js 18 버전 기반의 Alpine 리눅스 이미지 사용
WORKDIR /app       # 컨테이너 내 작업 디렉토리 설정
COPY package*.json ./ # 패키지 의존성 파일 복사
RUN npm install    # 의존성 설치
COPY . .           # 모든 소스 코드 복사
EXPOSE 3000        # 3000번 포트 노출
CMD ["npm", "start"] # 애플리케이션 시작 명령어

Dockerfile은 Node.js 애플리케이션을 컨테이너화하는 표준적인 방법을 보여줍니다. package.json 파일만 먼저 복사하여 의존성을 설치하면, 코드 변경 시마다 의존성을 재설치할 필요 없이 캐시를 활용하여 빌드 시간을 단축할 수 있습니다.

Docker Compose에 백엔드 서비스 추가

이제 docker-compose.yml 파일에 백엔드 서비스를 추가합니다.

version: '3.8'

services:
  mysql:
    # ... (이전 MySQL 설정) ...
    
  backend:
    build:
      context: ./backend # backend 폴더에 있는 Dockerfile을 사용합니다.
      dockerfile: Dockerfile
    ports:
      - "3000:3000" # 호스트의 3000 포트를 컨테이너의 3000 포트에 연결합니다.
    environment:
      DATABASE_HOST: mysql      # 데이터베이스 서비스 이름으로 호스트 지정
      DATABASE_USER: user
      DATABASE_PASSWORD: password
      DATABASE_NAME: my_database
    depends_on:
      mysql:
        condition: service_healthy # MySQL 서비스가 준비될 때까지 기다립니다.
    volumes:
      - ./backend:/app # 개발 중 코드 변경 사항을 반영하기 위한 볼륨 마운트

여기서 중요한 부분은 다음과 같습니다.

  • build: 백엔드 애플리케이션의 Dockerfile이 위치한 경로를 지정합니다. context는 빌드 컨텍스트 경로를, dockerfile은 Dockerfile의 이름을 명시합니다.
  • environment: 백엔드 애플리케이션이 데이터베이스에 접속하는 데 필요한 환경 변수를 설정합니다. DATABASE_HOST: mysql과 같이 데이터베이스 컨테이너의 서비스 이름을 사용하여 통신합니다. Docker Compose는 서비스 이름을 내부 DNS로 해석하여 해당 컨테이너의 IP 주소를 찾아줍니다.
  • depends_on: backend 서비스가 mysql 서비스에 의존함을 명시합니다. condition: service_healthy를 추가하여 MySQL 컨테이너가 완전히 준비될 때까지 백엔드 컨테이너 생성을 지연시킵니다.
  • volumes: 개발 편의성을 위해 ./backend:/app과 같이 호스트의 백엔드 소스 코드를 컨테이너의 작업 디렉토리에 마운트합니다. 이는 호스트에서 코드를 수정하면 컨테이너 내부에도 즉시 반영되어 개발 서버가 자동으로 재시작되도록 합니다 (핫 리로드).

프론트엔드 서비스 연동: React/Vue.js 예시

백엔드와 데이터베이스 설정이 완료되었다면, 마지막으로 프론트엔드 애플리케이션을 통합하여 풀스택 로컬 개발 환경을 완성합니다. 프론트엔드 역시 자체 도커 이미지로 빌드하고, 백엔드 API와 원활하게 통신할 수 있도록 설정해야 합니다.

React 프론트엔드 Dockerfile 예시 (개발 서버 사용)

개발 단계에서는 create-react-app 등으로 생성된 개발 서버를 직접 컨테이너화하는 것이 일반적입니다.

# Dockerfile (frontend 폴더 내)
FROM node:18-alpine as development # Node.js 18 버전 기반의 Alpine 리눅스 이미지 사용
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3001 # React 개발 서버 기본 포트 (예시)
CMD ["npm", "start"]

Dockerfile은 Node.js 기반의 개발 서버를 실행하는 기본적인 구성을 따릅니다. 프론트엔드 애플리케이션은 보통 백엔드 API와 통신해야 하므로, API 요청을 처리할 수 있는 설정이 필요합니다.

Docker Compose에 프론트엔드 서비스 추가

이제 docker-compose.yml 파일에 프론트엔드 서비스를 추가합니다.

version: '3.8'

services:
  mysql:
    # ... (이전 MySQL 설정) ...
    
  backend:
    # ... (이전 백엔드 설정) ...

  frontend:
    build:
      context: ./frontend
      dockerfile: Dockerfile
    ports:
      - "3001:3001" # 호스트의 3001 포트를 컨테이너의 3001 포트에 연결합니다.
    environment:
      REACT_APP_API_URL: http://backend:3000 # 백엔드 서비스 URL 설정
    volumes:
      - ./frontend:/app # 개발 중 코드 변경 사항을 반영하기 위한 볼륨 마운트
    depends_on:
      backend:
        condition: service_started # 백엔드 서비스가 시작될 때까지 기다립니다.

프론트엔드 서비스 설정의 주요 특징은 다음과 같습니다.

  • environment: 프론트엔드 애플리케이션이 백엔드 API에 접근할 URL을 환경 변수로 전달합니다. REACT_APP_API_URL: http://backend:3000와 같이 백엔드 컨테이너의 서비스 이름과 포트를 사용합니다. React, Vue, Angular 등 대부분의 프론트엔드 프레임워크는 .env 파일이나 빌드 환경 설정을 통해 이러한 환경 변수를 주입받을 수 있습니다.
  • volumes: 백엔드와 마찬가지로, 호스트의 프론트엔드 소스 코드를 컨테이너에 마운트하여 실시간 코드 변경을 반영할 수 있도록 합니다.
  • depends_on: 프론트엔드 서비스가 백엔드 서비스에 의존함을 명시하여, 백엔드가 먼저 시작된 후에 프론트엔드가 실행되도록 합니다.

개발 서버를 사용하는 대신, 프로덕션 환경처럼 Nginx와 같은 웹 서버를 사용하여 정적 파일을 서빙하는 방식으로 프론트엔드를 구성할 수도 있습니다. 이 경우 프론트엔드 Dockerfile은 애플리케이션을 빌드하고 Nginx 이미지를 사용하여 정적 파일을 서빙하도록 구성됩니다.

Docker Compose를 활용한 로컬 개발 환경 구축: 데이터베이스, 백엔드, 프론트엔드 통합 가이드 - colorful, papers, hues, free wallpaper, wallpaper hd, windows wallpaper, laptop wallpaper, full hd wallpaper, 4k wallpaper 1920x1080, cool backgrounds, colors, background, stationery, stack of papers, close up, free background, wallpaper 4k, 4k wallpaper, stack, paper stack, school supplies, beautiful wallpaper, office supplies, desktop backgrounds, mac wallpaper, hd wallpaper, stationery background

Image by AlexanderStein on Pixabay

완성된 Docker Compose 파일과 개발 워크플로우

지금까지 살펴본 데이터베이스, 백엔드, 프론트엔드 서비스를 모두 통합한 docker-compose.yml 파일은 다음과 같은 구조를 갖게 됩니다.

# docker-compose.yml
version: '3.8'

services:
  mysql:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: root_password
      MYSQL_DATABASE: my_database
      MYSQL_USER: user
      MYSQL_PASSWORD: password
    ports:
      - "3306:3306"
    volumes:
      - mysql_data:/var/lib/mysql
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "user", "-puser"]
      interval: 10s
      timeout: 5s
      retries: 5

  backend:
    build:
      context: ./backend
      dockerfile: Dockerfile
    ports:
      - "3000:3000"
    environment:
      DATABASE_HOST: mysql
      DATABASE_USER: user
      DATABASE_PASSWORD: password
      DATABASE_NAME: my_database
    volumes:
      - ./backend:/app
    depends_on:
      mysql:
        condition: service_healthy

  frontend:
    build:
      context: ./frontend
      dockerfile: Dockerfile
    ports:
      - "3001:3001"
    environment:
      REACT_APP_API_URL: http://backend:3000
    volumes:
      - ./frontend:/app
    depends_on:
      backend:
        condition: service_started

volumes:
  mysql_data:

이 파일을 사용하여 전체 개발 환경을 구동하는 과정은 매우 간단합니다. 프로젝트 루트 디렉토리에서 다음 명령어를 실행합니다.

docker-compose up -d

이 명령어는 docker-compose.yml 파일에 정의된 모든 서비스(MySQL, 백엔드, 프론트엔드)를 백그라운드에서 빌드하고 실행합니다. 각 서비스는 올바른 순서와 의존성에 따라 시작됩니다. 성공적으로 실행되면, 웹 브라우저에서 http://localhost:3001 (프론트엔드 포트)로 접속하여 개발 중인 애플리케이션을 확인할 수 있습니다.

일반적인 개발 워크플로우

Docker Compose 기반의 로컬 개발 환경에서의 일반적인 워크플로우는 다음과 같습니다.

  1. 환경 시작: docker-compose up -d로 모든 서비스를 시작합니다.
  2. 코드 수정: 호스트 머신에서 백엔드나 프론트엔드 코드를 수정합니다. 볼륨 마운트 덕분에 컨테이너 내부의 코드가 자동으로 업데이트되며, 개발 서버는 보통 변경을 감지하여 핫 리로드를 수행합니다.
  3. 로그 확인: docker-compose logs -f [서비스명] 명령어로 특정 서비스의 로그를 실시간으로 확인할 수 있습니다. 예를 들어, docker-compose logs -f backend는 백엔드 서버의 로그를 보여줍니다.
  4. 환경 중지: 개발을 마쳤거나 다른 프로젝트로 전환할 때 docker-compose down 명령어로 모든 컨테이너를 중지하고 제거합니다. volumes에 의해 데이터는 유지됩니다.
  5. 재빌드: Dockerfile이나 이미지 변경이 필요한 경우, docker-compose builddocker-compose up -d를 다시 실행합니다.

이러한 워크플로우는 개발자가 환경 설정에 소모하는 시간을 최소화하고, 순수하게 코드 개발에 집중할 수 있도록 지원합니다. 또한, 새로운 팀원이 프로젝트에 합류했을 때도 단 몇 개의 명령어로 전체 개발 환경을 구축할 수 있어 온보딩 프로세스를 크게 간소화합니다.

Docker Compose 활용을 통한 개발 생산성 극대화

Docker Compose를 활용한 로컬 개발 환경 구축은 개발 팀 전체의 생산성을 극대화하는 데 기여합니다. 주요 이점은 다음과 같습니다.

  • 환경 일관성 확보: 모든 개발자가 동일한 버전의 데이터베이스, 런타임, 의존성을 가진 환경에서 작업하므로 '내 컴퓨터에서는 잘 되는데...'와 같은 환경 불일치 문제를 근본적으로 해결합니다. 이는 오류 발생 가능성을 줄이고 디버깅 시간을 단축시킵니다.
  • 빠른 온보딩: 새로운 팀원이 프로젝트에 참여할 때, 복잡한 환경 설정 가이드를 따라갈 필요 없이 git clonedocker-compose up -d 명령어 하나로 모든 개발 환경을 즉시 구축할 수 있습니다. 이는 팀의 효율성을 크게 향상시킵니다.
  • 격리된 개발 환경: 각 서비스가 독립적인 컨테이너에서 실행되므로, 한 서비스의 변경 사항이 다른 서비스에 예상치 못한 영향을 미 미칠 가능성이 줄어듭니다. 이는 모듈화된 개발과 테스트에 유리합니다.
  • 유연한 스택 관리: 프로젝트 요구사항에 따라 데이터베이스 종류를 변경하거나, 캐시 서버, 메시지 큐 등 새로운 컴포넌트를 추가하는 것이 docker-compose.yml 파일 수정만으로 가능합니다. 이는 개발 스택의 유연성을 높입니다.
  • CI/CD 연동 용이성: Docker Compose 파일은 CI/CD 파이프라인과도 쉽게 통합될 수 있습니다. 개발 환경과 동일한 컨테이너 기반 환경에서 테스트 및 배포가 이루어지므로, 환경 간의 격차로 인한 문제가 최소화됩니다.

Docker Compose는 로컬 개발 환경을 넘어, 스테이징이나 테스트 환경 구축에도 활용될 수 있습니다. docker-compose.yml 파일의 구성을 약간만 변경하여 프로덕션에 준하는 환경을 신속하게 배포하고 테스트할 수 있습니다. 이는 개발 초기 단계부터 배포까지 일관된 환경을 유지하는 데 필수적인 요소로 작용합니다.

결론적으로, Docker Compose는 풀스택 개발자에게 필수적인 도구이며, 그 활용법을 숙지하는 것은 현대적인 소프트웨어 개발 워크플로우에서 경쟁력을 확보하는 중요한 방법입니다. 이 가이드에서 제시된 내용을 바탕으로 자신만의 최적화된 로컬 개발 환경을 구축하고, 개발 생산성을 한 단계 더 끌어올리시길 바랍니다.

이 글에 대한 피드백이나 Docker Compose 활용 경험이 있다면 댓글로 공유해 주세요. 여러분의 지식 공유가 더 나은 개발 문화를 만드는 데 기여할 것입니다.

📌 함께 읽으면 좋은 글

  • [보안] HashiCorp Vault 민감 정보 관리 전략: Secrets 보안 강화 완벽 가이드
  • [튜토리얼] Docker Compose ELK 스택 구축: 실시간 로그 분석 및 시각화 완벽 가이드
  • [튜토리얼] Playwright로 웹 애플리케이션 E2E 테스트 자동화, 실전 가이드

이 글이 도움이 되셨다면 공감(♥)댓글로 응원해 주세요!
궁금한 점이나 다루었으면 하는 주제가 있다면 댓글로 남겨주세요.