JavaScript 미드레벨 시스템 설계 면접
새 면접Q. RESTful API에서 페이지네이션을 구현할 때 Offset 기반 방식과 Cursor 기반 방식의 차이점을 설명하고, 각각의 장단점과 어떤 상황에서 어떤 방식을 선택해야 하는지 실무 관점에서 설명해주세요.
Offset 기반 방식은 page와 limit 파라미터로 데이터를 건너뛰는 방식으로 구현이 간단하지만 데이터 변경 시 중복/누락이 발생할 수 있습니다. Cursor 기반 방식은 마지막 항목의 고유 식별자를 기준으로 다음 데이터를 가져오는 방식으로 데이터 일관성이 보장되지만 특정 페이지로 직접 이동이 어렵습니다. 실시간으로 데이터가 자주 변경되는 소셜 피드나 채팅 메시지는 Cursor 방식이 적합하고, 검색 결과나 관리자 페이지처럼 페이지 번호가 필요한 경우 Offset 방식이 적합합니다. 대용량 데이터에서는 Cursor 방식이 인덱스를 효율적으로 활용하여 성능이 더 우수합니다.
- • Offset 방식: LIMIT/OFFSET 사용, 구현 간단, 데이터 변경 시 일관성 문제
- • Cursor 방식: 고유 식별자 기준, 데이터 일관성 보장, 인덱스 활용 효율적
- • 선택 기준: 실시간 데이터 변경 빈도, 페이지 이동 필요성, 데이터 규모
대용량 데이터에서 Cursor 기반 페이지네이션을 구현할 때 복합 정렬 조건(예: 생성일 DESC, ID DESC)이 있는 경우 어떻게 처리해야 하나요?
Q. 다국어를 지원하는 전자상거래 플랫폼에서 상품 정보를 저장할 때, 다국어 데이터를 관리하는 여러 DB 설계 방식(Single Table, Translation Table, JSON Column)의 장단점을 비교하고, 각 방식의 쿼리 성능과 확장성 측면에서 어떤 트레이드오프가 있는지 설명해주세요.
Single Table 방식은 각 언어별 컬럼을 추가하는 방식으로 쿼리가 간단하지만 언어 추가 시 스키마 변경이 필요하고 컬럼 수가 급격히 증가합니다. Translation Table 방식은 별도 번역 테이블로 JOIN하는 방식으로 정규화되어 확장성이 좋지만 JOIN 비용이 발생하고 쿼리가 복잡해집니다. JSON Column 방식은 하나의 컬럼에 모든 언어를 JSON으로 저장하여 스키마 유연성이 높지만 JSON 내부 검색 성능이 떨어지고 인덱싱이 제한적입니다. 실무에서는 Translation Table 방식을 기본으로 하되, 자주 조회되는 기본 언어는 메인 테이블에 두고 나머지는 번역 테이블로 분리하는 하이브리드 방식을 많이 사용합니다.
- • Single Table: 쿼리 단순, 스키마 변경 필요, 컬럼 수 증가 문제
- • Translation Table: 정규화 우수, JOIN 비용, 확장성 좋음
- • JSON Column: 스키마 유연, 검색 성능 저하, 인덱싱 제한
- • 하이브리드 접근: 기본 언어는 메인 테이블, 나머지는 번역 테이블
Translation Table 방식을 사용할 때 N+1 쿼리 문제를 어떻게 해결할 수 있으며, 캐싱 전략은 어떻게 설계하시겠습니까?
Q. Redis를 활용한 캐싱 시스템에서 Cache Stampede 문제가 무엇인지 설명하고, 이를 해결하기 위한 방법들(Lock, Probabilistic Early Expiration, Cache Warming)을 비교한 뒤 실무에서 어떤 방식을 선택할지 판단 기준을 제시해주세요.
Cache Stampede는 인기 있는 캐시 키가 만료될 때 대량의 요청이 동시에 DB에 접근하여 시스템에 과부하를 일으키는 현상입니다. Lock 방식은 첫 번째 요청만 DB 조회를 허용하고 나머지는 대기시키는 방법으로 DB 부하는 줄지만 응답 지연이 발생할 수 있습니다. Probabilistic Early Expiration은 만료 시간 전에 확률적으로 캐시를 갱신하여 만료 시점 분산을 유도하지만 구현이 복잡합니다. Cache Warming은 만료 전 백그라운드에서 미리 갱신하는 방식으로 가장 안정적이지만 추가 리소스가 필요합니다. 실무에서는 트래픽 패턴에 따라 고트래픽 핵심 데이터는 Cache Warming을, 중간 수준은 Lock 방식을, 저트래픽은 기본 TTL만 사용하는 것이 효율적입니다.
- • Cache Stampede: 캐시 만료 시 동시 다발적 DB 접근으로 인한 과부하
- • Lock 방식: 첫 요청만 허용, 응답 지연 가능
- • Probabilistic Early Expiration: 만료 시점 분산, 구현 복잡
- • Cache Warming: 백그라운드 갱신, 안정적이나 리소스 필요
분산 환경에서 여러 서버가 동시에 캐시를 갱신하려고 할 때 Redis의 어떤 기능을 활용하여 분산 락을 구현할 수 있나요?
Q. Node.js 기반 API 서버에서 Rate Limiting을 구현할 때 고려해야 할 사항들을 설명하고, Token Bucket과 Sliding Window 알고리즘의 차이점 및 각각의 장단점을 실무 관점에서 비교해주세요.
Rate Limiting 구현 시 사용자 식별 방법(IP, API Key, User ID), 제한 단위(초당, 분당, 시간당), 분산 환경 동기화, 예외 처리 등을 고려해야 합니다. Token Bucket 알고리즘은 고정된 속도로 토큰이 채워지고 요청마다 토큰을 소비하는 방식으로 버스트 트래픽을 허용하며 구현이 간단하지만 순간적인 과부하가 발생할 수 있습니다. Sliding Window 알고리즘은 시간 윈도우를 슬라이딩하며 요청 수를 계산하는 방식으로 더 정확한 제한이 가능하지만 메모리 사용량이 많고 계산 비용이 높습니다. 실무에서는 일반적인 API는 Token Bucket으로 충분하며, 민감한 인증 API나 결제 API는 Sliding Window를 사용하여 정확한 제어가 필요합니다.
- • 고려사항: 사용자 식별, 제한 단위, 분산 환경 동기화, 예외 처리
- • Token Bucket: 버스트 허용, 구현 간단, 순간 과부하 가능
- • Sliding Window: 정확한 제한, 메모리 사용량 높음, 계산 비용
- • 선택 기준: API 민감도, 트래픽 패턴, 시스템 리소스
Redis를 사용하여 분산 환경에서 Rate Limiting을 구현할 때 어떤 자료구조와 명령어를 사용하는 것이 효율적이며, Race Condition을 어떻게 방지할 수 있나요?
Q. 마이크로서비스 아키텍처에서 서비스 간 통신 방식으로 동기 REST API와 비동기 메시지 큐(RabbitMQ, Kafka)의 장단점을 비교하고, 각각 어떤 상황에서 적합한지 설명한 뒤, 두 방식을 혼용할 때 고려해야 할 데이터 일관성 문제와 해결 방안을 제시해주세요.
동기 REST API는 즉각적인 응답이 가능하고 구현이 간단하지만 서비스 간 강한 결합이 생기고 한 서비스 장애가 전파될 수 있습니다. 비동기 메시지 큐는 서비스 간 결합도가 낮고 장애 격리가 가능하며 트래픽 버퍼링이 되지만 복잡도가 높고 즉각적인 결과 확인이 어렵습니다. 실시간 조회나 인증처럼 즉각적인 응답이 필요한 경우 REST를 사용하고, 주문 처리나 이메일 발송처럼 비동기 처리가 가능한 경우 메시지 큐를 사용합니다. 두 방식을 혼용할 때는 Saga 패턴으로 분산 트랜잭션을 관리하고, 이벤트 소싱으로 상태 변경을 추적하며, 멱등성 보장과 보상 트랜잭션으로 데이터 일관성을 유지해야 합니다.
- • REST API: 즉각 응답, 강한 결합, 장애 전파 위험
- • 메시지 큐: 낮은 결합도, 장애 격리, 복잡도 증가, 비동기 처리
- • 선택 기준: 응답 즉시성, 비즈니스 요구사항, 장애 허용 범위
- • 일관성 해결: Saga 패턴, 이벤트 소싱, 멱등성, 보상 트랜잭션
Saga 패턴에서 Choreography 방식과 Orchestration 방식의 차이점은 무엇이며, 각각 어떤 상황에서 더 적합한가요?
아직 댓글이 없습니다. 첫 번째 댓글을 남겨보세요!