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

Java 주니어 (1~3년) 시스템 설계 5문항 조회수 116 · 2026-05-28 (목) 03:10:55
1 API 설계
Medium

Q. 회원가입 API를 설계할 때, 이메일 중복 확인과 실제 회원가입을 별도의 API로 분리하는 것과 하나의 API로 통합하는 것 중 어떤 방식을 선택하시겠습니까? 각 방식의 장단점과 함께 설명해주세요.

A. 모범답안

별도 API로 분리하는 것을 선호합니다. 이메일 중복 확인 API(GET /api/users/check-email?email=xxx)와 회원가입 API(POST /api/users)를 분리하면 사용자에게 실시간 피드백을 제공할 수 있고, 각 API의 책임이 명확해집니다. 다만 두 번의 요청이 발생하므로 네트워크 오버헤드가 있고, 중복 확인과 가입 사이에 동일 이메일이 등록될 수 있는 Race Condition이 발생할 수 있습니다. 이를 방지하기 위해 DB 레벨에서 이메일 컬럼에 UNIQUE 제약조건을 추가해야 합니다. 통합 방식은 요청 횟수가 줄어들지만 UX가 떨어지고 실패 시 사용자가 전체 입력을 다시 해야 하는 단점이 있습니다.

핵심 포인트
  • • 별도 API 분리 시 실시간 피드백 제공 가능 및 단일 책임 원칙 준수
  • • Race Condition 방지를 위한 DB UNIQUE 제약조건 필수
  • • 통합 API는 요청 횟수는 적지만 UX와 에러 처리가 복잡함
  • • 비즈니스 요구사항과 UX 우선순위에 따라 선택
Follow-up 질문

이메일 중복 확인 API가 악용되어 대량의 요청이 발생할 경우 어떻게 대응하시겠습니까?

2 DB 모델링
Medium

Q. 블로그 서비스에서 게시글에 여러 개의 태그를 붙일 수 있고, 하나의 태그는 여러 게시글에 사용될 수 있습니다. 이러한 N:M 관계를 데이터베이스에서 어떻게 모델링하시겠으며, 각 테이블의 주요 컬럼과 인덱스 전략을 설명해주세요.

A. 모범답안

N:M 관계는 중간 테이블(Junction Table)을 사용하여 두 개의 1:N 관계로 분해합니다. Post 테이블(id, title, content, created_at), Tag 테이블(id, name), PostTag 테이블(post_id, tag_id)로 설계합니다. PostTag 테이블에는 post_id와 tag_id의 복합 기본키를 설정하고, 각각에 외래키 제약조건을 추가합니다. 인덱스는 PostTag 테이블에 (post_id, tag_id)와 (tag_id, post_id) 복합 인덱스를 생성하여 특정 게시글의 태그 조회와 특정 태그의 게시글 조회 모두 최적화합니다. Tag 테이블의 name 컬럼에는 UNIQUE 인덱스를 추가하여 태그 중복을 방지합니다.

핵심 포인트
  • • N:M 관계는 중간 테이블(PostTag)로 두 개의 1:N 관계로 분해
  • • PostTag 테이블에 복합 기본키(post_id, tag_id) 설정
  • • 양방향 조회를 위한 복합 인덱스 전략 적용
  • • Tag 테이블의 name에 UNIQUE 제약조건으로 중복 방지
Follow-up 질문

태그별 게시글 수를 효율적으로 조회하기 위해 어떤 방법을 사용할 수 있을까요?

3 확장성
Medium

Q. 알림 서비스를 설계할 때, 사용자에게 이메일, SMS, 푸시 알림 등 여러 채널로 메시지를 발송해야 합니다. 동기 방식과 비동기 방식 중 어떤 방식을 선택하시겠으며, 비동기 방식을 선택한다면 어떻게 구현하시겠습니까?

A. 모범답안

비동기 방식을 선택합니다. 알림 발송은 시간이 오래 걸리고 외부 API 의존성이 높아 동기 처리 시 사용자 요청 응답이 지연되기 때문입니다. Spring에서는 메시지 큐(RabbitMQ, Kafka) 또는 @Async 어노테이션을 활용하여 구현할 수 있습니다. 메시지 큐 방식은 알림 요청을 큐에 저장하고 별도의 워커가 처리하므로 확장성이 좋고 실패 시 재처리가 용이합니다. @Async는 간단한 구현이 가능하지만 서버 재시작 시 작업 손실 가능성이 있습니다. 프로덕션 환경에서는 메시지 큐 방식을 권장하며, 알림 발송 결과는 별도 테이블에 기록하여 추적 가능하도록 설계합니다.

