Go 시니어 시스템 설계 면접
새 면접Q. 초당 10만 요청을 처리하는 API Gateway를 Go로 구현해야 합니다. 인증/인가, rate limiting, circuit breaking, request/response transformation, 라우팅을 지원해야 하며, 백엔드 서비스 장애 시에도 부분적인 서비스 제공이 가능해야 합니다. 각 기능의 구현 전략과 성능 최적화 방안, 그리고 장애 격리를 위한 아키텍처를 설계해주세요.
미들웨어 체인 패턴과 각 기능의 독립적인 실패 처리, 그리고 connection pooling 전략을 고려해보세요.
미들웨어 체인 패턴으로 각 기능을 독립적인 레이어로 분리하고, net/http의 ReverseProxy를 커스터마이징하여 라우팅을 구현합니다. 인증은 JWT 검증을 goroutine pool에서 병렬 처리하고, rate limiting은 로컬 메모리 기반 token bucket과 Redis 기반 분산 limiter를 조합하여 Redis 장애 시에도 동작하도록 합니다. Circuit breaker는 각 백엔드 서비스별로 독립적인 상태 머신을 유지하며, half-open 상태에서 health check를 수행합니다. Request transformation은 sync.Pool로 버퍼를 재사용하여 GC 압력을 줄이고, response caching은 TTL 기반 in-memory cache를 적용합니다. 백엔드 서비스별로 별도의 connection pool을 유지하며, timeout과 deadline을 계층별로 설정하여 cascading failure를 방지합니다. 모니터링을 위해 각 미들웨어에서 메트릭을 수집하고 distributed tracing으로 요청 흐름을 추적합니다.
- • 미들웨어 체인 패턴으로 기능 분리 및 독립적 실패 처리
- • 로컬/분산 하이브리드 rate limiting으로 장애 대응
- • 서비스별 circuit breaker와 connection pool 격리
- • sync.Pool 활용한 메모리 최적화와 GC 압력 감소
MSA 환경에서 수십 개의 백엔드 서비스를 단일 진입점으로 통합하고 횡단 관심사를 중앙화할 때 사용됩니다.
API Gateway가 다중 리전에 배포되어야 한다면, 글로벌 rate limiting과 라우팅 정책을 어떻게 설계하시겠습니까?
Q. 금융 거래 시스템을 Event Sourcing 패턴으로 설계합니다. 모든 상태 변경을 이벤트로 저장하고, 이벤트 스트림에서 현재 상태를 재구성할 수 있어야 하며, 특정 시점의 상태 조회(temporal query)를 지원해야 합니다. Go에서 이벤트 저장소 선택, 스냅샷 전략, 이벤트 버전 관리, CQRS 패턴 적용, 그리고 이벤트 replay 시 성능 최적화 방법을 설계해주세요.
이벤트 스트림의 append-only 특성과 스냅샷을 통한 재구성 성능 개선, 그리고 read model 분리를 고려해보세요.
이벤트 저장소로 PostgreSQL의 append-only 테이블을 사용하며, aggregate_id와 version으로 파티셔닝하여 특정 aggregate의 이벤트를 빠르게 조회합니다. 이벤트는 JSON 형태로 직렬화하되, event_type과 schema_version을 함께 저장하여 버전 관리를 수행하고, 이전 버전 이벤트는 upcasting으로 변환합니다. 스냅샷은 이벤트 100개마다 생성하며, 별도 테이블에 저장하여 재구성 시 최근 스냅샷부터 이후 이벤트만 replay합니다. CQRS 패턴으로 write model과 read model을 분리하고, 이벤트 발행 시 Kafka로 전송하여 read model을 비동기로 업데이트합니다. Temporal query는 특정 timestamp 이전 이벤트만 필터링하여 재구성하며, 자주 조회되는 시점은 별도 스냅샷으로 캐싱합니다. 이벤트 replay 시 goroutine pool로 여러 aggregate를 병렬 처리하고, 메모리 사용량 제어를 위해 배치 단위로 처리합니다.
- • Append-only 이벤트 저장소와 파티셔닝 전략
- • 스냅샷 기반 재구성 성능 최적화
- • 이벤트 버전 관리와 upcasting
- • CQRS로 read/write model 분리 및 비동기 동기화
금융 거래, 주문 처리 등 모든 변경 이력을 감사해야 하고 과거 시점 상태 복원이 필요한 도메인에서 사용됩니다.
이벤트 스트림이 수백만 개로 증가했을 때, 특정 aggregate의 재구성 성능을 유지하기 위한 추가 최적화 방안은 무엇입니까?
Q. 수억 개의 상품 데이터에서 전문 검색(full-text search)과 필터링을 제공하는 검색 API를 설계합니다. 키워드 검색, 카테고리/가격/브랜드 필터, 정렬, 페이징을 지원하며, 검색 결과는 100ms 이내에 반환되어야 합니다. Elasticsearch와 Go 애플리케이션 간 아키텍처, 검색 쿼리 최적화, 캐싱 전략, 인덱스 설계, 그리고 실시간 상품 업데이트 반영 방법을 설명해주세요.
Elasticsearch의 인덱스 구조와 검색 쿼리 패턴, 그리고 캐시 가능한 검색 결과의 특성을 고려해보세요.
Elasticsearch에 상품 인덱스를 생성하며, 샤딩은 상품 ID 기반으로 하고 replica를 3개 유지하여 읽기 성능을 확보합니다. 검색 쿼리는 multi_match로 상품명/설명을 검색하고, bool query로 필터를 조합하며, function_score로 인기도/재고 상태를 반영한 랭킹을 적용합니다. 자주 사용되는 검색 조합(키워드+필터)은 Redis에 캐싱하되, TTL을 짧게(1-5분) 설정하여 실시간성을 유지합니다. 페이징은 search_after를 사용하여 deep pagination 성능 문제를 해결하고, 첫 페이지는 더 공격적으로 캐싱합니다. 상품 업데이트는 Kafka로 이벤트를 받아 Go consumer가 bulk API로 배치 인덱싱하며, partial update로 변경된 필드만 갱신합니다. 검색 성능 모니터링을 위해 slow query log를 분석하고, 자주 사용되는 필터 조합은 aggregation으로 미리 계산합니다. Auto-completion은 completion suggester를 사용하고, 오타 교정은 fuzzy query로 처리합니다.
- • Elasticsearch 샤딩/레플리카 전략과 multi_match, bool query 조합
- • 자주 사용되는 검색 조합의 Redis 캐싱과 짧은 TTL
- • search_after 기반 페이징과 bulk API 배치 인덱싱
- • Kafka 기반 실시간 업데이트 반영과 partial update
이커머스, 채용 플랫폼, 부동산 검색 등 대량의 구조화된 데이터에서 복합 조건 검색이 필요한 서비스에서 사용됩니다.
검색 결과의 개인화(사용자별 맞춤 랭킹)를 추가한다면 아키텍처를 어떻게 확장하시겠습니까?
Q. 매일 밤 수천만 건의 데이터를 처리하는 배치 시스템을 Go로 구현해야 합니다. 데이터 추출, 변환, 적재(ETL) 과정이 있으며, 중간 실패 시 재시작 가능해야 하고, 처리 진행 상황을 모니터링할 수 있어야 합니다. Worker pool 설계, 작업 분할 전략, 체크포인팅, 에러 처리, 그리고 처리 시간 단축을 위한 최적화 방법을 포함한 전체 아키텍처를 설계해주세요.
데이터를 청크 단위로 분할하고, 각 청크의 처리 상태를 추적하며, goroutine pool로 병렬 처리하는 구조를 고려해보세요.
데이터를 ID 범위 기반으로 청크(예: 10만 건)로 분할하고, 각 청크를 독립적인 작업 단위로 처리합니다. Worker pool은 GOMAXPROCS의 2배 크기로 생성하며, buffered channel로 작업 큐를 구현하고, semaphore 패턴으로 동시 실행 수를 제어합니다. 각 청크 처리 전후로 상태를 DB에 기록(pending, processing, completed, failed)하여 체크포인팅하고, 재시작 시 미완료 청크만 재처리합니다. Extract 단계는 DB cursor를 사용하여 메모리 효율적으로 읽고, Transform 단계는 CPU-bound이므로 goroutine으로 병렬화하며, Load 단계는 bulk insert로 배치 처리합니다. 에러는 재시도 가능한 에러(네트워크 등)와 불가능한 에러(데이터 오류)를 구분하여, 전자는 exponential backoff로 재시도하고 후자는 dead letter queue에 저장합니다. 처리 진행률은 Redis에 실시간으로 업데이트하고, Prometheus 메트릭으로 처리 속도와 에러율을 모니터링합니다. 성능 최적화를 위해 DB connection pool을 충분히 확보하고, 네트워크 I/O는 비동기로 처리하며, 메모리 사용량은 pprof로 프로파일링합니다.
- • 청크 단위 작업 분할과 상태 기반 체크포인팅
- • Worker pool과 semaphore 패턴으로 동시성 제어
- • 단계별 최적화(cursor 읽기, 병렬 변환, bulk insert)
- • 재시도 가능 에러 구분과 exponential backoff
데이터 웨어하우스 적재, 일일 통계 집계, 대량 알림 발송 등 대용량 데이터를 주기적으로 처리하는 백그라운드 작업에서 사용됩니다.
배치 처리 중 데이터 소스의 스키마가 변경되었을 때 어떻게 대응하시겠습니까?
Q. 수천 개의 고객사가 사용하는 SaaS 플랫폼을 Go로 구축합니다. 각 테넌트는 독립적인 데이터 격리가 필요하며, 일부 대형 고객은 전용 리소스를, 소형 고객은 공유 리소스를 사용해야 합니다. 데이터베이스 격리 전략(DB per tenant vs Schema per tenant vs Row-level), 테넌트 식별 및 라우팅, 리소스 할당, 그리고 테넌트별 설정 관리 방법을 설계해주세요.
테넌트 규모에 따른 하이브리드 격리 전략과 미들웨어 기반 테넌트 컨텍스트 전파를 고려해보세요.
하이브리드 격리 전략을 적용하여, 대형 고객(월 매출 상위 5%)은 전용 DB 인스턴스를, 중형 고객은 schema per tenant를, 소형 고객은 row-level 격리(tenant_id 컬럼)를 사용합니다. 요청 시 JWT 또는 API key에서 tenant_id를 추출하고, 미들웨어에서 context.Context에 테넌트 정보를 주입하여 모든 하위 레이어로 전파합니다. 데이터 접근 레이어는 tenant_id를 자동으로 모든 쿼리에 추가하는 wrapper를 제공하며, 잘못된 테넌트 데이터 접근을 방지합니다. 테넌트별 설정(feature flag, rate limit, 스토리지 quota)은 Redis에 캐싱하고, 변경 시 pub/sub으로 모든 인스턴스에 전파합니다. 리소스 할당은 테넌트별 goroutine pool과 connection pool을 분리하여 noisy neighbor 문제를 방지하고, cgroup으로 CPU/메모리 제한을 설정합니다. 테넌트 마이그레이션(소형→중형, 중형→대형)은 blue-green 방식으로 수행하며, 마이그레이션 중에도 서비스 중단 없이 처리합니다. 모니터링은 테넌트별 메트릭을 수집하고, 이상 패턴 감지 시 자동으로 리소스를 조정합니다.
- • 테넌트 규모별 하이브리드 격리 전략(전용 DB, schema, row-level)
- • 미들웨어 기반 테넌트 컨텍스트 전파와 자동 쿼리 필터링
- • 테넌트별 리소스 격리로 noisy neighbor 방지
- • Redis 캐싱과 pub/sub 기반 설정 관리
B2B SaaS 플랫폼에서 수천 개 고객사의 데이터를 안전하게 격리하면서도 효율적으로 리소스를 공유할 때 사용됩니다.
테넌트 간 데이터 공유가 필요한 기능(예: 마켓플레이스)을 추가한다면 격리 모델을 어떻게 확장하시겠습니까?
Q. 복잡한 관계형 데이터를 제공하는 GraphQL API를 Go로 구현합니다. N+1 쿼리 문제, 깊은 중첩 쿼리의 성능 이슈, 쿼리 복잡도 제한, 그리고 DataLoader 패턴 구현을 포함한 전체 아키텍처를 설계해주세요. REST API 대비 GraphQL의 트레이드오프와 실무 적용 시 고려사항도 함께 설명해주세요.
DataLoader를 통한 배치 로딩과 쿼리 복잡도 계산 기반 rate limiting을 고려해보세요.
gqlgen 라이브러리로 schema-first 방식으로 GraphQL 서버를 구현하고, resolver에서 DataLoader 패턴을 적용하여 N+1 문제를 해결합니다. DataLoader는 요청 단위로 생성되며, 동일 엔티티의 여러 요청을 배치로 모아 한 번의 DB 쿼리로 처리합니다. 각 resolver는 context에서 DataLoader를 가져와 사용하고, 10ms의 배치 윈도우 내에서 요청을 수집합니다. 쿼리 복잡도는 각 필드에 가중치를 부여하고, 중첩 깊이와 배열 크기를 곱하여 계산하며, 임계값 초과 시 요청을 거부합니다. 깊은 중첩 쿼리는 최대 depth를 5로 제한하고, pagination을 강제하여 대량 데이터 조회를 방지합니다. 자주 사용되는 쿼리 패턴은 Redis에 캐싱하되, 쿼리 변수를 키에 포함하여 정확한 캐시 히트를 보장합니다. REST 대비 장점은 클라이언트가 필요한 데이터만 요청하여 over-fetching을 방지하지만, 캐싱이 어렵고 쿼리 복잡도 관리가 필요한 트레이드오프가 있습니다. 실무에서는 public API보다는 internal API나 BFF(Backend for Frontend) 패턴에 적합합니다.
- • DataLoader 패턴으로 N+1 문제 해결 및 배치 로딩
- • 쿼리 복잡도 계산과 depth 제한으로 성능 보호
- • 요청 단위 DataLoader 생성과 배치 윈도우 설정
- • REST 대비 트레이드오프 이해와 적합한 사용 사례 판단
모바일 앱과 웹의 요구사항이 다른 BFF 레이어나, 복잡한 관계형 데이터를 유연하게 조회해야 하는 대시보드에서 사용됩니다.
GraphQL subscription을 추가하여 실시간 데이터 푸시를 구현한다면 어떤 아키텍처를 사용하시겠습니까?
Q. 다중 리전에 배포된 Go 웹 애플리케이션의 세션 관리 시스템을 설계합니다. 사용자는 어느 리전에서든 동일한 세션을 유지해야 하며, 세션 데이터는 보안이 중요하고, 로그아웃 시 즉시 무효화되어야 합니다. 세션 저장소 선택, 세션 ID 생성 및 검증, 크로스 리전 동기화, 보안 고려사항, 그리고 세션 만료 정책을 포함한 설계를 제시해주세요.
Redis Cluster의 글로벌 복제와 JWT vs 서버 세션의 트레이드오프를 고려해보세요.
세션 저장소로 Redis Cluster를 사용하며, 각 리전에 replica를 배치하고 비동기 복제로 크로스 리전 동기화를 수행합니다. 세션 ID는 crypto/rand로 생성한 32바이트 무작위 값을 base64 인코딩하여 사용하고, httponly와 secure 플래그가 설정된 쿠키로 전송합니다. 세션 데이터는 민감 정보(비밀번호 등)를 제외하고 저장하며, 필요 시 AES로 암호화합니다. 세션 만료는 Redis TTL로 관리하고, sliding window 방식으로 활동 시마다 TTL을 갱신하여 사용자 경험을 개선합니다. 로그아웃 시 해당 세션을 즉시 삭제하고, 블랙리스트를 별도로 관리하여 탈취된 세션 ID의 재사용을 방지합니다. CSRF 방지를 위해 각 세션에 CSRF 토큰을 포함하고, SameSite 쿠키 속성을 설정합니다. 대안으로 JWT 기반 stateless 세션도 고려할 수 있으나, 즉시 무효화가 어려운 단점이 있어 민감한 작업에는 서버 세션이 적합합니다. 세션 접근 패턴을 모니터링하여 이상 징후(동시 다중 지역 접근)를 감지하고 자동으로 세션을 무효화합니다.
- • Redis Cluster 기반 다중 리전 세션 저장소와 비동기 복제
- • 암호학적으로 안전한 세션 ID 생성과 httponly, secure 쿠키
- • Sliding window TTL과 로그아웃 시 즉시 무효화
- • CSRF 토큰과 SameSite 속성으로 보안 강화
글로벌 서비스에서 사용자가 여러 리전을 이동하며 접속해도 끊김 없는 경험을 제공하고, 보안을 유지해야 할 때 사용됩니다.
세션 고정 공격(session fixation)과 세션 하이재킹을 방어하기 위한 추가 보안 조치는 무엇입니까?
Q. IoT 센서에서 초당 10만 개의 시계열 데이터 포인트를 수집하고, 실시간 집계와 이상 탐지를 수행하는 시스템을 Go로 설계합니다. 데이터 수집, 저장, 다운샘플링, 실시간 쿼리, 그리고 장기 보관 전략을 포함한 전체 아키텍처를 제시해주세요. InfluxDB, TimescaleDB 등 시계열 DB 선택 기준도 함께 설명해주세요.
시계열 데이터의 특성(append-only, 시간 기반 파티셔닝)과 집계 레벨별 다운샘플링을 고려해보세요.
데이터 수집은 Kafka를 통해 수행하며, Go consumer가 배치로 읽어 TimescaleDB에 저장합니다. TimescaleDB는 시간 기반 자동 파티셔닝(hypertable)과 압축을 지원하여 선택했습니다. 원본 데이터는 1분 단위로 파티션을 생성하고, 7일 후 압축하여 스토리지를 절감합니다. 실시간 집계는 Go 애플리케이션 메모리에서 1분/5분/1시간 단위로 수행하고, continuous aggregates로 DB에도 저장합니다. 다운샘플링은 시간이 지날수록 해상도를 낮추어(1초→1분→1시간→1일) 저장 공간을 최적화하며, retention policy로 오래된 고해상도 데이터는 자동 삭제합니다. 이상 탐지는 sliding window 기반 통계(평균, 표준편차)를 실시간 계산하고, z-score가 임계값을 초과하면 알림을 발송합니다. 실시간 쿼리는 최근 데이터만 조회하므로 인덱스를 활용하여 빠르게 처리하고, 장기 트렌드 분석은 다운샘플링된 데이터를 사용합니다. 대량 쓰기 성능을 위해 batch insert를 사용하고, connection pool을 충분히 확보하며, WAL 설정을 최적화합니다. 장기 보관이 필요한 데이터는 S3로 아카이빙하고, Parquet 포맷으로 변환하여 저장합니다.
- • TimescaleDB hypertable과 시간 기반 자동 파티셔닝
- • 시간 경과에 따른 다운샘플링과 retention policy
- • 실시간 집계와 continuous aggregates 조합
- • Sliding window 기반 이상 탐지와 z-score 계산
IoT 모니터링, 서버 메트릭 수집, 주식 시세 데이터 처리 등 대량의 시계열 데이터를 실시간으로 수집하고 분석해야 할 때 사용됩니다.
센서 수가 100배 증가하여 초당 1000만 데이터 포인트를 처리해야 한다면 아키텍처를 어떻게 확장하시겠습니까?
Q. Go 마이크로서비스의 무중단 배포를 위한 Blue-Green 배포 시스템을 설계합니다. 트래픽 전환, 헬스 체크, 롤백 전략, 데이터베이스 마이그레이션 처리, 그리고 배포 자동화를 포함한 전체 프로세스를 설명해주세요. Canary 배포와 비교했을 때의 장단점도 함께 제시해주세요.
로드 밸런서의 트래픽 라우팅과 backward compatible 스키마 변경을 고려해보세요.
Blue(현재 버전)와 Green(새 버전) 환경을 독립적으로 구성하고, 로드 밸런서(ALB, Nginx)로 트래픽을 제어합니다. Green 환경 배포 후 헬스 체크 엔드포인트(/health, /ready)로 서비스 준비 상태를 확인하고, smoke test로 핵심 기능을 검증합니다. 검증 완료 후 로드 밸런서 설정을 변경하여 트래픽을 Blue→Green으로 전환하며, 전환은 즉시 이루어지므로 일부 요청만 새 버전으로 보내는 Canary 배포보다 단순합니다. 롤백은 로드 밸런서 설정을 되돌려 Blue로 트래픽을 재전환하면 되므로 빠르게 수행됩니다. DB 마이그레이션은 backward compatible하게 수행하여 Blue, Green 모두 동작하도록 하며, 컬럼 추가는 nullable로 하고 삭제는 다음 배포에서 수행합니다. 배포 자동화는 CI/CD 파이프라인에서 Green 환경 빌드→배포→헬스 체크→트래픽 전환→Blue 환경 종료 순서로 진행합니다. Canary 배포 대비 장점은 구현이 단순하고 롤백이 빠르지만, 단점은 인프라 비용이 2배이고 문제 발생 시 전체 사용자에게 영향을 준다는 점입니다. 실무에서는 안정성이 검증된 서비스는 Blue-Green, 새로운 기능은 Canary를 사용합니다.
- • 독립적인 Blue/Green 환경과 로드 밸런서 기반 트래픽 전환
- • 헬스 체크와 smoke test로 배포 검증
- • Backward compatible DB 마이그레이션
- • Canary 대비 단순하지만 인프라 비용 2배
프로덕션 서비스의 무중단 배포가 필수적이고, 빠른 롤백이 중요한 미션 크리티컬 시스템에서 사용됩니다.
Blue-Green 배포 중 세션 데이터나 in-memory 캐시는 어떻게 처리하시겠습니까?
Q. 위치 기반 서비스를 위한 API를 설계합니다. 사용자 현재 위치 기준 반경 N km 내의 매장을 검색하고, 거리순으로 정렬하여 반환해야 합니다. 수백만 개의 매장 데이터를 효율적으로 처리하기 위한 데이터베이스 선택, 인덱싱 전략, 거리 계산 최적화, 캐싱 방법, 그리고 API 설계를 제시해주세요.
공간 인덱스(Geospatial Index)와 bounding box 기반 필터링을 먼저 수행한 후 정확한 거리 계산을 고려해보세요.
PostgreSQL의 PostGIS 확장을 사용하여 지리공간 데이터를 저장하고, GIST 인덱스로 공간 쿼리를 최적화합니다. 매장 위치는 GEOGRAPHY 타입으로 저장하여 지구 곡률을 반영한 정확한 거리 계산을 수행합니다. 검색 쿼리는 먼저 ST_DWithin 함수로 반경 내 매장을 필터링하고, ST_Distance로 정확한 거리를 계산하여 정렬합니다. Bounding box 기반 초기 필터링으로 계산량을 줄이고, 인덱스 스캔을 활용합니다. 자주 검색되는 지역(핫스팟)은 Redis Geospatial 자료구조로 캐싱하며, GEORADIUS 명령으로 빠르게 조회합니다. 캐시 무효화는 매장 정보 변경 시 해당 매장 주변 캐시를 삭제하는 방식으로 처리합니다. API는 위도, 경도, 반경을 파라미터로 받고, 페이징을 지원하며, 응답에는 매장 정보와 거리를 포함합니다. 거리 계산은 Haversine 공식보다 정확한 Vincenty 공식을 사용하되, 성능이 중요한 경우 근사값으로 Haversine을 사용합니다. 대용량 데이터 처리를 위해 매장을 지역별로 파티셔닝하고, 검색 시 관련 파티션만 조회하여 성능을 개선합니다.
- • PostGIS와 GIST 인덱스로 공간 쿼리 최적화
- • ST_DWithin 필터링 후 ST_Distance 정확한 계산
- • Redis Geospatial로 핫스팟 캐싱
- • 지역별 파티셔닝으로 대용량 데이터 처리
배달 앱, 택시 호출, 주변 매장 찾기 등 위치 기반으로 가까운 대상을 검색하고 거리를 계산해야 하는 서비스에서 사용됩니다.
실시간으로 이동하는 배달원의 위치를 추적하고 고객에게 보여주는 기능을 추가한다면 어떻게 설계하시겠습니까?
아직 댓글이 없습니다. 첫 번째 댓글을 남겨보세요!