Java 시니어 코딩 및 알고리즘 심화 면접

Java 시니어 (7년+) 코딩 · 알고리즘 5문항 조회수 120 · 2026-05-03 (일) 11:11:00
1 동시성 프로그래밍
Hard

Q. Producer-Consumer 패턴을 구현할 때 BlockingQueue, wait/notify, Semaphore, Lock & Condition의 4가지 방식 중 어떤 것을 선택하시겠습니까? 각 방식의 장단점과 성능 특성을 비교하고, 실제 프로덕션 환경에서 어떤 기준으로 선택해야 하는지 설명해주세요.

A. 모범답안

BlockingQueue는 가장 간결하고 안전하며 대부분의 경우 첫 번째 선택지입니다. wait/notify는 레거시 코드에서 사용되나 spurious wakeup 처리가 필요하고 실수하기 쉽습니다. Semaphore는 리소스 개수 제한이 명확할 때 유용하지만 큐 기능은 별도 구현이 필요합니다. Lock & Condition은 복잡한 대기 조건이나 공정성 제어가 필요할 때 사용하며, ReentrantLock의 tryLock으로 타임아웃 처리가 가능합니다. 일반적인 프로듀서-컨슈머는 LinkedBlockingQueue나 ArrayBlockingQueue를 사용하고, 처리량이 극도로 중요한 경우 Disruptor 같은 lock-free 큐를 고려합니다.

핵심 포인트
  • • BlockingQueue는 구현이 간단하고 안전하며 대부분의 경우 최선의 선택
  • • wait/notify는 spurious wakeup과 synchronized 블록 관리가 복잡
  • • Lock & Condition은 복잡한 대기 조건, 공정성, 타임아웃이 필요할 때 유용
  • • 성능이 극도로 중요한 경우 lock-free 자료구조 고려
Follow-up 질문

LinkedBlockingQueue와 ArrayBlockingQueue의 내부 구조 차이와 성능 특성을 설명하고, 각각 어떤 상황에서 사용해야 하는지 말씀해주세요.

2 알고리즘 설계
Hard

Q. 대규모 로그 분석 시스템에서 슬라이딩 윈도우 방식으로 최근 1시간 동안의 요청 수를 카운팅해야 합니다. 초당 수만 건의 요청이 들어오는 환경에서 메모리 효율적이면서도 정확한 카운팅을 위해 어떤 자료구조와 알고리즘을 설계하시겠습니까? Fixed Window, Sliding Log, Sliding Window Counter 방식의 트레이드오프를 비교해주세요.

A. 모범답안

Fixed Window는 메모리가 가장 효율적이지만 경계 시점에서 burst traffic을 제대로 감지하지 못합니다. Sliding Log는 정확하지만 모든 타임스탬프를 저장해야 해서 메모리 사용량이 큽니다. Sliding Window Counter는 시간을 여러 버킷으로 나누어 각 버킷의 카운트만 저장하는 방식으로 메모리와 정확도의 균형을 맞춥니다. 실무에서는 ConcurrentHashMap과 원형 배열을 조합하여 분 단위 버킷 60개로 관리하며, AtomicLong으로 각 버킷의 카운트를 관리합니다. 만료된 버킷은 주기적으로 클리어하고, 조회 시 현재 시간 기준으로 유효한 버킷들만 합산합니다.

핵심 포인트
  • • Fixed Window는 메모리 효율적이나 경계 문제로 정확도가 떨어짐
  • • Sliding Log는 정확하나 메모리 사용량이 크고 스케일링이 어려움
  • • Sliding Window Counter는 시간을 버킷으로 나누어 메모리와 정확도 균형
  • • AtomicLong과 원형 배열로 lock-free 구현 가능
Follow-up 질문

Rate Limiting을 분산 환경에서 구현할 때 Redis를 사용한다면 어떤 자료구조와 Lua 스크립트 전략을 사용하시겠습니까?

3 가비지 컬렉션
Hard

Q. G1 GC와 ZGC의 동작 원리와 차이점을 설명하고, 각각 어떤 애플리케이션 특성에 적합한지 설명해주세요. 특히 힙 크기가 수십 GB인 대용량 메모리 환경에서 GC 튜닝 전략과 모니터링해야 할 주요 지표는 무엇인가요?

A. 모범답안

G1 GC는 힙을 리전 단위로 나누어 Young/Old 영역을 논리적으로 관리하며, pause time goal을 설정하여 예측 가능한 지연시간을 제공합니다. Mixed GC를 통해 Old 영역도 점진적으로 수집하지만 여전히 수백 ms의 STW가 발생할 수 있습니다. ZGC는 colored pointer와 load barrier를 사용하여 10ms 이하의 매우 짧은 pause time을 보장하며, 힙 크기에 관계없이 일정한 지연시간을 유지합니다. 일반적인 서비스는 G1 GC로 충분하지만, 실시간성이 중요하거나 대용량 힙(100GB+)을 사용하는 경우 ZGC가 적합합니다. 튜닝 시 GC 빈도, pause time, throughput, 할당률, promotion rate를 모니터링하며, GC 로그 분석 도구를 활용합니다.

