백엔드 면접 학습 노트 목차

면접 시나리오·트러블슈팅 — 백엔드 면접 (실제 기출 기반·심화)

지식 질문을 넘어 "이 장애를 어떻게 진단했나요", "이 선택의 트레이드오프는", "경험을 말해 보세요" 로 가는 단골. 정답 암기가 아니라 생각하는 과정·트레이드오프·실무 감각을 본다. 앞의 01~11편을 실전으로 엮는 캡스톤 — 여기서는 단순 정의 대신 실제로 어떤 명령·설정으로 좁혀 가는지를 다룬다.

함정형 단골: ① "느려요"에 추측으로 코드부터 고침 → 측정 없이 가설 검증 X(★) ② OOM = 메모리 부족? → 누수·대량 적재·메타스페이스가 더 흔함 ③ 커넥션 풀 키우면 해결? → DB가 못 받으면 오히려 악화, 점유 시간이 진짜 원인 ④ 데드락은 앱이 멈춤? → InnoDB가 자동 감지·한쪽 롤백(에러 1213)·앱은 재시도하면 됨.


1. 면접 진행 방식·태도 (지식만큼 평가된다)

실제 질문: "모르는 질문이 나오면 어떻게 대처하세요?" · "이 기술을 선택했나요?" (거의 모든 회사 공통)

  • 모르면: "정확히는 모르지만 이렇게 접근하겠습니다"로 사고 과정을 보여라. 아는 척하면 꼬리질문에서 무너진다 — 면접관은 모르는 영역을 다루는 방식을 본다.
  • 항상 트레이드오프로 마무리: "A가 빠르지만 B는 일관성이 좋습니다. 이 상황(읽기 多·약한 일관성 허용)이면 A를 택하겠습니다" — 단정보다 상황별 판단.
  • 되물어라: 설계·장애 질문은 요구사항·규모·제약을 먼저 명확화. "읽기:쓰기 비율? QPS? 일관성 요구? 데이터 규모?"를 묻는 것 자체가 점수다.
  • 수치로 말하라: "빨라졌다"❌ → "p99를 800ms→120ms로"⭕. 측정값이 신뢰를 만든다.

함정: ❌ 자신 없는 주제를 단정적으로 → 꼬리질문 3번이면 들통. 모르는 경계를 솔직히 + 접근법.


2. 트러블슈팅 만능 틀 (★ 모든 장애 질문의 뼈대)

증상 → 가설 → 측정 → 격리 → 수정 → 검증

추측으로 고치지 말고 측정으로 좁힌다. 업계 표준 관찰 방법론과 같은 사고다 — USE(자원별 Utilization·Saturation·Errors, Brendan Gregg)·RED(요청별 Rate·Errors·Duration, Tom Wilkie).

다이어그램 로딩 중…

측정 도구 4종: ① APM·분산 트레이싱(요청이 어느 서비스·어느 스팬에서 시간 소비?) ② 메트릭(Micrometer→Prometheus·Grafana: CPU·힙·풀·QPS·p99) ③ 로그(에러·슬로우쿼리) ④ 덤프(스레드 덤프=어디서 블로킹·힙 덤프=무엇이 메모리 점유).


3. 시나리오 A — "API가 갑자기 느려졌어요" (실전 워크스루)

실제 질문: "특정 API의 응답이 느려졌다는 제보가 왔습니다. 어떻게 원인을 찾나요?" (VSFe·우아한형제들·올리브영 단골)

격리부터: APM 트레이스로 시간이 어디서 소모되는지 본다 — 앱 로직? DB? 외부 API? 큐 대기?

① DB가 범인일 때 — 슬로우 쿼리 로그를 켜고(long_query_time) 느린 쿼리를 잡는다.

EXPLAIN SELECT * FROM orders WHERE user_id = 42 AND status = 'PAID';
-- type=ALL(풀스캔)·rows 큼 → 인덱스 누락. (user_id, status) 복합 인덱스 추가

인덱스 추가·커버링 인덱스·쿼리 재작성. (DB 편)

