F-LAB JAVA · 6주차 · Phase 4 · Connection Pool과 DB 세션
이 Unit을 끝내면 다음을 답할 수 있어야 한다.
DB 연결은 TCP 연결 → 세션 생성 → SQL 실행 → 트랜잭션 종료 → 연결 종료의 5단계로 진행되며, 한 Connection 은 하나의 DB 세션과 1:1 매핑되어 동시에 두 트랜잭션을 진행할 수 없고, 따라서 커넥션 풀의 Connection 100 개는 DB 입장에서 세션 100 개로 보인다.
DB 연결 절차는 (1) 클라이언트 ↔ DB 서버 TCP 연결, (2) DB 가 세션 생성 (트랜잭션 단위), (3) 클라이언트 → SQL 전달, 세션이 실행, (4) 세션이 트랜잭션 시작 → commit/rollback 으로 종료, (5) 사용자가 connection close 또는 DB 관리자가 세션 종료다.
세션 은 DB 서버가 클라이언트별로 할당하는 자원 단위로, 트랜잭션 컨텍스트·캐시·임시 데이터 등을 보관한다.
한 Connection 은 하나의 DB 세션과 1:1 매핑 되며, 한 세션은 동시에 한 개의 트랜잭션만 진행할 수 있어 한 Connection 에서 두 트랜잭션 동시 진행은 불가능 하다.
따라서 애플리케이션이 커넥션 풀에 Connection 100 개를 둔다면 DB 서버는 세션 100 개를 들고 있는 것 이며, 풀 크기 결정 시 DB 의max_connections한계를 반드시 고려해야 한다.
DB 세션 = 호텔 객실:
연결 절차 (5단계):
1. 호텔 도착 (TCP 연결)
2. 체크인 — 객실 배정 (세션 생성)
3. 활동 (SQL 실행)
4. 일정 (트랜잭션) — commit/cancel
5. 체크아웃 (연결 종료)
Connection ↔ 세션 (1:1):
- 투숙객 1명 = 객실 1개
- 한 객실에 한 일정 (동시 두 트랜잭션 X)
- 동시 작업하려면 객실 2개
풀 100 개 = 객실 100 개:
- 호텔 관점:
- 객실 100개 점유
- 메모리/자원
- 다른 손님 못 받음
max_connections:
- 호텔 객실 한계 (151)
- 초과 시 거부
DB 입장:
- 풀이 보이지 않음
- 그냥 N 개 세션
- 누구든 같음
→ 연결 5단계 + Connection ↔ Session 1:1 + 풀 N 개 = DB 세션 N 개.
1. DB 연결 5단계
2. DB 세션이란
3. 세션 = 트랜잭션 단위
4. Connection ↔ Session 1:1
5. 한 Connection 두 트랜잭션 불가
6. 풀 N개 = 세션 N개
7. 세션 종료 방식
8. DB 입장의 풀
9. 면접 + 자기 점검
DB 연결 5단계:
1. TCP 연결 (클라 → DB)
2. 세션 생성 (DB 가 할당)
3. SQL 실행 (요청·응답)
4. 트랜잭션 종료 (commit/rollback)
5. 연결 종료 (close)
1. TCP 연결:
클라이언트 ↔ DB 서버:
- TCP 3-way handshake
- 네트워크 채널 수립
→ Unit 4.1 비용
2. 세션 생성:
DB:
- 인증 (ID/PW)
- 세션 객체 생성
- 메모리 할당
- 세션 ID 부여
3. SQL 실행:
클라이언트 → DB:
- SQL 전송
DB → 클라이언트:
- 결과 반환
세션 안에서 수행
4. 트랜잭션 종료:
세션이:
- 트랜잭션 시작 (BEGIN)
- SQL 실행
- commit (확정) 또는 rollback (취소)
여러 트랜잭션 가능 (순차)
5. 연결 종료:
종료 주체:
- 클라이언트: connection.close()
- DB 관리자: 세션 강제 종료
- 타임아웃 (idle)
→ 세션 해제, TCP 종료
DB 연결 5단계 (ILIC)
ILIC backend → MySQL:
1. TCP 연결:
- backend → mysql:3306
- 3-way handshake
2. 세션 생성:
- 인증 (ilic_user/pwd)
- 세션 ID 부여
- 메모리 할당
3. SQL 실행:
- SELECT * FROM shipments WHERE id = 1
- 결과 반환
4. 트랜잭션 종료:
- INSERT/UPDATE/DELETE
- commit
5. 연결 종료:
- close() (또는 풀로 반환)
- 세션 해제
→ Connection Pool 에선 5번 거의 X (재사용)
DB 연결 절차 5단계는?
답:
1. 5단계:
TCP:
세션:
종료:
DB 세션:
DB 가 클라이언트에 할당:
- 자원 단위
- 메모리/상태
- 트랜잭션 컨텍스트
세션의 내용:
- 세션 ID
- 인증된 사용자
- 현재 데이터베이스
- 트랜잭션 상태
- 임시 테이블
- 세션 변수
- 캐시 (PGA 등)
세션 격리:
세션끼리:
- 독립
- 다른 세션 메모리 X
- 다른 세션 트랜잭션 X
→ DB 가 격리 보장
DB 서버 자원:
세션마다:
- 메모리 (수 MB)
- 백그라운드 프로세스 (Oracle)
- 파일 디스크립터
→ 무한 X (max_connections)
DB 세션 (ILIC MySQL)
ILIC MySQL 세션 확인:
-- 현재 세션 목록
SHOW PROCESSLIST;
-- 결과
+----+-----------+------+----+-------+---------+
| Id | User | Host | DB | Time | Command |
+----+-----------+------+----+-------+---------+
| 10 | ilic_user | ... |ilic| 0 | Sleep |
| 11 | ilic_user | ... |ilic| 1 | Query |
| 12 | ilic_user | ... |ilic| 0 | Sleep |
| ...
+----+-----------+------+----+-------+---------+
HikariCP 풀이 maximum=20:
- 약 20개 세션 (PROCESSLIST)
- 각각 자원 사용 (메모리 등)
DB 세션이란?
답:
1. 세션:
내용:
격리:
자원:
세션 = 트랜잭션 단위:
한 세션:
- 한 번에 한 트랜잭션
- 순차 진행
- commit/rollback 으로 종료
트랜잭션 흐름 (한 세션):
세션 생성
↓
트랜잭션1 시작 → SQL → commit
↓
트랜잭션2 시작 → SQL → rollback
↓
트랜잭션3 시작 → SQL → commit
↓
세션 종료
autocommit:
JDBC 기본: autocommit = true
- 각 SQL = 자동 commit
- 트랜잭션 짧음
명시적 트랜잭션:
- autoCommit = false
- 명시적 commit/rollback
세션의 트랜잭션 상태:
- 트랜잭션 미시작 (idle)
- 트랜잭션 진행 (active)
- 대기 (waiting on lock)
→ 세션이 추적
// 세션의 트랜잭션 (ILIC)
@Service
public class ShipmentService {
@Transactional // 한 트랜잭션
public void createShipment(Shipment s) {
shipmentDao.add(s); // SQL1
bookingDao.updateStatus(s.getId()); // SQL2
// 같은 세션, 한 트랜잭션
// 메서드 끝 → commit
}
// 메서드 호출마다:
// 1. Connection 빌림 (풀에서, = 세션 1개)
// 2. 트랜잭션 시작
// 3. SQL1, SQL2 (같은 세션)
// 4. commit (트랜잭션 종료)
// 5. Connection 반환 (= 세션 유지, 풀에)
ShipmentDao shipmentDao;
BookingDao bookingDao;
}
class ShipmentDao { void add(Shipment s) {} }
class BookingDao { void updateStatus(Long id) {} }
class Shipment { Long getId() { return null; } }
세션 = 트랜잭션 단위의 의미는?
답:
1. 트랜잭션 단위:
흐름:
autocommit:
상태:
Connection ↔ Session:
한 Connection (애플리케이션)
↕ 1:1
한 Session (DB)
- Connection 만들 때 세션 생성
- Connection 닫을 때 세션 해제
매핑 의미:
애플리케이션 Connection:
= DB 서버 Session
→ 둘이 같은 것의 양면
풀의 Connection:
HikariCP 풀에 N 개 Connection:
- DB 에 N 개 세션
- 1:1
→ 풀 ≒ DB 세션 묶음
시각화:
[애플리케이션] [DB 서버]
┌─────────────────┐ ┌────────────────┐
│ HikariPool │ │ Sessions │
│ ┌─────────────┐ │ TCP 연결 │ ┌────────────┐ │
│ │ Conn 1 │ │←─────────────│→│ Session 1 │ │
│ │ Conn 2 │ │←─────────────│→│ Session 2 │ │
│ │ Conn 3 │ │←─────────────│→│ Session 3 │ │
│ │ ... │ │ │ │ ... │ │
│ │ Conn N │ │←─────────────│→│ Session N │ │
│ └─────────────┘ │ │ └────────────┘ │
└─────────────────┘ └────────────────┘
→ N : N 짝
Connection ↔ Session 1:1 (ILIC)
ILIC HikariCP (maximum=20):
- 풀에 Connection 20개
- MySQL 에 Session 20개
애플리케이션 측:
- Connection 객체 20개 (메모리)
- 풀이 관리
DB 측 (MySQL):
- Session 20개 (메모리)
- PROCESSLIST 에 20행
애플리케이션이 풀 크기 늘리면:
- Connection ↑ → Session ↑
- DB 부담 증가
- max_connections 고려
→ 1:1 이므로 풀 크기 = DB 세션 수
Connection ↔ Session 1:1 인가?
답:
1. 1:1 매핑:
의미:
풀 N:
시각화:
한 Connection 두 트랜잭션 동시:
→ 불가능
이유:
- 세션 = 트랜잭션 단위
- 한 세션 = 한 트랜잭션
시도 시:
같은 Connection 으로:
- 트랜잭션1 진행 중
- 트랜잭션2 시작?
- → 트랜잭션1 영향 받음
→ 트랜잭션 격리 깨짐
멀티스레드 + 같은 Connection:
스레드 A: 트랜잭션 A
스레드 B: 같은 Connection 으로 트랜잭션 B
→ 위험!
→ Connection 은 스레드 안전 X
해결:
다른 트랜잭션 동시 진행:
- 다른 Connection
- 다른 세션
→ 풀에서 두 개 빌림
한 트랜잭션 = 한 Connection:
트랜잭션 시작:
- Connection 빌림 (세션 잡음)
트랜잭션 중:
- 같은 Connection 유지
- 다른 작업 못 끼어듦
commit/rollback:
- Connection 반환
// 한 Connection 두 트랜잭션 불가 (ILIC)
@Service
public class ShipmentService {
@Transactional
public void processBooking(Booking b) {
// 이 메서드 실행 동안:
// - Connection 1개 점유 (트랜잭션 A)
// - 같은 Connection 으로 다른 트랜잭션 동시 X
shipmentDao.add(b.getShipment()); // SQL (트랜잭션 A)
bookingDao.save(b); // SQL (트랜잭션 A)
// 같은 Connection
// 메서드 끝 → commit
}
// 다른 트랜잭션 동시 진행하려면:
@Async // 다른 스레드 + 다른 Connection
public void asyncTask() {
// 다른 Connection 빌림 → 다른 세션 → 별도 트랜잭션
}
ShipmentDao shipmentDao;
BookingDao bookingDao;
}
class Booking { Object getShipment() { return null; } }
class ShipmentDao { void add(Object o) {} }
class BookingDao { void save(Object o) {} }
한 Connection 에서 동시 두 트랜잭션 가능한가?
답:
1. 불가능:
이유:
멀티스레드:
해결:
풀 N 개 Connection
= DB N 개 세션
- 1:1 매핑 (섹션 4)
- 풀 늘리면 세션 늘어남
DB 입장:
애플리케이션 풀 모름:
- 그냥 N 개 클라이언트
- 각자 세션
- 자원 할당
max_connections:
DB 의 최대 세션 한계:
- MySQL: 151 (기본)
- PostgreSQL: 100 (기본)
- 늘릴 수 있지만 자원 ↑
→ 풀 크기 + 다른 클라이언트 ≤ max
여러 애플리케이션 서버:
ILIC backend 3대 × 풀 20 = 60 세션
+ admin 서버 5
+ 배치 서버 10
= 75 세션
→ DB max_connections > 75 필요
→ 여유분 (운영/관리자) 도 고려
풀 N = 세션 N (ILIC)
ILIC 환경:
- MySQL max_connections = 151
- backend (1대) × HikariCP (20) = 20 세션
- 배치 작업 풀 (5) = 5 세션
- 운영 도구 (10) = 10 세션
- 합 = 35 세션 (안전)
확장 시:
- backend 5대 × 20 = 100
- 다른 것 + 25 = 125
- max (151) 까지 여유 26
→ 스케일 아웃 시 max_connections 고려
→ DB 측 설정도 함께 (my.cnf)
풀의 Connection N 개 = DB 세션 N 개인가?
답:
1. N = N:
DB 입장:
max_connections:
여러 서버:
세션 종료:
1. 클라이언트가 close
2. 타임아웃 (idle)
3. DB 관리자 강제 (KILL)
4. DB 서버 종료
5. 네트워크 끊김
// 클라이언트 close
connection.close();
// → DB 에 종료 알림
// → 세션 해제
// → TCP 4-way handshake
idle 타임아웃:
세션 일정 시간 미사용:
- 자동 종료
- 자원 회수
MySQL: wait_timeout (기본 8시간)
HikariCP: idle-timeout (10분)
→ 양쪽 시간 조율 필요
-- DB 관리자 강제 종료 (MySQL)
SHOW PROCESSLIST; -- 세션 목록
KILL 12; -- 세션 ID 12 종료
-- PostgreSQL
SELECT pg_terminate_backend(pid);
종료 시 정리:
세션 종료:
- 미완료 트랜잭션 rollback
- 메모리 해제
- 잠금 해제 (lock)
- 임시 데이터 정리
-- 세션 종료 사례 (ILIC)
-- 1. 평소: HikariCP 가 close (풀로 반환, 세션 유지)
-- 2. idle 타임아웃:
-- HikariCP idle-timeout (10분) 보다
-- MySQL wait_timeout (28800 = 8시간) 길어야
-- → 안 그러면 끊긴 Connection 사용 위험
-- 3. 운영 도구로 확인
SHOW PROCESSLIST;
-- ID User Time Command
-- 12 ilic_user 3600 Sleep ← 1시간 idle
-- 13 ilic_user 0 Query
-- 4. 문제 세션 강제 종료 (운영자)
KILL 12;
-- 5. 애플리케이션 재시작 시
-- → HikariCP 가 모든 Connection close
-- → 세션 모두 해제
세션 종료 방식은?
답:
1. 종료:
close:
idle:
강제:
DB 가 보는 풀:
애플리케이션 풀 X:
- 그냥 N 개 클라이언트
- 각자 세션
- 누가 풀인지 모름
→ 풀은 클라이언트 개념
클라이언트 인지:
DB 측:
- Connection 들 = 평범한 세션
- HikariCP 알 필요 없음
- 그저 N 개 사용자
→ 풀은 추상화 (DB 무관)
DB 자원 관점:
세션 N 개:
- 메모리 (N × 수 MB)
- CPU (인증/캐시)
- 파일 디스크립터
→ N 작을수록 DB 부담 ↓
-- DB 입장 모니터링 (MySQL)
-- 활성 세션
SHOW PROCESSLIST;
-- 세션 수
SELECT COUNT(*) FROM information_schema.processlist;
-- 활성/슬립 비율
SELECT command, COUNT(*)
FROM information_schema.processlist
GROUP BY command;
-- max_connections
SHOW VARIABLES LIKE 'max_connections';
DB 입장 모니터링 (ILIC MySQL)
ILIC MySQL 모니터링:
-- 현재 세션
SHOW PROCESSLIST;
→ ilic_user 의 세션들 (HikariCP 풀)
+ 운영 도구 세션
+ 백그라운드
-- 사용량
SELECT
(SELECT COUNT(*) FROM information_schema.processlist) AS used,
(SELECT @@max_connections) AS max,
ROUND(
(SELECT COUNT(*) FROM information_schema.processlist)
/ @@max_connections * 100, 2
) AS pct;
→ 사용률 (예: 35 / 151 = 23%)
→ 풀 크기 조정 근거
→ max_connections 증설 시점
DB 입장에서 풀이 어떻게 보이나?
답:
1. DB 입장:
인지:
자원:
모니터링:
| Q | 핵심 답변 |
|---|---|
| 연결 5단계? | TCP/세션/SQL/트랜잭션/종료 |
| DB 세션? | DB 가 할당한 자원 |
| 세션 단위? | 트랜잭션 |
| Connection-Session? | 1:1 |
| 한 Conn 두 TX? | 불가 (세션 1 TX) |
| 풀 N = ? | 세션 N |
| 종료? | close/idle/KILL |
| DB 입장? | N 개 세션 |
| max_connections? | DB 한계 |
| 풀과 세션 차이? | 클라/서버 |
답:
답:
답:
답:
답:
1. 연결 5단계와 세션
2. Connection ↔ Session 1:1
3. 풀 N = 세션 N
이번 Unit에서 세션/연결을 봤다면, 다음은 DB Lock (Phase 4 마지막).
🔗 Phase 4 — Connection Pool과 DB 세션
✅ Unit 4.1 매 요청마다 연결의 비효율
✅ Unit 4.2 Connection Pool 개념 ★깊이
✅ Unit 4.3 DB 세션과 연결 구조 ← 여기
⏭ Unit 4.4 DB Lock 개념 — Phase 4 완주
🧪 Part A (9 Unit) ✅
💾 Part B — DB 접근의 진화
✅ Phase 3 — JDBC (3)
🔗 Phase 4 — Connection Pool (3/4)
총: 15/28 Unit