핵심 포인트
  • • G1 GC는 리전 기반으로 예측 가능한 pause time 제공하지만 여전히 수백 ms STW 발생
  • • ZGC는 colored pointer와 load barrier로 10ms 이하 초저지연 보장
  • • 일반 서비스는 G1, 실시간성 중요하거나 대용량 힙은 ZGC 선택
  • • GC 빈도, pause time, allocation rate, promotion rate 모니터링 필수
Follow-up 질문

애플리케이션에서 Old 영역으로의 promotion rate가 비정상적으로 높게 나타난다면 어떤 원인들을 의심하고 어떻게 해결하시겠습니까?

4 문자열 알고리즘
Medium

Q. 대용량 텍스트에서 특정 패턴을 검색하는 시스템을 구현해야 합니다. 단순 문자열 매칭, KMP, Boyer-Moore, Rabin-Karp 알고리즘의 시간복잡도와 각 알고리즘이 유리한 상황을 설명하고, 실무에서 여러 패턴을 동시에 검색해야 한다면 어떤 자료구조를 사용하시겠습니까?

A. 모범답안

단순 매칭은 O(nm)으로 느리지만 구현이 간단하고 짧은 텍스트에는 충분합니다. KMP는 O(n+m)으로 최악의 경우에도 선형 시간을 보장하며 실패 함수를 전처리합니다. Boyer-Moore는 평균적으로 가장 빠르며 패턴 끝에서부터 비교하고 불일치 시 큰 폭으로 건너뜁니다. Rabin-Karp는 해시를 사용하여 O(n+m)이지만 해시 충돌 처리가 필요합니다. 여러 패턴을 동시 검색할 때는 Aho-Corasick 알고리즘을 사용하며, 이는 트라이와 실패 링크를 결합하여 O(n + m + z) 시간에 모든 패턴을 찾습니다. 실무에서는 Java의 String.indexOf가 최적화되어 있어 일반적인 경우 충분하지만, 패턴이 많거나 텍스트가 매우 클 때는 전용 알고리즘이 필요합니다.

핵심 포인트
  • • Boyer-Moore는 평균적으로 가장 빠르며 패턴 끝부터 비교
  • • KMP는 최악의 경우에도 O(n+m) 선형 시간 보장
  • • Aho-Corasick은 여러 패턴 동시 검색에 최적화된 트라이 기반 알고리즘
  • • 실무에서는 일반적으로 최적화된 표준 라이브러리 사용
Follow-up 질문

정규표현식 엔진의 내부 동작 원리를 NFA와 DFA 관점에서 설명하고, catastrophic backtracking 문제와 해결 방법을 말씀해주세요.

5 객체 직렬화
Medium

Q. Java Serialization, JSON(Jackson, Gson), Protocol Buffers, MessagePack의 장단점을 비교하고, 마이크로서비스 간 통신에서 직렬화 방식을 선택할 때 고려해야 할 요소들을 설명해주세요. 특히 버전 호환성과 성능 측면에서 어떤 차이가 있나요?

A. 모범답안

Java Serialization은 Java 전용이며 느리고 보안 취약점이 있어 권장되지 않습니다. JSON은 사람이 읽을 수 있고 언어 독립적이며 디버깅이 쉽지만 크기가 크고 파싱 비용이 높습니다. Protocol Buffers는 스키마 기반으로 타입 안정성이 높고 크기가 작으며 빠르지만, 스키마 관리가 필요하고 사람이 읽기 어렵습니다. MessagePack은 JSON과 호환되면서 바이너리로 인코딩하여 크기와 속도를 개선했습니다. 마이크로서비스에서는 외부 API는 JSON, 내부 통신은 Protocol Buffers를 사용하는 것이 일반적입니다. 버전 호환성을 위해 필드 추가는 optional로 하고, 필드 삭제나 타입 변경은 신중하게 처리하며, Protobuf의 경우 필드 번호를 재사용하지 않습니다.

핵심 포인트
  • • JSON은 디버깅 용이하지만 크기가 크고 파싱 비용 높음
  • • Protocol Buffers는 작고 빠르며 타입 안전하지만 스키마 관리 필요
  • • 외부 API는 JSON, 내부 통신은 Protobuf가 일반적
  • • 버전 호환성 위해 필드 추가는 optional, 삭제/변경은 신중히
Follow-up 질문

gRPC에서 사용하는 HTTP/2 프로토콜의 멀티플렉싱과 헤더 압축이 성능에 미치는 영향을 설명하고, REST API 대비 어떤 장점이 있는지 말씀해주세요.

댓글 0

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

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