② N+1이 범인일 때 — 한 요청에 쿼리가 수백 개. show_sql이나 p6spy로 쿼리 개수를 본다.

// ❌ 주문 1 + 주문마다 회원 N번 = 1+N
List<Order> orders = orderRepo.findAll();
orders.forEach(o -> o.getMember().getName()); // lazy → 매번 SELECT

// ⭕ fetch join / @EntityGraph / default_batch_fetch_size(IN 절로 묶음)
@Query("select o from Order o join fetch o.member")

fetch join·@EntityGraph·spring.jpa.properties.hibernate.default_batch_fetch_size=100. (Spring·JPA 편)

GC(STW)가 범인일 때 — 주기적 지연·p99만 튐. jstat -gcutil <pid> 1000로 GC 빈도·STW 시간, -Xlog:gc*로 로그 확인.

# Full GC가 잦고 STW가 길다 → 힙 부족/누수·잘못된 객체 수명
jstat -gcutil 12345 1000   # FGC(횟수)·FGCT(누적시간) 급증 확인

→ 힙 크기·G1 튜닝·누수 제거. (Java 편)

④ 외부 API가 범인일 때 — 동기 호출이 느려지며 연쇄 지연. → 타임아웃·서킷브레이커·비동기화. (시스템설계 편)

꼬리질문: "측정 도구가 없으면?" → 임시로 구간별 로그(시작/종료 타임스탬프)·스레드 덤프 여러 장으로 어디서 멈춰 있는지. / "느린 쿼리는 빠른데 API가 느리면?" → 커넥션 풀 대기·직렬화·로깅 I/O·GC. / "재현이 안 되면?" → 부하·데이터량·동시성 조건 차이(운영 데이터 규모로 재현).

함정: ❌ 트레이스 없이 "아마 쿼리겠지" 하고 인덱스부터 → 측정이 먼저. 병목이 GC였다면 헛수고.


4. 시나리오 B — "커넥션 풀이 고갈됐어요" (HikariCP)

실제 질문: "갑자기 Connection is not available 에러가 쏟아집니다. 원인과 해결은?" (실무 단골)

증상: HikariPool-1 - Connection is not available, request timed out after 30000ms. HikariCP 기본 풀 크기 10·connectionTimeout 30s — 모든 커넥션이 점유된 채 반납이 안 돼 대기가 타임아웃.

원인은 거의 "점유 시간" — 풀이 작은 게 아니라 오래 쥐고 있는 것:

  • 트랜잭션 안에서 외부 API 호출: 네트워크 대기 동안 DB 커넥션을 쥠 → 동시 요청 몇 개면 고갈.
  • OSIV(Open Session In View, spring.jpa.open-in-view=true 기본값): 영속성 컨텍스트뷰 렌더링·응답 직렬화까지 열어둠 → 커넥션을 요청 끝까지 점유.
  • 누수: 커넥션을 명시적으로 닫는 코드에서 예외로 반납 누락. leakDetectionThreshold로 탐지.

해결: ① 트랜잭션 짧게·외부 호출은 트랜잭션 밖으로 ② OSIV off(spring.jpa.open-in-view=false)로 커넥션을 트랜잭션 범위로만 ③ 누수 탐지(spring.datasource.hikari.leak-detection-threshold=5000) ④ 풀 크기는 근거 있게 — HikariCP 권장 pool size = (코어 수 × 2) + 디스크 수 수준에서 측정으로 조정(무작정 키우면 DB 컨텍스트 스위칭·락 경합으로 악화).

꼬리질문: "풀을 100으로 키우면?" → DB가 동시 100을 못 버티면 DB가 병목으로 이동·오히려 악화. / "OSIV를 끄면 부작용은?" → 컨트롤러·뷰에서 lazy 접근 시 LazyInitializationException → 서비스 계층에서 fetch join·DTO로 미리 로딩. / "누수인지 점유인지 구분?" → 점유는 부하 시 고갈·평시 회복, 누수는 시간이 지날수록 가용 커넥션이 단조 감소.

