Java 미드레벨 시스템 설계 기술면접
새 면접Q. RESTful API를 설계할 때 버전 관리 전략에는 URI 버저닝, 헤더 버저닝, 쿼리 파라미터 버저닝 등이 있습니다. 각 방식의 장단점을 설명하고, 실무에서 하위 호환성을 유지하면서 API를 점진적으로 업데이트하기 위한 전략을 제시해주세요.
URI 버저닝(/api/v1/users)은 가장 명시적이고 직관적이며 캐싱이 용이하지만 URL이 복잡해지는 단점이 있습니다. 헤더 버저닝(Accept: application/vnd.company.v1+json)은 URL을 깔끔하게 유지하지만 테스트와 디버깅이 어렵고, 쿼리 파라미터 방식(?version=1)은 구현이 간단하지만 RESTful 원칙에 어긋납니다. 실무에서는 주로 URI 버저닝을 사용하며, Deprecated 헤더를 통해 구버전 종료 예고, 필드 추가는 하위 호환 유지, 필드 삭제나 타입 변경 시에만 새 버전 생성, 그리고 최소 6개월의 마이그레이션 기간 제공 등의 전략을 사용합니다.
- • URI 버저닝이 가장 명시적이고 캐싱에 유리함
- • 하위 호환성 유지를 위해 필드 추가는 기존 버전에서 처리
- • Deprecated 헤더와 충분한 마이그레이션 기간 제공
- • Breaking Change 발생 시에만 메이저 버전 증가
마이크로서비스 아키텍처에서 여러 서비스 간 API 버전이 다를 때 발생할 수 있는 문제와 해결 방법은 무엇인가요?
Q. 전자상거래 시스템에서 상품, 주문, 결제 테이블을 설계할 때 정규화와 반정규화의 트레이드오프를 고려해야 합니다. 주문 테이블에 상품 가격을 중복 저장할지, 상품 테이블을 참조할지 결정할 때 어떤 요소들을 고려해야 하며, 각 방식의 장단점을 설명해주세요.
주문 시점의 가격을 주문 테이블에 중복 저장하는 것이 일반적으로 권장됩니다. 상품 가격은 시간에 따라 변경되는데, 주문 내역은 구매 당시의 가격을 보존해야 하는 히스토리 데이터이기 때문입니다. 참조 방식은 데이터 중복을 제거하고 저장 공간을 절약하지만, 가격 변경 시 과거 주문 정보가 왜곡되고 JOIN 연산으로 인한 성능 저하가 발생합니다. 반정규화 방식은 데이터 정합성과 조회 성능을 보장하지만 저장 공간이 증가하며, 이는 전자상거래의 법적 요구사항(세금계산서, 영수증)을 충족하는 데도 필수적입니다. 추가로 상품명, 옵션 정보 등도 함께 스냅샷으로 저장하는 것이 좋습니다.
- • 주문은 시점 기준의 스냅샷 데이터로 가격을 중복 저장해야 함
- • 법적 요구사항과 감사 추적을 위해 히스토리 보존 필수
- • 조회 성능과 데이터 정합성이 저장 공간보다 우선
- • 상품명, 옵션 등 주요 정보도 함께 반정규화
주문 테이블이 수억 건으로 증가했을 때 성능을 유지하기 위한 파티셔닝 전략과 보관 주기 관리 방법은 무엇인가요?
Q. Redis를 활용한 캐싱 전략에서 Cache-Aside와 Write-Through 패턴의 차이점을 설명하고, 각 패턴에서 캐시와 DB 간 데이터 불일치가 발생할 수 있는 시나리오와 해결 방법을 제시해주세요. 특히 동시성 환경에서의 문제점도 함께 다뤄주세요.
Cache-Aside는 애플리케이션이 캐시를 먼저 조회하고 없으면 DB에서 읽어 캐시에 저장하는 방식으로, 읽기 중심 워크로드에 적합하지만 업데이트 시 캐시 삭제만 하므로 다음 조회까지 불일치가 존재합니다. Write-Through는 데이터 쓰기 시 캐시와 DB를 동시에 업데이트하여 일관성을 보장하지만 쓰기 지연이 발생합니다. 동시성 문제로는 Cache-Aside에서 두 스레드가 동시에 캐시 미스를 겪고 각각 DB 조회 후 다른 버전을 캐시에 저장하는 경우, 또는 업데이트와 조회가 동시에 발생해 오래된 데이터가 캐시에 남는 경우가 있습니다. 해결 방법으로는 캐시 삭제 대신 업데이트 사용, Redis의 SETNX나 Lua 스크립트를 통한 원자적 연산, TTL 설정을 통한 최종 일관성 보장, 그리고 분산 락을 활용한 동시성 제어가 있습니다.
- • Cache-Aside는 읽기 중심, Write-Through는 일관성 중심
- • 동시 업데이트로 인한 Race Condition 발생 가능
- • 캐시 삭제 후 재조회 사이의 불일치 윈도우 존재
- • Redis Lua 스크립트나 분산 락으로 원자성 보장
캐시 stampede 문제가 발생했을 때 이를 감지하고 해결하기 위한 방법은 무엇이며, 실제로 어떤 모니터링 지표를 확인해야 하나요?
Q. 사용자 수가 급증하여 단일 데이터베이스로 처리할 수 없는 상황에서 데이터베이스 샤딩을 도입하려고 합니다. Hash 기반 샤딩과 Range 기반 샤딩의 차이점을 설명하고, 샤드 키 선정 시 고려사항과 리샤딩이 필요한 상황에서의 무중단 마이그레이션 전략을 제시해주세요.
Hash 기반 샤딩은 샤드 키를 해시 함수에 넣어 균등하게 분산시키므로 데이터 밸런싱이 우수하지만 범위 조회가 어렵고 샤드 추가 시 대규모 리샤딩이 필요합니다. Range 기반 샤딩은 특정 범위로 데이터를 나누어 범위 조회에 유리하고 샤드 추가가 용이하지만 핫스팟이 발생할 수 있습니다. 샤드 키는 카디널리티가 높고, 균등 분산되며, 조회 패턴에 맞고, 변경되지 않는 값을 선택해야 합니다. 무중단 마이그레이션을 위해서는 Dual Write 방식(기존 DB와 새 샤드에 동시 쓰기), 백그라운드로 기존 데이터 마이그레이션, 애플리케이션 레벨에서 라우팅 로직 점진적 전환, 그리고 데이터 정합성 검증 후 기존 DB 제거 순서로 진행합니다. Consistent Hashing을 사용하면 샤드 추가 시 일부 데이터만 이동하면 되어 리샤딩 비용을 줄일 수 있습니다.
- • Hash 샤딩은 균등 분산, Range 샤딩은 범위 조회에 유리
- • 샤드 키는 카디널리티, 분산성, 불변성을 고려해 선정
- • Dual Write와 점진적 마이그레이션으로 무중단 전환
- • Consistent Hashing으로 리샤딩 비용 최소화
샤딩된 환경에서 여러 샤드에 걸친 트랜잭션이나 JOIN 쿼리가 필요할 때 어떻게 처리해야 하나요?
Q. JWT 기반 인증 시스템을 설계할 때 Access Token과 Refresh Token을 분리하는 이유를 설명하고, Token Refresh 과정에서 보안을 강화하기 위한 방법들을 제시해주세요. 또한 Refresh Token이 탈취되었을 때의 대응 전략도 함께 설명해주세요.
Access Token은 짧은 만료 시간(15분~1시간)으로 API 요청마다 사용되므로 탈취 위험이 높지만 피해 범위를 제한할 수 있고, Refresh Token은 긴 만료 시간(2주~1개월)으로 Access Token 재발급에만 사용하여 노출 빈도를 최소화합니다. 보안 강화 방법으로는 Refresh Token을 HttpOnly Secure Cookie에 저장, Redis에 Refresh Token 화이트리스트 관리, Refresh 시 Rotation 기법으로 새로운 Refresh Token 발급 및 기존 토큰 무효화, 그리고 IP나 User-Agent 변경 감지 등이 있습니다. Refresh Token 탈취 시에는 해당 사용자의 모든 Refresh Token 즉시 무효화, 사용자에게 알림 발송 및 비밀번호 변경 유도, 의심스러운 접근 로그 분석, 그리고 재로그인 강제 등의 대응이 필요합니다.
- • Access Token은 짧게, Refresh Token은 길게 설정하여 보안과 편의성 균형
- • Refresh Token Rotation으로 재사용 방지
- • Redis 화이트리스트로 중앙 집중식 토큰 관리
- • 탈취 감지 시 즉시 무효화 및 사용자 알림
마이크로서비스 환경에서 각 서비스가 JWT를 검증할 때 공개키 관리와 배포 전략은 어떻게 구성해야 하나요?
아직 댓글이 없습니다. 첫 번째 댓글을 남겨보세요!