장애 회의. 개발자가 빠르게 말합니다. "HikariCP 풀이 고갈됐고, 슬로우 쿼리가 커넥션을 점유했어요. AOP 트랜잭션이 안 끝나서 누수도 의심돼요. 일단 Heap Dump 떴는데 Full GC가 계속 돌아요." 한 문장에 모르는 단어가 다섯 개. PM·인프라인 당신은 이 말이 '얼마나 심각한지', '무엇을 해야 하는지' 판단해야 하는데 용어에서 막힙니다. 이 모듈은 백엔드 자바·스프링 용어를 '들으면 뜻을 알고, 어떻게 대응할지 아는' 수준으로 빠르게 해독하는 사전입니다. 깊이가 필요한 항목은 심화 모듈로 연결합니다.
- 1DB 접속 계층(JDBC·DataSource·커넥션 풀) 용어를 듣고 장애 신호를 해석할 수 있다
- 2ORM·계층 구조(JPA·DAO·DTO·Controller) 용어로 코드 구조 대화를 따라갈 수 있다
- 3스프링 핵심(DI·IoC·AOP·Bean) 용어의 의미를 설명할 수 있다
- 4메모리·GC·배포 산출물(Heap·OOM·WAR/JAR) 용어로 운영 대응을 판단할 수 있다
DB 접속 계층
확대
위 그림처럼 자바 앱은 DataSource를 통해 HikariCP 풀에서 커넥션을 빌리고, JDBC Driver로 DB에 접속합니다. 풀 고갈(Connection is not available)이 발생하면 슬로우 쿼리·트랜잭션 누수·풀 크기 세 원인을 순서대로 점검합니다.
JDBC → DataSource → 커넥션 풀: 앱이 DB에 닿는 길
자바 앱이 DB에 연결하는 경로의 용어들입니다. 장애 로그에 자주 등장하므로 신호를 알아야 합니다.
| 용어 | 한 줄 뜻 | 언제 마주치나 | 대응 | 중요도 |
|---|---|---|---|---|
| JDBC | 자바의 표준 DB 접속 API | 모든 DB 연동 | 규약이라 직접 손댈 일 적음 | ★ |
| JDBC Driver | 특정 DB(MySQL 등)용 JDBC 구현 | 드라이버 버전/누락 에러 | DB 버전과 드라이버 호환 확인 | ★★ |
| DataSource | 커넥션을 공급하는 추상화 | 설정(application.yml) | URL·계정·풀 설정 위치 | ★★ |
| Connection Pool | 커넥션을 미리 만들어 재사용하는 풀 | 성능·고갈 장애 | 풀 크기·타임아웃 튜닝 → DB 연결 지연을 없애는 HikariCP 설정과 대기 성능 튜닝 | ★★★ |
| HikariCP / DBCP | 대표적 커넥션 풀 구현(HikariCP가 기본) | 풀 고갈 로그 | "Connection not available" = 고갈 신호 | ★★★ |
| JNDI | 외부(WAS)에서 DataSource를 이름으로 조회 | 레거시 WAS 환경 | server.xml/context 설정 | ★ |
핵심 신호: "HikariCP ... timed out" = 커넥션 풀 고갈. 슬로우 쿼리·트랜잭션 미종료(누수)·풀 부족이 3대 원인. 깊은 진단은 DB 연결 지연을 없애는 HikariCP 설정과 대기 성능 튜닝.
ORM과 계층 구조
JPA·MyBatis와 Controller→Service→Repository 흐름
데이터를 다루는 방식(ORM/매퍼)과 코드를 나누는 계층 용어입니다.
| 용어 | 한 줄 뜻 | 비고 | 중요도 |
|---|---|---|---|
| JPA | 자바 ORM 표준(객체↔테이블 매핑) | 스펙. 구현이 Hibernate | ★★ |
| Hibernate | 가장 널리 쓰는 JPA 구현 | N+1·지연로딩 이슈 → Prisma, JPA, TypeORM, SQLAlchemy의 성능 차이와 올바른 사용법 | ★★ |
| MyBatis | SQL을 직접 쓰는 매퍼 프레임워크 | 복잡 쿼리에 선호 | ★★ |
| Mapper / DAO / Repository | DB 접근 담당 계층(이름만 다름) | 데이터 입출구 | ★★ |
| Service Layer | 비즈니스 로직 계층 | 트랜잭션 경계가 보통 여기 | ★★ |
| Controller | 요청을 받는 진입 계층 | HTTP↔로직 연결 | ★★ |
| DTO / VO / Entity | 데이터 전달/값/DB매핑 객체 | 계층 간 데이터 그릇 | ★★ |
대화 따라가기: "Controller→Service→Repository로 흐른다"는 요청이 진입→로직→DB 순으로 간다는 뜻. Entity는 DB 테이블과 매핑되고, DTO는 계층/API 경계에서 주고받는 그릇입니다. ORM의 대표 함정(N+1)은 Prisma, JPA, TypeORM, SQLAlchemy의 성능 차이와 올바른 사용법에서 다룹니다.
스프링 핵심 개념
확대
위 그림처럼 스프링 컨테이너가 Bean을 생성·관리하며 각 계층에 DI로 주입합니다. @Transactional은 AOP가 Service 계층에 자동으로 걸어 주며, "빈 주입 실패"는 컴포넌트 스캔 누락이 원인입니다.
DI·IoC·AOP·Bean과 요청 처리 부속(Servlet·Filter·Interceptor)
스프링을 '틀'로 만드는 핵심 메커니즘과 요청 처리 부속입니다.
| 용어 | 한 줄 뜻 | 왜 중요 | 중요도 |
|---|---|---|---|
| IoC | 객체 생성·흐름 제어를 프레임워크가 가져감 | 스프링의 근간(프레임워크·라이브러리·런타임·SDK) | ★★ |
| DI | 필요한 객체를 외부에서 주입 | IoC의 구현 방식 | ★★ |
| Bean | 스프링 컨테이너가 관리하는 객체 | "빈 등록 안 됨" 에러 단골 | ★★ |
| AOP | 공통 관심사(트랜잭션·로깅)를 분리 주입 | @Transactional이 AOP로 동작 | ★★ |
| Servlet / Servlet Container | 자바 웹 요청 처리 표준 / 그 실행 환경(톰캣) | 요청 처리의 토대 | ★ |
| Filter / Interceptor | 요청 전/후 가로채 공통 처리(인증·로깅) | 보안·로깅 위치 | ★★ |
자주 듣는 말 해독: "@Transactional이 AOP로 걸려서 메서드 끝에 커밋된다" = 트랜잭션을 코드가 아니라 AOP가 자동 처리한다. "빈으로 등록 안 돼서 주입 실패" = DI 대상 객체가 컨테이너에 없다.
동시성 · 메모리 · 배포 산출물
확대
위 그림처럼 OOM은 대부분 Heap(Old Generation)에서 발생합니다. Full GC가 반복(stop-the-world)되면 응답이 멈추며, Heap Dump로 한도 부족과 메모리 누수를 구분합니다. WAR는 외부 WAS가 필요하고, Fat JAR는 Tomcat 내장으로 단독 실행됩니다.
Thread Pool·Async·GC·OOM·WAR/JAR
운영 장애와 직결되는 동시성·메모리·배포 형태 용어입니다.
| 용어 | 한 줄 뜻 | 장애 신호/대응 | 중요도 |
|---|---|---|---|
| Thread / Thread Pool | 동시 실행 단위 / 재사용 풀 | 풀 고갈 시 요청 적체 | ★★ |
| ExecutorService / Async / Future / CompletableFuture | 비동기 작업 실행·결과 핸들 | 비동기 처리 → 동기 vs 비동기 | ★★ |
| Heap / Stack Memory | 객체 저장 영역 / 호출 스택 | OOM은 보통 Heap | ★★ |
| GC / Minor·Major·Full GC | 안 쓰는 객체 자동 회수 | Full GC 잦으면 지연 → Heap/GC/Thread Dump 분석과 OOM 대응 실무 | ★★★ |
| OOM / Memory Leak | 메모리 부족 / 누수(계속 증가) | Heap Dump로 구분, 한도 vs 누수 | ★★★ |
| ClassLoader / Classpath | 클래스 로딩 / 탐색 경로 | "ClassNotFound" 에러 | ★ |
| Maven / Gradle / pom.xml / build.gradle | 빌드 도구 / 설정 파일 | 의존성·빌드 → 컴파일·인터프리터·빌드·런타임 | ★★ |
| WAR / JAR / Fat JAR / Embedded Tomcat | 배포 산출물 형태 | WAS 필요 여부 결정 | ★★ |
| Profile / application.yml/properties | 환경별 설정 | dev/prod 분리 → 용어사전 | ★★ |
핵심 신호: Full GC가 반복되면 응답 지연·정지(stop-the-world). OOM은 Heap Dump로 '한도 부족 vs 누수'를 가립니다. 깊은 자바 메모리 진단은 Heap/GC/Thread Dump 분석과 OOM 대응 실무.
장애 로그에서 용어 찾아 해석하기 — 직접 해보기
운영 로그에서 이 모듈의 용어가 보이면, 그 자체가 '무엇이 문제이고 누구에게 무엇을 물어야 하는지'의 단서입니다.
# 자바 앱 로그에서 핵심 키워드 추출
grep -iE 'hikari|outofmemory|full gc|connection is not available|timed out' app.log | tail -20
WARN HikariPool-1 - Connection is not available, request timed out after 30000ms
→ 커넥션 풀 고갈. 슬로우쿼리/누수/풀크기 확인([[connection-pooling]])
WARN G1 Full GC (Allocation Failure) 4521ms
→ Full GC가 4.5초! 그동안 앱 정지 → 메모리 압박([[jvm-operations]])
ERROR java.lang.OutOfMemoryError: Java heap space
→ Heap 부족. Dump로 한도부족 vs 누수 판별
grep -iE 'hikari|oom|gc|connection' app.log | tail -20- "Connection is not available / timed out" → 커넥션 풀 고갈. 먼저 슬로우 쿼리 여부, 그다음 트랜잭션 미종료(누수), 마지막으로 풀 크기를 본다(DB 연결 지연을 없애는 HikariCP 설정과 대기 성능 튜닝)
- "Full GC ... Nms"에서 N이 1초(1000ms)를 넘으면 그동안 앱이 멈춘 것(stop-the-world) → 메모리 압박 신호. 잦으면 Heap 증설 또는 누수 조사(Heap/GC/Thread Dump 분석과 OOM 대응 실무)
- "OutOfMemoryError: Java heap space" → Heap Dump를 떠서 메모리 사용이 우상향(누수)인지 일시적 폭증(한도부족)인지 구분. 한도만 올리면 누수는 재발
- "빈 주입 실패/NoSuchBeanDefinition" → DI 대상이 컨테이너에 없음(컴포넌트 스캔·설정 누락). 운영보다 빌드/기동 단계 문제
상황: 새 버전 배포 직후 응답이 느려지고 위 로그가 쏟아집니다. 사용자 요청이 줄줄이 타임아웃됩니다.
원인: 새 코드가 트랜잭션/커넥션을 제대로 반환하지 않거나(누수), 추가된 쿼리가 슬로우 쿼리라 커넥션을 오래 점유해 풀이 고갈됐습니다. 풀 크기(기본 10 등)보다 동시에 묶인 커넥션이 많아진 것입니다.
진단:
# 현재 DB 측 커넥션 상태(많이 idle in transaction이면 누수)
# PostgreSQL: SELECT state, count(*) FROM pg_stat_activity GROUP BY state;
grep -i "Connection is not available" app.log | wc -l # 빈도
해결: 단기로는 릴리스 전략에 따라 직전 버전으로 롤백. 근본 원인은 ① 슬로우 쿼리 → 인덱스/쿼리 개선(쿼리 실행 계획(Execution Plan) 읽는 법과 인덱스 최적화) ② 트랜잭션 미종료 → 코드 수정 ③ 풀 크기 부적정 → 부하 기준 재산정. 깊은 커넥션 풀 운영은 DB 연결 지연을 없애는 HikariCP 설정과 대기 성능 튜닝에서 다룹니다. PM·인프라는 이 로그를 보는 순간 "DB 커넥션 문제"로 방향을 좁혀 해당 변경의 쿼리·트랜잭션을 1순위로 검토하도록 이끕니다.
심화 — 장애는 한 용어에서 끝나지 않는다
심화: GC·커넥션 풀·스레드 풀이 하나의 장애로 엮이는 연쇄
이 모듈의 용어들은 장애 때 따로 오지 않습니다. 풀 고갈 로그는 원인이 아니라 연쇄의 마지막 증상인 경우가 많아서, 어떤 사슬로 엮이는지 알아야 로그를 거꾸로 추적할 수 있습니다.
- 전형적 연쇄: 메모리 압박 → Full GC(stop-the-world) → 처리 중이던 요청들이 멈춘 동안 커넥션을 쥔 채 대기 → 풀 고갈("Connection is not available") → 커넥션을 기다리는 요청이 스레드 풀까지 채움 → 헬스체크 타임아웃 → 인스턴스 재시작 → 재시작 직후 콜드 상태에서 같은 연쇄 재발. 로그엔 HikariCP가 찍히지만 범인은 GC인 셈입니다.
- 트랜잭션 안의 외부 호출은 풀의 숨은 지배자입니다: 트랜잭션 도중 외부 API를 3초씩 호출하면 그 3초 동안 커넥션을 쥐고 있습니다. 풀이 10개면 이 경로의 처리량 상한은 초당 약 3건 — 슬로우 쿼리가 하나도 없어도 풀은 마릅니다. "슬로우 쿼리가 없는데 풀이 고갈된다"면 트랜잭션 경계 안에 무엇이 들어 있는지(외부 호출·파일 IO)를 봐야 합니다.
- 면접이 파고드는 지점: "풀 고갈이면 풀을 키우면 되지 않나요?"에 "커넥션을 오래 쥐는 원인(슬로우 쿼리·트랜잭션 안 외부 호출·GC 정지)을 먼저 없애야 하고, 풀만 키우면 DB 동시 연결이 늘어 DB가 먼저 넘어진다"까지 답하면 운영을 아는 사람입니다. 풀 크기는 'DB가 감당할 동시 실행 수'에서 역산하는 값이지, 앱 쪽 대기를 없애 주는 다이얼이 아닙니다.
그래서 풀 고갈 알람의 점검 순서는 '풀 설정'이 아니라 무엇이 커넥션을 오래 쥐는가입니다 — 슬로우 쿼리(쿼리 실행 계획(Execution Plan) 읽는 법과 인덱스 최적화), 트랜잭션 안 외부 호출, GC 시간(Heap/GC/Thread Dump 분석과 OOM 대응 실무)을 한 타임라인에 놓고 봅니다.
상황: 주문 생성 중 예외가 나면 전체가 롤백돼야 하는데, 포인트 차감만 반영되고 주문은 없는 데이터가 발견됩니다. 코드를 보면 해당 메서드에 @Transactional이 분명히 붙어 있어 개발팀도 한동안 원인을 못 찾았습니다.
원인: 같은 클래스 안에서의 내부 호출이었습니다. 스프링의 @Transactional은 AOP 프록시가 메서드 호출을 가로채야 동작하는데, 같은 클래스의 다른 메서드가 this로 직접 호출하면 프록시를 거치지 않아 어노테이션이 조용히 무시됩니다. 트랜잭션 없이 실행되니 각 저장이 개별 커밋됐고, 중간에 예외가 나자 이미 커밋된 것(포인트 차감)만 남은 것입니다. 에러도 경고도 없이 '적용 안 됨'이라 발견이 늦습니다.
진단:
□ 호출 경로가 같은 클래스 내부 호출(this.메서드())인가?
□ 트랜잭션 로그 레벨을 올렸을 때 begin/commit이 메서드 단위로 찍히는가?
□ 예외가 checked exception은 아닌가? (기본 설정은 unchecked만 롤백)
해결: 트랜잭션 경계가 되는 메서드를 별도 빈으로 분리해 항상 프록시를 거쳐 호출되게 하거나, 트랜잭션을 진입점(다른 빈이 호출하는 공개 메서드)에서 시작하도록 구조를 바꿉니다. checked 예외까지 롤백하려면 rollbackFor를 명시합니다. 코드 리뷰 관점에서는 "@Transactional이 붙어 있는가"가 아니라 "프록시를 거쳐 호출되는가"를 확인 항목으로 삼습니다. PM·인프라는 '반쪽 데이터' 신고가 오면 트랜잭션 경계 미적용을 1순위 가설로 올려 개발팀의 탐색 범위를 좁혀 줄 수 있습니다.
인프라/SRE로서 자바 백엔드를 운영하면, 이 용어들은 곧 장애 알림과 대시보드의 언어입니다 — HikariCP 풀 사용률, GC 시간, Heap 사용량을 모니터링(용어사전)하고, 임계 초과 시 무엇을 의심할지 이 사전이 알려줍니다. PM은 이 용어를 알면 개발자의 장애 설명을 "얼마나 심각하고 사용자에게 어떤 영향인지"로 번역해 이해관계자에게 전달하고, 재발 방지(쿼리 개선·풀 튜닝·메모리 한도)를 백로그 우선순위로 올릴 수 있습니다. 용어를 모르면 장애 회의에서 통역이 필요하지만, 알면 바로 의사결정에 참여합니다.
다음 용어사전에서는 이 백엔드가 다루는 데이터 — DB·SQL·트랜잭션 용어를 정리합니다.
용어 식별 실습으로 굳히기: 용어 식별 — Backend / Java / Spring — 증상·로그·대화 문구를 보고 어떤 용어인지 가려내고 헷갈리는 짝을 구분합니다.