함정: ❌ "풀 크기만 키우면 해결" → 진짜 원인은 점유 시간. 외부 호출·OSIV부터.


5. 시나리오 C — "메모리가 계속 차서 OOM이 납니다"

실제 질문: "OutOfMemoryError가 간헐적으로 발생합니다. 어떻게 분석하나요?" (VSFe·기업 블로그)

증거 확보: -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/dump터지는 순간의 힙을 떠서, Eclipse MATDominator Tree·Leak Suspects무엇이 힙을 지배하는지 본다.

흔한 누수 패턴:

  • ThreadLocal 미해제: 스레드풀에서 스레드가 재사용되는데 remove()를 안 하면 객체가 계속 매달림(웹 컨테이너 단골).
  • static 컬렉션·무한 캐시: 끝없이 put만 → 크기 제한 캐시(Caffeine maximumSize)·약한 참조.
  • 미해제 자원: 스트림·커넥션·리스너 등록 후 해제 누락.

OOM ≠ 항상 누수: 정상인데 양이 큼(대량 조회를 메모리에 다 적재 → 페이징·스트리밍)·Metaspace OOM(클래스 무한 로딩·동적 프록시)·스레드 과다. 메시지부터 구분: Java heap space vs Metaspace vs unable to create new native thread.

꼬리질문: "힙 덤프 없이 운영 중 분석?" → jmap -histo:live <pid>로 인스턴스 수 상위 클래스·jcmd GC.class_histogram. / "GC가 도는데 왜 OOM?" → 회수 가능한 게 없음(전부 도달 가능 = 누수) 또는 회수보다 적재가 빠름. / "재현이 안 됨?" → 운영 트래픽·데이터량·장시간 가동(누수는 시간 누적).

함정: ❌ "힙만 늘리면 됨" → 누수면 터지는 시점만 미룸. 근본 원인(도달 가능한 쓰레기)을 끊어야.


6. 시나리오 D — "DB 데드락 / 간헐적 데이터 꼬임"

실제 질문: "데드락이 가끔 발생합니다. 원인과 대응은?" · "동시에 같은 행을 갱신할 때 값이 꼬입니다." (DB·동시성 단골)

데드락: 두 트랜잭션이 락을 엇갈린 순서로 잡아 서로 대기. InnoDB는 자동 감지해서 비용이 적은 쪽을 롤백(에러 1213 Deadlock found) — 앱이 멈추지 않는다. 원인은 SHOW ENGINE INNODB STATUSLATEST DETECTED DEADLOCK로 확인.

  • 해결: ① 여러 자원을 항상 같은 순서로 락 ② 트랜잭션을 짧게(락 보유 시간↓) ③ 데드락은 정상 발생할 수 있으니 재시도 로직(1213 → 지수 백오프 재시도) ④ 격리수준·인덱스 정비(범위 락 줄이기).

