Java 주니어 시스템 설계 기술면접

Java 주니어 (1~3년) 시스템 설계 5문항 조회수 114 · 2026-05-13 (수) 03:10:52
1 API 버전 관리
Medium

Q. REST API를 운영 중인 서비스에서 기존 API의 응답 구조를 변경해야 하는 상황입니다. 기존 클라이언트에 영향을 주지 않으면서 새로운 API를 제공하기 위한 버전 관리 전략을 설명하고, 각 방식의 장단점을 말씀해주세요.

A. 모범답안

API 버전 관리는 크게 세 가지 방식이 있습니다. 첫째, URL 경로에 버전을 포함하는 방식(/api/v1/users, /api/v2/users)으로 가장 명시적이고 직관적이지만 URL이 복잡해질 수 있습니다. 둘째, 헤더를 이용한 방식(Accept: application/vnd.company.v1+json)으로 URL을 깔끔하게 유지할 수 있지만 테스트와 디버깅이 어렵습니다. 셋째, 쿼리 파라미터 방식(/api/users?version=1)으로 구현이 간단하지만 RESTful 원칙에서 벗어납니다. 주니어 개발자에게는 명시적이고 캐싱이 용이한 URL 경로 방식을 권장합니다.

핵심 포인트
  • • URL 경로 버전 관리가 가장 명시적이고 직관적
  • • 헤더 방식은 URL을 깔끔하게 유지하지만 디버깅이 어려움
  • • 기존 클라이언트 호환성 유지가 최우선
  • • 버전 관리 정책을 초기에 수립하는 것이 중요
Follow-up 질문

만약 v1 API를 deprecate하고 v2로 완전히 전환해야 한다면, 어떤 단계적 전략을 사용하시겠습니까?

2 DB 인덱스 설계
Medium

Q. 게시판 서비스에서 게시글 목록을 조회할 때 작성일 기준 최신순 정렬과 특정 카테고리 필터링이 자주 발생합니다. 이 경우 데이터베이스 인덱스를 어떻게 설계하시겠으며, 인덱스 설계 시 고려해야 할 사항을 설명해주세요.

A. 모범답안

카테고리와 작성일을 함께 조회하는 쿼리가 빈번하므로 복합 인덱스(category_id, created_at DESC)를 생성하는 것이 효율적입니다. 인덱스 컬럼 순서는 카디널리티가 낮은 카테고리를 먼저 두고, 정렬 기준인 작성일을 뒤에 배치합니다. 인덱스 설계 시 고려사항으로는 첫째, 조회 성능 향상과 INSERT/UPDATE 시 성능 저하의 트레이드오프를 고려해야 하고, 둘째, 인덱스가 차지하는 스토리지 공간을 고려해야 하며, 셋째, 실제 쿼리 실행 계획을 EXPLAIN으로 확인하여 인덱스가 제대로 사용되는지 검증해야 합니다.

핵심 포인트
  • • 복합 인덱스는 WHERE와 ORDER BY 조건을 모두 고려하여 설계
  • • 인덱스 컬럼 순서는 카디널리티와 쿼리 패턴을 고려
  • • 인덱스는 조회 성능을 높이지만 쓰기 성능을 저하시킴
  • • EXPLAIN을 통한 실행 계획 검증 필수
Follow-up 질문

인덱스를 생성했는데도 쿼리가 인덱스를 타지 않는 경우는 어떤 상황이 있을까요?

3 파일 업로드 설계
Medium

Q. 사용자가 프로필 이미지를 업로드하는 기능을 구현해야 합니다. 파일 저장 위치, 파일명 생성 전략, 허용 파일 타입 검증, 파일 크기 제한 등을 고려한 설계 방안을 설명해주세요.

A. 모범답안

파일 저장은 서버 로컬 스토리지보다 AWS S3 같은 객체 스토리지 사용을 권장하며, 확장성과 CDN 연동이 용이합니다. 파일명은 UUID나 타임스탬프를 활용해 유니크하게 생성하고, 원본 파일명은 DB에 별도 저장하여 중복과 보안 문제를 방지합니다. 파일 타입은 확장자뿐 아니라 MIME 타입과 매직 넘버를 검증하여 위장 파일을 차단하고, Spring의 MultipartFile을 사용해 파일 크기를 제한합니다. DB에는 파일 메타데이터(파일명, 크기, 경로, 업로드 시간)를 저장하고, 실제 파일은 스토리지에 분리 저장하는 구조가 적합합니다.

