본문으로 건너뛰기

배포/환경 전략

이 문서로 해결할 질문

  • dev와 prod에서 컴포넌트는 어디에 올라가나요?
  • Compose 파일 역할과 기동 순서는 무엇인가요?
  • Mealio를 배포할 때 어떤 특성을 고려해야 하나요?

스택 구성

계층컴포넌트비고
프론트엔드client (Next.js)SSR·ISR — 서버 런타임 필요
백엔드 APIproducer (NestJS)HTTP API, OAuth, Kafka produce
이벤트 워커consumer (NestJS)Kafka consume, 배치 job
메시지 브로커Kafka도메인 이벤트 버스
관계 DBPostgreSQLPrisma, pgvector 확장
문서 DBMongoDBMongoose
캐시RedisCache-Aside, 세션
관측성Prometheus, Pushgateway, Grafana메트릭 수집·push·시각화

배포 시 고려 사항

client (Next.js)

  • SSR·ISR을 사용하므로 Node.js 서버 런타임이 필요합니다.
  • NEXT_PUBLIC_* 변수는 이미지 빌드 시 번들에 인라이닝됩니다. 값이 바뀌면 재빌드가 필요합니다.
  • INTERNAL_API_BASE_URL을 설정하면 SSR에서 내부 네트워크를 통해 producer를 호출할 수 있습니다.
  • Docker 배포 시 docker/client/compose.ymldocker/Dockerfile.client를 사용합니다.

producer / consumer

  • 각각 독립 프로세스·컨테이너로 운영합니다.
  • 부팅 시 Joi 스키마로 모든 환경 변수를 검증하며, 실패 시 프로세스가 종료됩니다.
  • Kafka 브로커가 준비된 뒤 기동해야 합니다.

PostgreSQL (Prisma)

  • prisma migrate deploy를 배포 파이프라인에 포함합니다.
  • recipe ingestion은 pgvector 확장이 필요합니다.

Redis

  • Cache-Aside, OAuth/세션에 사용합니다.
  • TLS 연결을 지원합니다 (rediss://).

Kafka

  • producer·consumer 모두 동일 브로커에 연결합니다.
  • kafka-ui는 개발 전용으로 프로덕션에는 배포하지 않습니다.
  • 토픽은 pnpm run db:kafka:create-topics:production으로 생성합니다.

Prometheus

  • producer·consumer는 별도 METRICS_PORT에서 /metrics를 노출합니다 (METRICS_ENABLED=true).
  • .env.dockerPROMETHEUS_PRODUCER_TARGET·PROMETHEUS_CONSUMER_TARGET으로 스크랩 대상(host:port)을 지정합니다. 기본값은 producer:9100·consumer:9101이며, 호스트에서 앱을 직접 실행할 때는 host.docker.internal:포트로 덮어씁니다.

Pushgateway

  • recipe-ingestion CLI batch job은 PUSHGATEWAY_URL로 Pushgateway에 메트릭을 push합니다.
  • PUSHGATEWAY_PORT로 호스트 바인딩 포트를 지정합니다.
  • Prometheus는 PROMETHEUS_PUSHGATEWAY_TARGET으로 Pushgateway를 스크랩합니다. 기본값은 pushgateway:9091이며, 호스트 개발 시 host.docker.internal:9091로 덮어씁니다.

환경별 배치

프로덕션(예시)

아래 배치는 예시이므로 실제 운영 환경에서는 트래픽·비용·보안 요구사항에 맞게 구성을 조정하세요.

데모 배포 예시에서는 역할에 따라 두 서버로 나눠 운영합니다.

앱 서버 (Nginx·producer·consumer):

컴포넌트배포 방식
producerdocker/producer/compose.yml
consumerdocker/consumer/compose.yml

인프라 서버 (DB·메시지·관측):

컴포넌트배포 방식
PostgreSQLdocker/postgres/compose.yml
Redisdocker/redis/compose.yml
Kafkadocker/kafka/compose.yml
Prometheusdocker/prometheus/compose.yml
Pushgatewaydocker/pushgateway/compose.yml
Grafanadocker/grafana/compose.yml

이 외에 client는 Vercel, MongoDB는 MongoDB Atlas에 배포합니다.

개발 (로컬)

컴포넌트위치
producer, consumer, client호스트 (pnpm run start:*)
DB, Redis, Kafka, 관측Docker Compose
docker/producer·docker/consumer·docker/client미기동

로컬 개발/온보딩

Compose 파일 (docker/{서비스명}/compose.yml)

파일대상proddev
docker/mongodb/compose.ymlmongodb
docker/postgres/compose.ymlpostgres
docker/redis/compose.ymlredis
docker/kafka/compose.ymlkafka
docker/kafka-ui/compose.ymlkafka-ui
docker/pushgateway/compose.ymlpushgateway
docker/prometheus/compose.ymlprometheus
docker/grafana/compose.ymlgrafana
docker/producer/compose.ymlproducer
docker/consumer/compose.ymlconsumer
docker/client/compose.ymlclient선택선택

기동 순서는 인프라 Compose를 먼저 기동한 뒤 앱 Compose를 기동합니다. 모든 Compose 파일은 동일한 브리지 네트워크(mealio-net)를 공유합니다.

환경 변수 파일

파일용도
.env.docker.local인프라 Compose 전용
client/.env.local호스트 client
server/producer/.env.local호스트 producer
server/consumer/.env.local호스트 consumer
server/shared/.env.localPrisma·Mongoose·Kafka 토픽 CLI (db:*)
*.env.docker.localDocker로 앱 기동 시

변수별 사용처·예시·환경별 패턴은 환경 변수와 패키지별 문서를 참고하세요.

릴리스 흐름 (요약)

  1. CI가 통과해야 합니다 (pnpm run ci).
  2. DB 마이그레이션을 적용합니다 (db:prisma:migrate:deploy).
  3. 인프라 Compose(Kafka·관측)를 먼저 기동합니다.
  4. Kafka 토픽을 생성합니다 (pnpm run db:kafka:create-topics:production).
  5. producer·consumer 이미지를 빌드·기동합니다.
  6. client를 배포합니다.
  7. 헬스·메트릭·validation 시나리오를 확인합니다.

관련 문서