간헐적 데이터 꼬임 = 경쟁 조건: 읽고-수정-쓰기(check-then-act)가 원자적이지 않음. → 비관락(SELECT … FOR UPDATE낙관락(@Version·충돌 시 재시도)·원자 연산(UPDATE … SET stock=stock-1 WHERE stock>0)·격리수준 상향. (DB·시스템설계 편)

앱(JVM) 데드락도 같은 틀: jstack <pid>(또는 kill -3)로 "Found one Java-level deadlock" 블록 — 어느 스레드가 어느 모니터를 잡고 무엇을 기다리는지.

꼬리질문: "데드락을 0으로?" → 완전 제거보다 확률↓ + 재시도가 현실적. / "낙관 vs 비관 선택?" → 충돌 드물면 낙관(락 비용↓)·잦으면 비관/원자 연산. / "재시도가 위험한 연산은?" → 비멱등(중복 결제) → 멱등키 먼저.

함정: ❌ "데드락 = 서버 멈춤" → InnoDB가 한쪽 롤백·앱은 재시도면 됨. 진짜 문제는 락 순서·긴 트랜잭션.


7. 시스템 설계 인터뷰 — 접근 틀 (작은 예라도 을 보여라)

실제 질문: "URL 단축기를 설계해 보세요." · "선착순 쿠폰을 설계한다면?" (분산 심화는 11편, 여기선 접근 순서)

: 요구사항 명확화 → 용량 산정 → API·데이터 모델 → 고수준 구성 → 병목·확장 → 트레이드오프. 바로 그리지 말고 되묻기부터.

미니 워크스루 — URL 단축기 용량 산정 (숫자로 규모 감각을 보여주는 게 핵심):

  • 가정: 쓰기 1억 URL/월 ≈ 40 writes/s, 읽기:쓰기 = 100:1 → 4,000 reads/s.
  • 키 길이: Base62 7자리 = 62⁷ ≈ 3.5조 → 수년 충분. 저장 5년 ≈ 60억 row.
  • 설계: 읽기가 압도적 → 캐시(핫 URL)+읽기 복제·리다이렉트는 영구면 301(브라우저 캐시·집계 손실) vs 추적 필요면 302.
  • 병목: 키 생성 충돌(카운터/Snowflake)·핫키(캐시)·읽기 폭주(CDN·복제).

되묻기 체크리스트: 규모(QPS·저장량)·읽기:쓰기 비율·일관성 요구·지연 허용·가용성 목표·트래픽 패턴(피크/핫키). (구체 분산 기법 = 11편: 복제·샤딩·CAP·Saga·서킷브레이커.)

함정: ❌ 요구사항 안 묻고 바로 박스 그리기 → 과·과소 설계. 먼저 규모를 정의.


8. 경험·인성(behavioral) — STAR로 구조화

실제 질문: "가장 어려웠던 기술 문제는?" · "성능을 개선한 경험은?" · "협업 중 갈등 경험은?"

STAR: Situation(상황·맥락) → Task(내 과제) → Action(내가 한 구체 행동) → Result(수치 결과).

  • 예: "결제 API p99가 800ms로 SLA를 못 맞춤(S) → 원인 규명·개선 담당(T) → APM으로 N+1 발견, fetch join + Redis 캐시 + 커넥션 풀 점유 분리(A) → p99 800ms→120ms·DB CPU 70%→35%(R)."
  • 기술 선택은 왜 그것을·대안은·트레이드오프는까지. 실패·배움도 성장 관점으로 솔직히("재시도를 멱등 없이 넣어 중복 결제 → 멱등키로 수정, 이후 비멱등 연산을 먼저 점검하는 습관").

함정: ❌ "우리 팀이/우리가" 일색 → 면접관은 당신의 Action을 본다. 내가 한 것을 명확히.


9. 장애 대응 체계 — 개인 무용담이 아니라 프로세스로 답하라

실제 질문: "장애 대응 경험이 있나요?" · "장애가 나면 가장 먼저 무엇을 하나요?" · "포스트모템은 어떻게 쓰나요?"

3~7절이 기술적 원인 규명이라면 이 절은 조직이 장애를 다루는 방식이다. 주니어는 "로그를 봤습니다"에서 끝나고, 시니어는 단계·역할·지표로 답한다. 후자가 훨씬 강하게 평가된다.

장애 라이프사이클

실제 운영 조직이 쓰는 단계 구분이다(우아한형제들 사례).

[탐지] 이상 감지        모니터링이 이상을 잡고, ACK 등 객관적 근거로 '장애'로 확정
  ↓
① Open          장애 인지 + 조직 간 전파 (채널 동시 활성화)
② Investigating 영향 범위와 기여 요인 분석
③ Identified    완화 조치 실행          ← First Action 이 여기
④ Monitoring    조치가 실제로 듣는지 확인
⑤ Resolved      서비스 정상화 확인 + 이해관계자 통보
⑥ Closure       근본 원인 문서화 + 재발 방지 과제 추적

First Action — "판단 없이 즉시 실행하는 기계적 완화"

핵심 개념이다. 원인을 몰라도 즉시 실행할 수 있게 미리 정해 둔 조치 — 롤백, 오토스케일링, 트래픽 차단 같은 것들이다.

롤백을 First Action으로 쓴 장애가 핫픽스를 쓴 장애보다 약 50% 빨리 해결됐다.

이유는 단순하다. 핫픽스는 원인을 먼저 알아야 하지만, 롤백은 몰라도 된다. 변경을 되돌리면 변경으로 생긴 문제는 사라진다. 그래서 "원인부터 찾자"는 본능이 오히려 복구를 늦춘다.

면접에서 이렇게 답하면 강하다.

"원인 규명보다 영향 차단을 먼저 합니다. 배포 직후라면 원인을 몰라도 일단 롤백하고, 복구된 뒤에 원인을 봅니다. 롤백이 불가능한 변경(스키마 마이그레이션 등)은 애초에 배포 전에 되돌릴 수 있는 형태로 나눠 둡니다."

시간 지표 — 어디가 병목인지 드러난다

MTTD   장애 발생 → 인지        모니터링이 제 역할을 하는가
MTTFA  장애 발생 → First Action 실행   초기 대응이 빠른가
MTTEA  장애 발생 → 지표가 실제로 회복   조치가 효과가 있었는가
MTTR   인지 → 완전 복구        운영 병목이 어디인가
MTTIR  장애 발생 → 보고서 완료
MTTPM  장애 발생 → 재발 방지 과제 완료

MTTD만 짧고 MTTFA가 길면 "빨리 알았는데 아무도 결정을 못 내린" 조직이다. 지휘 체계와 사전 정의된 대응 시나리오가 없다는 뜻이다. MTTFA는 짧은데 MTTEA가 길면 조치가 원인을 안 건드린 것이다.

포스트모템

  • 비난하지 않는다(blameless). 사람을 탓하면 다음 장애 때 보고가 늦어지고, 그게 더 큰 손실이다.
  • 보고서 단계와 재발 방지 과제 추적 단계를 나눈다. 보고서를 쓰고 끝내면 같은 장애가 반복된다. 과제에 담당자와 기한을 붙여 완료까지 추적한다(그래서 MTTPM 지표가 따로 있다).
  • "왜"를 다섯 번 파고든다. "NPE가 났다"에서 멈추지 말고 "왜 그 값이 null일 수 있었나 → 왜 검증이 없었나 → 왜 리뷰에서 안 걸렸나"까지.

함정: ❌ "장애 나서 밤새 고쳤습니다"만 말하기 → 영웅담은 체계가 없다는 신호로 읽힌다. 무엇을 자동화했고 무엇을 사전 정의했는지를 말하라.


10. 리팩터링 경험 — "왜 지금", "어떻게 안전하게"를 답하라

실제 질문: "리팩터링 경험이 있나요?" · "레거시 코드를 어떻게 개선했나요?" · "리팩터링을 어떻게 설득했나요?"

면접관이 보는 건 세 가지다 — 문제를 어떻게 진단했나 / 어떻게 안전하게 바꿨나 / 무엇으로 좋아졌다고 증명하나. "코드가 더러워서 고쳤습니다"는 셋 다 없는 답이다.

사례 — 12년 된 메시징 서버 (카카오톡 Java App Server)

① 진단: 가변 Context 클래스의 범람

상태를 담는 Context 클래스가 10개를 넘어가면서, 이것들이 서로 물고 물리는 종속성을 만들었다. 참조가 여러 함수로 전달되면서 사실상 전역 변수처럼 쓰였다 — 어딘가에서 A가 set 하고 다른 곳에서 B가 get 한다.

class CarContext {
    private Car car;
    private List<People> passengers;
    private List<People> visitors;
    ... 많은 필드
    ... 다양한 get/set
}

그러면 수정할 때 사용처를 다 추적할 수 없고, 장애가 나도 디버깅이 안 된다.

② 기법 1 — 파라미터로 받아 set 하지 말고 반환하라

// ✗ 함수가 바깥 객체의 상태를 직접 바꾼다 → 결합도↑, 추적 불가
Result createCar(CarContext ctx, Something a, Something b) {
    ctx.setCar(new Car());
    return new Result(v);
}

// ✓ 만든 값을 돌려준다 — 호출부가 무엇이 바뀌는지 안다
Pair<Result, Car> createCar(Something a, Something b) {
    return new Pair<>(new Result(v), new Car());
}

③ 기법 2 — Context 통째로 받지 말고 필요한 것만 명시적으로 받아라

// ✗ 이 함수가 Context의 무엇을 읽고 무엇을 바꾸는지 시그니처만 봐선 알 수 없다
void doSomethingForPassengers(CarContext ctx, Something a) { ... }

// ✓ 의도가 시그니처에 드러난다
void doSomethingForPassengers(List<People> passengers, SomeValue v, Something a) { ... }

파라미터가 늘어 불편하면 함수를 더 작은 책임으로 쪼갤 신호로 읽는다.

④ 기법 3 — 순환 의존성을 고차 함수로 끊는다

오래된 스프링 서비스에서 흔한 문제다. ServiceA → ServiceB → ServiceC → ServiceA 같은 순환이 생기면 읽기도 어렵고 단위 테스트도 못 만든다.

// Before — ServiceA 가 ServiceB 를 필드로 들고 있다(순환의 씨앗)
@Service
class ServiceA {
    @Resource ServiceB serviceB;
    void methodA(Integer p) { ... serviceB.methodB(p) ... }
}

// After — 의존을 '함수'로 낮춘다. ServiceA 는 더 이상 ServiceB 를 모른다
@Service
class ServiceA {
    void methodA(Integer p, Function<Integer, Integer> methodB) { ... methodB.apply(p) ... }
}

// 의존은 상위(Handler)로 올리고 생성자 주입으로 조립한다
@Component
class Handler {
    private final ServiceA a; private final ServiceB b;
    Handler(ServiceA a, ServiceB b) { this.a = a; this.b = b; }
    void execute() { a.methodA(2, b::methodB); }
}

클래스 인터페이스보다 함수형 인터페이스가 더 작고 약한 결합이다. 의존 자체를 없앨 수 없다면 가능한 한 작게 유지한다.

여기서 꼬리질문이 자주 붙는다 — "필드 주입과 생성자 주입 중 뭘 쓰나?" 순환 의존이 있을 때 생성자 주입은 기동 자체가 실패하지만 필드 주입은 리플렉션이라 조용히 통과한다. 즉 필드 주입은 설계 결함을 감춘다. Spring Boot 2.6부터는 순환 참조가 기본 금지이고, 굳이 켜려면 spring.main.allow-circular-references=true가 필요하다.

⑤ 결과

  • Context 클래스 10개 → 3개, 수백 라인 삭제, 기능은 동일하게 유지
  • 순환 의존성 그래프를 단순 그래프로 정리해 라이브 서비스에 무중단 반영
  • 성능 저하 없이 유지보수성·테스트 용이성 확보

답변 골격

왜 지금 — "기능 추가마다 수정 범위를 예측할 수 없었고, 장애 시 디버깅이 오래 걸렸습니다. 부채가 개발 속도에 실제 비용으로 드러난 시점이었습니다." 어떻게 안전하게 — "점진적으로 했습니다. 한 번에 갈아엎지 않고 Context를 하나씩 줄였고, 각 단계마다 기능 동일성을 확인했습니다." 무엇으로 증명 — "Context 10→3개, 순환 의존성 제거, 성능 지표는 동일. 테스트 작성이 가능해진 것이 가장 큰 변화입니다."

함정

  • 빅뱅 리팩터링 — "전면 재작성했습니다"는 위험 신호다. 되돌릴 수 없고 검증도 안 된다. 점진적 접근과 각 단계의 안전망을 말하라.
  • 측정 없는 개선 — "깔끔해졌습니다"는 근거가 아니다. 복잡도·의존성·결함률·변경 소요 시간 중 하나라도 수치를 대라.
  • 테스트 없이 시작 — 바꾸기 전에 현재 동작을 고정하는 테스트(characterization test)부터 만든다. 없으면 "동일하게 유지했다"를 증명할 수 없다.

흔한 오답·함정 정리

  • 측정 없이 코드부터 고침 → 증상→가설→측정→격리가 먼저(병목을 틀리면 헛수고).
  • 커넥션 풀만 키우면 해결 → 진짜 원인은 점유 시간(외부 호출·OSIV). DB가 못 받으면 악화.
  • OOM = 메모리 부족 → 누수(도달 가능한 쓰레기)·대량 적재·Metaspace가 더 흔함.
  • 데드락 = 서버 멈춤 → InnoDB 자동 감지·한쪽 롤백(1213)·재시도로 처리.
  • 시스템 설계는 바로 그린다 → 요구사항·규모 되묻기가 먼저.
  • 모르는 걸 아는 척 → 꼬리질문에 붕괴. 접근법·솔직함이 점수.

한국 면접 단골 종합 Q&A (답변 골격)

질문핵심 접근
API 느림 진단?APM 구간 격리 → 슬로우쿼리/N+1/GC/외부지연 → 가설 검증
커넥션 풀 고갈?점유 시간(외부호출·OSIV)·누수 → 짧게·분리·OSIV off
OOM 분석?힙 덤프 + MAT dominator → ThreadLocal·무한캐시·대량적재 구분
데드락?INNODB STATUS·락 순서 통일·짧게·재시도(1213)
동시성 꼬임?경쟁 조건 → 비관/낙관락·원자 연산·격리수준
트래픽 10배?캐시·복제·비동기·샤딩·CDN — 병목부터(11편)
시스템 설계?요구사항→용량→API/모델→병목→트레이드오프
어려웠던 경험?STAR + 수치 + 트레이드오프
모르는 질문?접근 과정 제시·솔직·되묻기

꼬리질문 대비 (상 난이도)

  • "측정 도구가 없는 환경이면?" → 구간 로그·스레드 덤프 다중 샷·jstat/jmap/jstack 같은 JDK 내장으로.
  • "그 캐시·DB·큐가 죽으면?" → 폴백(DB 직접)·스탬피드 대비·소비자 멱등·서킷브레이커(8·9·10·11편).
  • "그 선택의 단점은?" → 모든 선택엔 비용이 있다 — 단점을 먼저 인지하고 왜 감수하는지.
  • "더 큰 규모면 뭐가 먼저 깨지나?" → 단일 DB 쓰기·동기 호출 연쇄·캐시 미스·핫 파티션.
  • "장애를 어떻게 예방?" → 부하 테스트·SLO/알람·서킷브레이커·점진 배포·관찰성(메트릭·트레이싱).

한 줄 요약 — 면접은 지식 + 생각 과정·트레이드오프·실무 감각. 트러블슈팅증상→가설→측정→격리→수정→검증(추측 말고 측정: APM·메트릭·로그·덤프). 단골 장애 — 느림(구간 격리→슬로우쿼리/N+1/GC커넥션 고갈(점유 시간·OSIV)·OOM(힙 덤프→누수/적재)·데드락(INNODB STATUS·재시도)·동시성(락·원자 연산) — 은 앞 편의 원인·해결로 푼다. 시스템 설계는 요구사항→용량→설계→병목→트레이드오프 틀로 되묻기 먼저. 경험은 STAR + 수치. 모르면 접근법을 보여라.

(출처 — 한국 면접 기출·교차검증 2026-06: VSFe/Tech-Interview·gyoogle — tech-interview-for-developer·WeareSoft/tech-interview · 기업 기술블로그(우아한형제들·올리브영 트러블슈팅 사례) · 도구·동작 1차자료: HikariCP About Pool Sizing·[Spring Boot OSIV 문서]·MySQL InnoDB Deadlock Detection·USE Method(Brendan Gregg)·System Design Interview(Alex Xu)·Release It!(Nygard) — 앞 01~11편(각 1차자료 검증) 종합·교차검증.)

시스템 설계·분산 — CAP·복제·샤딩·Saga·서킷브레이커채용공고 실전 면접 질문 — 90문항·모범답안(기출·1차검증)