핵심 포인트
  • • 객체 스토리지 사용으로 확장성 확보
  • • UUID 기반 파일명으로 중복 방지 및 보안 강화
  • • MIME 타입과 매직 넘버로 파일 타입 검증
  • • 파일 메타데이터는 DB에, 실제 파일은 스토리지에 분리 저장
Follow-up 질문

대용량 파일 업로드 시 타임아웃이나 메모리 문제를 방지하기 위한 방법은 무엇이 있을까요?

4 페이징 처리
Easy

Q. 수천 건 이상의 데이터를 조회하는 API에서 페이징 처리를 구현해야 합니다. Offset 기반 페이징과 Cursor 기반 페이징의 차이점을 설명하고, 각각 어떤 상황에 적합한지 말씀해주세요.

A. 모범답안

Offset 기반 페이징은 LIMIT과 OFFSET을 사용하여 페이지 번호로 데이터를 조회하는 방식으로, 구현이 간단하고 특정 페이지로 바로 이동할 수 있지만 데이터가 많아질수록 성능이 저하되고 데이터 변경 시 중복이나 누락이 발생할 수 있습니다. Cursor 기반 페이징은 마지막 조회 항목의 ID나 타임스탬프를 기준으로 다음 데이터를 조회하는 방식으로, 대용량 데이터에서도 일정한 성능을 보장하고 실시간 데이터 변경에 안정적이지만 특정 페이지로 직접 이동할 수 없습니다. 일반적인 게시판은 Offset 방식을, 무한 스크롤이나 실시간 피드는 Cursor 방식을 사용합니다.

핵심 포인트
  • • Offset 페이징은 구현이 간단하지만 대용량 데이터에서 성능 저하
  • • Cursor 페이징은 일정한 성능 보장하지만 특정 페이지 이동 불가
  • • Offset은 페이지 번호 UI에, Cursor는 무한 스크롤에 적합
  • • 데이터 규모와 UX 요구사항에 따라 선택
Follow-up 질문

Spring Data JPA에서 Pageable을 사용한 페이징 구현 방법을 설명해주세요.

5 Rate Limiting
Hard

Q. 공개 API를 제공하는 서비스에서 특정 사용자가 과도한 요청으로 서버 자원을 독점하는 것을 방지하기 위해 Rate Limiting을 구현하려고 합니다. Rate Limiting의 주요 알고리즘과 Spring에서 구현 가능한 방법을 설명해주세요.

A. 모범답안

Rate Limiting의 주요 알고리즘으로는 첫째, Token Bucket 방식으로 일정 시간마다 토큰을 채우고 요청마다 토큰을 소비하는 방식이며 버스트 트래픽을 허용합니다. 둘째, Fixed Window 방식으로 고정된 시간 창에서 요청 수를 카운트하며 구현이 간단하지만 경계 시점에 2배 요청이 가능한 단점이 있습니다. 셋째, Sliding Window 방식으로 시간 창을 이동시키며 카운트하여 더 정확하지만 메모리 사용량이 많습니다. Spring에서는 Bucket4j 라이브러리를 사용하거나, Redis를 활용해 분산 환경에서 카운터를 관리하고, Interceptor나 Filter에서 사용자별 요청 수를 체크하여 제한을 초과하면 429 Too Many Requests 응답을 반환합니다.

핵심 포인트
  • • Token Bucket은 버스트 트래픽 허용으로 유연성 제공
  • • Fixed Window는 구현 간단하지만 경계 문제 존재
  • • 분산 환경에서는 Redis로 중앙 집중식 카운터 관리
  • • 429 상태 코드와 Retry-After 헤더로 클라이언트에 안내
Follow-up 질문

사용자별, IP별, API 키별로 각각 다른 Rate Limit을 적용해야 한다면 어떻게 설계하시겠습니까?

댓글 0

로그인 후 댓글을 작성할 수 있습니다.

아직 댓글이 없습니다. 첫 번째 댓글을 남겨보세요!