Next.js 리드·아키텍트 배포·운영 기술면접
새 면접Q. Next.js 애플리케이션을 Kubernetes 환경에서 운영 중입니다. 새 버전 배포 시 rolling update를 사용하는데, 배포 도중 일부 사용자가 API 요청 실패를 경험합니다. Pod가 종료되는 시점에 SIGTERM을 받고도 즉시 종료되어 진행 중인 요청이 중단되는 상황입니다. Graceful Shutdown의 구현 원리를 설명하고, Next.js 서버에서 preStop hook과 terminationGracePeriodSeconds를 활용한 무중단 배포 전략을 제시해주세요. 또한 Readiness Probe와 Liveness Probe의 차이점과 각각의 적절한 설정 기준을 설명해주세요.
Pod 라이프사이클에서 SIGTERM 신호 이후 새로운 트래픽 차단과 기존 요청 완료 대기가 핵심입니다.
Graceful Shutdown은 SIGTERM 신호를 받으면 즉시 종료하지 않고 (1) 새로운 요청 수락 중단, (2) 기존 요청 처리 완료 대기, (3) 모든 연결 종료 후 프로세스 종료하는 방식입니다. Next.js에서는 server.close()로 새 연결을 거부하고 setTimeout으로 최대 대기 시간을 설정합니다. preStop hook에서 sleep을 추가해 로드밸런서가 Pod를 제거하는 시간을 확보하고, terminationGracePeriodSeconds는 평균 요청 처리 시간의 2~3배로 설정합니다. Readiness Probe는 트래픽 수신 준비 여부를 판단해 배포 중 트래픽 라우팅을 제어하고, Liveness Probe는 애플리케이션 생존 여부를 확인해 데드락 상태의 Pod를 재시작합니다. Readiness는 배포 중 실패 시 즉시 트래픽 차단을 위해 짧은 주기(5초)로, Liveness는 false positive 재시작 방지를 위해 긴 주기(30초)와 높은 failureThreshold로 설정합니다.
- • SIGTERM 수신 시 새 요청 거부와 기존 요청 완료 대기의 2단계 처리
- • preStop hook으로 로드밸런서 갱신 시간 확보
- • Readiness는 트래픽 제어, Liveness는 데드락 복구 목적으로 구분
- • terminationGracePeriodSeconds는 요청 처리 시간 기반 설정
대규모 트래픽 서비스에서 배포 중 요청 손실 없이 안정적인 버전 전환을 보장해야 할 때 필수적입니다.
Blue-Green 배포와 Canary 배포를 비교하고, Next.js 환경에서 각각의 트레이드오프와 적합한 상황을 설명해주세요.
Q. Next.js 애플리케이션을 Docker 컨테이너로 운영하는데, 메모리 사용량이 지속적으로 증가하다가 OOMKilled로 Pod가 재시작됩니다. Node.js의 힙 메모리는 여유가 있는데 컨테이너 메모리는 한계에 도달하는 상황입니다. 컨테이너의 메모리 limit과 Node.js의 --max-old-space-size 설정의 관계를 설명하고, RSS(Resident Set Size), Heap Used, External Memory의 차이점을 분석해주세요. 또한 메모리 누수 진단을 위한 Heap Snapshot 분석 전략과, 프로덕션 환경에서 안전하게 메모리 프로파일링을 수행하는 방법을 제시해주세요.
V8 힙 외부의 Buffer, Native Module 메모리도 컨테이너 limit에 포함됩니다.
컨테이너 메모리 limit은 프로세스 전체(힙, 스택, 네이티브 메모리, 버퍼)를 포함하지만 --max-old-space-size는 V8 힙만 제한합니다. RSS는 물리 메모리에 실제 할당된 전체 크기, Heap Used는 V8이 관리하는 JavaScript 객체 메모리, External Memory는 Buffer나 네이티브 애드온이 사용하는 힙 외부 메모리입니다. 컨테이너 limit의 75~80%를 --max-old-space-size로 설정해 나머지를 버퍼와 네이티브 메모리에 할당합니다. Heap Snapshot은 process.memoryUsage()로 증가 추세 확인 후 heapdump 모듈로 덤프를 생성하고, Chrome DevTools로 Retained Size가 큰 객체와 Retainer를 추적합니다. 프로덕션에서는 트래픽이 적은 시간대에 단일 인스턴스에서만 프로파일링하고, 메모리 덤프는 외부 스토리지로 즉시 전송해 디스크 부족을 방지합니다.
- • 컨테이너 메모리는 힙+버퍼+네이티브 메모리 전체, --max-old-space-size는 V8 힙만 제한
- • RSS, Heap Used, External Memory의 구분과 각각의 증가 원인 분석
- • 컨테이너 limit의 75~80%를 힙 크기로 설정하는 경험적 규칙
- • Heap Snapshot의 Retained Size와 Retainer 추적을 통한 누수 지점 식별
대용량 파일 처리나 이미지 변환 작업이 있는 서비스에서 컨테이너 메모리 최적화가 비용 절감의 핵심입니다.
Node.js 애플리케이션에서 Worker Threads를 사용할 때 메모리 격리와 공유 전략, 그리고 각 워커의 힙 크기 설정 방법을 설명해주세요.
Q. Next.js 프로젝트의 GitHub Actions CI/CD 파이프라인에서 빌드 시간이 15분 이상 소요되어 배포 속도가 느립니다. 의존성 설치, TypeScript 컴파일, 테스트, Docker 이미지 빌드 단계가 포함되어 있습니다. 빌드 시간을 단축하기 위한 캐싱 전략을 설명하고, Layer Caching, Dependency Caching, Incremental Build의 원리와 적용 방법을 제시해주세요. 또한 Multi-stage Docker Build를 활용한 이미지 크기 최적화와 빌드 병렬화 전략도 함께 설명해주세요.
각 단계별로 변경 빈도를 분석하고, 변경이 적은 레이어를 먼저 배치하는 것이 핵심입니다.
Layer Caching은 Dockerfile의 각 명령어를 레이어로 저장해 변경되지 않은 레이어를 재사용하는 방식으로, package.json과 lock file을 먼저 COPY해 의존성 설치 레이어를 분리합니다. Dependency Caching은 actions/cache로 node_modules를 캐시해 npm install 시간을 단축하며, 캐시 키는 lock file의 해시값을 사용합니다. Incremental Build는 Next.js의 .next 디렉토리를 캐시해 변경된 페이지만 재빌드하도록 하며, tsc의 --incremental 옵션으로 TypeScript 컴파일도 최적화합니다. Multi-stage Build는 빌드 단계와 런타임 단계를 분리해 devDependencies와 빌드 도구를 최종 이미지에서 제외하고, node_modules는 production만 포함해 이미지 크기를 70% 이상 줄입니다. 테스트와 린트를 병렬로 실행하고, 캐시 히트율을 모니터링해 효과를 측정합니다.
- • Dockerfile에서 변경 빈도가 낮은 의존성 설치를 소스 복사보다 먼저 배치
- • GitHub Actions cache로 node_modules와 .next 디렉토리 캐시
- • Multi-stage Build로 빌드 도구와 devDependencies 제외
- • 테스트와 린트를 병렬 job으로 실행해 전체 시간 단축
하루에 수십 번 배포하는 애자일 환경에서 빌드 시간 단축은 개발 생산성과 직결됩니다.
Monorepo 환경에서 변경된 패키지만 선택적으로 빌드하고 배포하는 전략을 설명해주세요.
Q. Next.js 애플리케이션을 프로덕션 운영하며 Prometheus와 Grafana로 모니터링하고 있습니다. SLO(Service Level Objective)를 정의하고 SLI(Service Level Indicator)를 측정해 SLA를 보장하려고 합니다. API 응답 시간, 에러율, 가용성을 모니터링하는데, 어떤 메트릭을 수집하고 어떤 임계값으로 알람을 설정해야 하는지 설명해주세요. 또한 Error Budget 개념을 적용한 배포 정책과, Golden Signals(Latency, Traffic, Errors, Saturation)를 Next.js 환경에 맞게 구체화하는 방법을 제시해주세요.
평균값보다 백분위수(percentile) 기반 메트릭이 사용자 경험을 더 정확히 반영합니다.
SLI로는 P99 응답 시간(상위 1% 사용자 경험), 5xx 에러율(전체 요청 대비), 가용성(정상 응답 비율)을 측정하고, SLO는 P99 < 500ms, 에러율 < 0.1%, 가용성 > 99.9%로 설정합니다. 알람은 5분 윈도우에서 SLO 위반이 연속 3회 발생 시 트리거해 일시적 스파이크를 무시합니다. Error Budget은 월간 허용 다운타임(99.9% = 43분)을 계산해, 예산 소진율이 50% 초과 시 배포를 중단하고 안정화에 집중합니다. Golden Signals는 Latency(API route별 P50/P95/P99), Traffic(RPS와 동시 연결 수), Errors(HTTP 상태 코드별 분포), Saturation(CPU/메모리 사용률과 이벤트 루프 지연)으로 구체화합니다. Next.js에서는 custom server로 prom-client를 통합하거나 OpenTelemetry를 사용해 메트릭을 수집하고, 비즈니스 메트릭(전환율, 결제 성공률)도 함께 추적합니다.
- • P99 응답 시간과 에러율을 SLI로 측정해 사용자 경험 반영
- • Error Budget으로 배포 속도와 안정성의 균형 유지
- • Golden Signals를 Next.js 특성에 맞게 구체화(이벤트 루프 지연 포함)
- • 연속 위반 조건으로 알람을 설정해 false positive 감소
장애 발생 시 MTTD(Mean Time To Detect)와 MTTR(Mean Time To Resolve)을 단축하는 데 필수적입니다.
분산 추적(Distributed Tracing)을 도입할 때 OpenTelemetry의 Span과 Trace 개념을 설명하고, Next.js에서 API Route와 외부 서비스 호출을 추적하는 구현 방법을 제시해주세요.
Q. Next.js 애플리케이션의 새 버전을 배포한 후 데이터베이스 스키마 변경으로 인해 구버전과 호환되지 않는 문제가 발생했습니다. 즉시 롤백을 시도하는데, 데이터베이스는 이미 마이그레이션되어 롤백이 불가능한 상황입니다. Forward Compatibility와 Backward Compatibility를 고려한 안전한 배포 전략을 설명하고, Expand-Contract 패턴을 활용한 무중단 스키마 변경 절차를 제시해주세요. 또한 Feature Flag를 활용해 코드 배포와 기능 활성화를 분리하는 방법도 함께 설명해주세요.
스키마 변경을 코드 배포와 분리하고, 새 컬럼 추가와 구 컬럼 제거를 여러 단계로 나누는 것이 핵심입니다.
Expand-Contract 패턴은 (1) Expand: 새 컬럼 추가하고 기본값 설정, (2) Migrate: 애플리케이션이 새/구 컬럼 모두 읽고 쓰도록 배포, (3) Contract: 구 컬럼 제거의 3단계로 진행합니다. 첫 배포에서는 구 컬럼을 유지해 롤백 가능성을 보장하고, 새 버전이 안정화된 후 두 번째 배포에서 구 컬럼을 제거합니다. Forward Compatibility는 구버전이 새 스키마를 처리할 수 있도록 nullable 컬럼으로 추가하고, Backward Compatibility는 신버전이 구 스키마도 읽을 수 있도록 fallback 로직을 구현합니다. Feature Flag는 LaunchDarkly나 환경변수로 새 기능을 비활성화 상태로 배포하고, 배포 후 단계적으로 활성화해 문제 발생 시 코드 재배포 없이 즉시 비활성화합니다. 데이터 마이그레이션은 별도 배치 작업으로 수행하고, 진행률을 모니터링하며 언제든 중단 가능하도록 설계합니다.
- • Expand-Contract 패턴으로 스키마 변경을 3단계로 분리
- • 새 컬럼을 nullable로 추가해 구버전 호환성 유지
- • Feature Flag로 코드 배포와 기능 활성화 분리
- • 데이터 마이그레이션을 별도 작업으로 수행해 롤백 가능성 확보
대규모 서비스에서 다운타임 없이 스키마를 변경하고 안전하게 롤백할 수 있는 능력이 필수입니다.
Database Migration 도구(Prisma Migrate, TypeORM)에서 production 환경의 마이그레이션 전략과 안전 장치를 설명해주세요.
Q. Next.js 애플리케이션이 마이크로서비스 아키텍처로 구성되어 있으며, 사용자 요청이 여러 서비스를 거쳐 처리됩니다. 특정 API 요청의 전체 흐름을 추적하고 병목 지점을 파악하기 위해 Correlation ID 기반 로깅 시스템을 구축하려고 합니다. Structured Logging의 개념과 JSON 형식 로그의 장점을 설명하고, Next.js Middleware에서 Correlation ID를 생성하고 전파하는 방법을 제시해주세요. 또한 ELK Stack이나 Loki를 활용한 중앙 집중식 로그 수집 아키텍처와 로그 레벨별 보관 정책을 설명해주세요.
각 서비스가 동일한 Correlation ID를 포함하도록 HTTP 헤더와 로그 컨텍스트에 전파하는 것이 핵심입니다.
Structured Logging은 로그를 key-value 쌍의 JSON 형식으로 기록해 파싱과 검색이 용이하고, timestamp, level, correlationId, userId, method, path 등의 메타데이터를 일관되게 포함합니다. Next.js Middleware에서 uuid로 Correlation ID를 생성하고 AsyncLocalStorage에 저장해 모든 하위 함수에서 접근 가능하게 하며, 외부 API 호출 시 X-Correlation-ID 헤더로 전파합니다. 각 서비스는 요청 헤더에서 Correlation ID를 추출해 로그에 포함하고, 없으면 새로 생성합니다. ELK Stack에서는 Filebeat가 컨테이너 로그를 수집해 Logstash로 전송하고, Elasticsearch에 인덱싱한 후 Kibana로 Correlation ID 기준 검색과 시각화를 수행합니다. 로그 레벨별로 ERROR는 90일, WARN은 30일, INFO는 7일 보관하고, DEBUG는 프로덕션에서 비활성화하거나 샘플링(1% 수집)합니다. 로그 볼륨이 크면 Loki로 전환해 인덱싱 비용을 절감합니다.
- • JSON 형식 Structured Logging으로 메타데이터 일관성 확보
- • AsyncLocalStorage로 Correlation ID를 컨텍스트에 저장하고 전파
- • HTTP 헤더(X-Correlation-ID)로 서비스 간 ID 전달
- • 로그 레벨과 보관 기간을 차등화해 스토리지 비용 최적화
분산 시스템에서 장애 원인을 빠르게 파악하고 특정 사용자 요청의 전체 흐름을 추적할 때 필수적입니다.
로그와 메트릭, 트레이스를 통합하는 Observability 전략에서 각각의 역할과 상호보완 방법을 설명해주세요.
Q. Next.js 애플리케이션을 AWS에서 운영하는데, 월 인프라 비용이 예상보다 높습니다. CloudFront CDN, ALB, ECS Fargate, RDS, S3 비용이 주요 항목입니다. 트래픽 패턴을 분석한 결과 피크 시간대와 야간의 부하 차이가 5배 이상입니다. 비용 최적화를 위한 Auto Scaling 전략을 설명하고, Fargate Spot Instances와 Reserved Instances의 트레이드오프를 분석해주세요. 또한 CloudFront의 Price Class와 Cache Hit Ratio 최적화, RDS의 Read Replica와 Query Cache 전략도 함께 제시해주세요.
트래픽 패턴에 맞춰 리소스를 탄력적으로 조정하고, 캐싱 레이어를 적극 활용하는 것이 핵심입니다.
ECS Auto Scaling은 Target Tracking으로 CPU 사용률 70%를 목표로 설정하고, Scheduled Scaling으로 예측 가능한 피크 시간(오전 9시, 오후 6시) 전에 미리 스케일 아웃합니다. Fargate Spot은 온디맨드 대비 70% 저렴하지만 중단 가능하므로, 비상태 워크로드나 배치 작업에 사용하고 중요 API는 온디맨드로 유지합니다. Reserved Instances는 최소 용량(베이스라인)에 적용해 1년 약정으로 40% 절감하고, 피크 용량은 Spot과 온디맨드 조합으로 처리합니다. CloudFront는 Price Class 200(북미+유럽)으로 제한해 아시아 엣지 비용을 절감하고, Cache-Control 헤더를 적극 설정해 Hit Ratio를 90% 이상 유지합니다. RDS는 읽기 부하를 Read Replica로 분산하고, 자주 조회되는 데이터는 ElastiCache(Redis)로 캐싱해 DB 부하를 70% 감소시킵니다. S3는 Intelligent-Tiering으로 액세스 빈도에 따라 자동으로 스토리지 클래스를 변경하고, Lifecycle Policy로 90일 이상 미사용 객체를 Glacier로 이동합니다.
- • Target Tracking과 Scheduled Scaling을 조합한 Auto Scaling
- • Spot Instances를 비상태 워크로드에, Reserved Instances를 베이스라인에 적용
- • CloudFront Cache Hit Ratio 90% 이상 유지로 오리진 부하 감소
- • ElastiCache로 DB 읽기 부하 70% 감소 및 응답 시간 단축
스타트업에서 제한된 예산으로 서비스 품질을 유지하면서 인프라 비용을 절감해야 할 때 필수적입니다.
FinOps 관점에서 클라우드 비용을 지속적으로 모니터링하고 최적화하는 조직 프로세스와 도구를 설명해주세요.
아직 댓글이 없습니다. 첫 번째 댓글을 남겨보세요!