핵심 포인트
  • • 비동기 방식으로 사용자 요청 응답 시간 단축
  • • 메시지 큐(RabbitMQ, Kafka) 활용하여 확장성과 안정성 확보
  • • 실패 시 재처리 메커니즘과 알림 발송 이력 관리
  • • @Async는 간단하지만 프로덕션에서는 메시지 큐 권장
Follow-up 질문

메시지 큐를 사용할 때 동일한 알림이 중복으로 발송되는 것을 방지하려면 어떻게 해야 할까요?

4 캐싱
Medium

Q. 실시간 랭킹 시스템을 구현할 때, 사용자 점수가 자주 업데이트되고 랭킹 조회도 빈번하게 발생합니다. 데이터베이스만 사용하는 것과 Redis 같은 인메모리 캐시를 함께 사용하는 것의 차이를 설명하고, Redis를 사용한다면 어떤 자료구조를 활용하시겠습니까?

A. 모범답안

데이터베이스만 사용하면 매번 ORDER BY와 LIMIT 쿼리를 실행해야 하므로 조회 성능이 떨어지고 DB 부하가 높아집니다. Redis를 사용하면 Sorted Set 자료구조를 활용하여 O(log N) 시간복잡도로 랭킹 조회와 점수 업데이트가 가능합니다. ZADD 명령어로 사용자 점수를 추가/업데이트하고, ZREVRANGE로 상위 랭킹을 조회하며, ZRANK로 특정 사용자의 순위를 확인할 수 있습니다. 다만 Redis는 휘발성이므로 주기적으로 DB에 동기화하거나 RDB/AOF 영속성 옵션을 설정해야 합니다. 실시간성이 중요한 랭킹은 Redis를 primary로 사용하고, DB는 백업 및 통계 용도로 활용하는 것이 효율적입니다.

핵심 포인트
  • • DB만 사용 시 ORDER BY 쿼리로 인한 성능 저하
  • • Redis Sorted Set으로 O(log N) 성능의 랭킹 관리
  • • ZADD, ZREVRANGE, ZRANK 등의 명령어 활용
  • • Redis 데이터 영속성 확보 및 DB 동기화 전략 필요
Follow-up 질문

일간, 주간, 월간 랭킹을 모두 제공해야 한다면 Redis 키 설계를 어떻게 하시겠습니까?

5 보안
Medium

Q. Spring Security를 사용하여 인증/인가를 구현할 때, 특정 API는 로그인한 사용자만 접근 가능하고, 일부 API는 관리자 권한이 필요합니다. 이러한 권한 기반 접근 제어를 어떻게 설계하고 구현하시겠습니까?

A. 모범답안

Spring Security의 SecurityFilterChain을 설정하여 URL 패턴별로 접근 권한을 정의합니다. HttpSecurity를 통해 authorizeHttpRequests()에서 requestMatchers()로 경로를 지정하고 hasRole() 또는 hasAuthority()로 권한을 설정합니다. 예를 들어 /api/admin/** 경로는 ROLE_ADMIN, /api/user/** 경로는 authenticated()로 설정합니다. 사용자 정보는 UserDetailsService 인터페이스를 구현하여 DB에서 조회하고, 권한은 GrantedAuthority로 표현합니다. 메서드 레벨 보안이 필요하면 @PreAuthorize 어노테이션을 활용하여 더 세밀한 제어가 가능합니다. JWT를 사용한다면 토큰에 권한 정보를 포함시키고 필터에서 검증하여 SecurityContext에 설정합니다.

핵심 포인트
  • • SecurityFilterChain에서 URL 패턴별 권한 설정
  • • UserDetailsService로 사용자 정보 및 권한 로드
  • • hasRole(), hasAuthority()로 역할 기반 접근 제어
  • • @PreAuthorize로 메서드 레벨 세밀한 권한 제어 가능
  • • JWT 사용 시 토큰에 권한 정보 포함 및 필터에서 검증
Follow-up 질문

사용자의 권한이 변경되었을 때, 이미 발급된 JWT 토큰은 어떻게 처리해야 할까요?

댓글 0

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

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