배포/환경 전략
이 문서로 해결할 질문
- dev와 prod에서 컴포넌트는 어디에 올라가나요?
- Compose 파일 역할과 기동 순서는 무엇인가요?
- Mealio를 배포할 때 어떤 특성을 고려해야 하나요?
스택 구성
| 계층 | 컴포넌트 | 비고 |
|---|---|---|
| 프론트엔드 | client (Next.js) | SSR·ISR — 서버 런타임 필요 |
| 백엔드 API | producer (NestJS) | HTTP API, OAuth, Kafka produce |
| 이벤트 워커 | consumer (NestJS) | Kafka consume, 배치 job |
| 메시지 브로커 | Kafka | 도메인 이벤트 버스 |
| 관계 DB | PostgreSQL | Prisma, pgvector 확장 |
| 문서 DB | MongoDB | Mongoose |
| 캐시 | Redis | Cache-Aside, 세션 |
| 관측성 | Prometheus, Pushgateway, Grafana | 메트릭 수집·push·시각화 |
배포 시 고려 사항
client (Next.js)
- SSR·ISR을 사용하므로 Node.js 서버 런타임이 필요합니다.
NEXT_PUBLIC_*변수는 이미지 빌드 시 번들에 인라이닝됩니다. 값이 바뀌면 재빌드가 필요합니다.INTERNAL_API_BASE_URL을 설정하면 SSR에서 내부 네트워크를 통해 producer를 호출할 수 있습니다.- Docker 배포 시
docker/client/compose.yml과docker/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.docker의PROMETHEUS_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):
| 컴포넌트 | 배포 방식 |
|---|---|
| producer | docker/producer/compose.yml |
| consumer | docker/consumer/compose.yml |
인프라 서버 (DB·메시지·관측):
| 컴포넌트 | 배포 방식 |
|---|---|
| PostgreSQL | docker/postgres/compose.yml |
| Redis | docker/redis/compose.yml |
| Kafka | docker/kafka/compose.yml |
| Prometheus | docker/prometheus/compose.yml |
| Pushgateway | docker/pushgateway/compose.yml |
| Grafana | docker/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)
| 파일 | 대상 | prod | dev |
|---|---|---|---|
docker/mongodb/compose.yml | mongodb | ✗ | ✓ |
docker/postgres/compose.yml | postgres | ✗ | ✓ |
docker/redis/compose.yml | redis | ✗ | ✓ |
docker/kafka/compose.yml | kafka | ✓ | ✓ |
docker/kafka-ui/compose.yml | kafka-ui | ✗ | ✓ |
docker/pushgateway/compose.yml | pushgateway | ✓ | ✓ |
docker/prometheus/compose.yml | prometheus | ✓ | ✓ |
docker/grafana/compose.yml | grafana | ✓ | ✓ |
docker/producer/compose.yml | producer | ✓ | ✗ |
docker/consumer/compose.yml | consumer | ✓ | ✗ |
docker/client/compose.yml | client | 선택 | 선택 |
기동 순서는 인프라 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.local | Prisma·Mongoose·Kafka 토픽 CLI (db:*) |
*.env.docker.local | Docker로 앱 기동 시 |
변수별 사용처·예시·환경별 패턴은 환경 변수와 패키지별 문서를 참고하세요.
릴리스 흐름 (요약)
- CI가 통과해야 합니다 (
pnpm run ci). - DB 마이그레이션을 적용합니다 (
db:prisma:migrate:deploy). - 인프라 Compose(Kafka·관측)를 먼저 기동합니다.
- Kafka 토픽을 생성합니다 (
pnpm run db:kafka:create-topics:production). - producer·consumer 이미지를 빌드·기동합니다.
- client를 배포합니다.
- 헬스·메트릭·validation 시나리오를 확인합니다.