ยซ   2026/03   ยป
์ผ ์›” ํ™” ์ˆ˜ ๋ชฉ ๊ธˆ ํ† 
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
Archives
Recent Posts
03-20 12:39

Today
Total

Recent Comments
๊ด€๋ฆฌ ๋ฉ”๋‰ด

์—ฐ์˜ ๊ธฐ๋ก ๐Ÿช

์ปค๋„ฅ์…˜ ํ’€(Spring Boot, HikariCP) ๋ณธ๋ฌธ

Computer Science/๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค

์ปค๋„ฅ์…˜ ํ’€(Spring Boot, HikariCP)

kite707 2025. 9. 30. 23:21

๊ฐœ์š”

Spring Boot ๊ฐœ๋ฐœ์„ ํ•˜๋‹ค๋ณด๋ฉด application.yaml์„ ์•„๋ž˜์™€ ๊ฐ™์ด ์„ค์ •ํ•˜์—ฌ DB์™€ ์—ฐ๊ฒฐ์„ ํ•œ๋‹ค.

spring:
  application:
    name: backend-basics-for-juniors
    
  datasource:
    url: jdbc:mysql://localhost:3306/${DB_NAME}
    username: ${DB_USERNAME}
    password: ${DB_PASSWORD}
    driver-class-name: com.mysql.cj.jdbc.Driver
    
    hikari:
      maximum-pool-size: 10
      minimum-idle: 2
      connection-timeout: 30000

์—ฌ๊ธฐ ๋ณด์ด๋Š” hikari๋Š” HikariCP(ํžˆ์นด๋ฆฌ ์ปค๋„ฅ์…˜ ํ’€)์„ ์˜๋ฏธํ•˜๋Š”๋ฐ, HikariCP๋Š” JDBC ์ปค๋„ฅ์…˜ ํ’€ ๊ตฌํ˜„์ฒด์ด๋‹ค. build.gradle์„ ๋ณด๋ฉดimplementation 'org.springframework.boot:spring-boot-starter-jdbc' ์™€ ๊ฐ™์€ ์ฝ”๋“œ๊ฐ€ ์žˆ์„ํ…๋ฐ spring-boot-starter-jdbc ๋ฅผ ์“ฐ๋ฉด HikariCP๊ฐ€ ๊ธฐ๋ณธ ์ปค๋„ฅ์…˜ ํ’€๋กœ ์ž๋™ ์ ์šฉ๋œ๋‹ค.

 

์ปค๋„ฅ์…˜ ํ’€์ด๋ž€?

์ปค๋„ฅ์…˜ ํ’€์ด๋ž€ DB์— ์—ฐ๊ฒฐ๋œ ์ปค๋„ฅ์…˜์„ ๋ฏธ๋ฆฌ ์ƒ์„ฑํ•ด์„œ ๋ณด๊ด€ํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ์šฐ๋ฆฌ๊ฐ€ DB๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด DB์— ์—ฐ๊ฒฐํ•˜๊ณ , ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•œ ํ›„ ์—ฐ๊ฒฐ์„ ์ข…๋ฃŒํ•˜๋Š”๋ฐ, ์ด ์—ฐ๊ฒฐ์„ ๋ฏธ๋ฆฌ ๋งŒ๋“ค์–ด๋‘”๋‹ค๊ณ  ์ƒ๊ฐํ•˜๋ฉด ๋œ๋‹ค. ์ปค๋„ฅ์…˜์„ ๋ฏธ๋ฆฌ ๋งŒ๋“ค์–ด๋‘๋ฉด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ DB์ž‘์—…์ด ํ•„์š”ํ•  ๋•Œ ๋งŒ๋“ค์–ด์ ธ์žˆ๋Š” ์ปค๋„ฅ์…˜์„ ์‚ฌ์šฉํ•˜๊ณ , ์ฟผ๋ฆฌ ์ˆ˜ํ–‰์ด ๋๋‚˜๋ฉด ์ปค๋„ฅ์…˜ํ’€์— ์ปค๋„ฅ์…˜์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์‘๋‹ต์‹œ๊ฐ„์„ ์ค„์ด๋Š” ๊ฒƒ์ด๋‹ค.

์ปค๋„ฅ์…˜ ํ’€์—๋Š” ์—ฌ๋Ÿฌ๊ฐ€์ง€ ์„ค์ •์„ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ์ปค๋„ฅ์…˜ ํ’€ ํฌ๊ธฐ, ์ปค๋„ฅ์…˜ ๋Œ€๊ธฐ์‹œ๊ฐ„, ์ปค๋„ฅ์…˜ ์œ ์ง€์‹œ๊ฐ„ ๋“ฑ.. ๋งŽ์€ ์„ค์ •์ด ๊ฐ€๋Šฅํ•˜๊ณ  ๊ฐ ๊ฐ’๋“ค์„ ์ ์ ˆํ•˜๊ฒŒ ์„ค์ •ํ•˜์—ฌ ์„ฑ๋Šฅ์„ ํ–ฅ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ๋‹ค.

 

์ปค๋„ฅ์…˜ ํ’€ ์„ค์ •๊ฐ’

HikariCP์˜ ์„ค์ •๊ฐ’์€ HikariCP์˜ ๋ ˆํฌ์ง€ํ† ๋ฆฌ์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

Every property is optional, except for the "essentials" marked below.

HikariCP์— ์˜ํ•˜๋ฉด dataSourceClassName ํ˜น์€ jdbcUrl, username, password๋งŒ ๋ช…์‹œํ•˜๋ฉด ๋‹ค๋ฅธ ์„ค์ •๊ฐ’์€ ๋ชจ๋‘ ์˜ต์…˜์ด๋ผ๊ณ  ํ•œ๋‹ค.

์•„๋ž˜๋Š” HikariCP์˜ ์„ค์ •๊ฐ’ ์ค‘ ํ•„์ˆ˜๊ฐ’๊ณผ ์œ ์šฉํ•œ ์„ค์ •๋“ค์„ ์ •๋ฆฌํ•œ ๊ฒƒ์ด๋‹ค.

ํ•„์ˆ˜ ๊ฐ’ ์„ค๋ช… ์˜ˆ์‹œ ๊ฐ’
dataSourceClassName(๋˜๋Š” jdbcUrl์‚ฌ์šฉ) JDBC driver ๋งˆ๋‹ค ๋ช…์‹œ๋˜์–ด ์žˆ๋Š” Datasource class ์ด๋ฆ„ org.h2.jdbcx.JdbcDataSource
jdbcUrl(๋˜๋Š” dataSourceClassName ์‚ฌ์šฉ) jdbc ๋“œ๋ผ์ด๋ฒ„๊ฐ€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์—ฐ๊ฒฐํ•  ๋•Œ ์‚ฌ์šฉํ•˜๋Š” URL jdbc:mysql://localhost:3306/testdb
username DB ์—ฐ๊ฒฐ ์‹œ ์‚ฌ์šฉ๋˜๋Š” username username
password DB ์—ฐ๊ฒฐ ์‹œ ์‚ฌ์šฉ๋˜๋Š” password password
์œ ์šฉํ•œ ์„ค์ • ์„ค๋ช… ์˜ˆ์‹œ ๊ฐ’
autoCommit auto commit ์—ฌ๋ถ€(๊ธฐ๋ณธ๊ฐ’ true) true/false
connectionTimeout ์ปค๋„ฅ์…˜ ํ’€์—์„œ ์ปค๋„ฅ์…˜์„ ์–ป์ง€ ๋ชปํ–ˆ์„ ๋•Œ ๊ธฐ๋‹ค๋ฆด ์‹œ๊ฐ„(๊ธฐ๋ณธ๊ฐ’: 30000(30์ดˆ)) 30000
idleTimeout ์ปค๋„ฅ์…˜์ด ์‚ฌ์šฉ๋˜์ง€ ์•Š์•˜์„ ๋•Œ ์ปค๋„ฅ์…˜์— ๋จธ๋ฌด๋Š” ์ตœ๋Œ€ ์‹œ๊ฐ„
0์œผ๋กœ ์„ค์ • ์‹œ ์ปค๋„ฅ์…˜์ด ์˜ค๋žœ ์‹œ๊ฐ„ ์‚ฌ์šฉ๋˜์ง€ ์•Š์•„๋„ ์ œ๊ฑฐ๋˜์ง€ ์•Š์Œ.(๊ธฐ๋ณธ๊ฐ’: 6000000(10๋ถ„)
600000
keepaliveTime ์œ ํ›„(idle)์ƒํƒœ์ธ ์ปค๋„ฅ์…˜์— ping์„ ๋ณด๋‚ด๊ณ , ํ•ด๋‹น ์ปค๋„ฅ์…˜์ด ์ฃฝ์€ ๊ฒƒ์œผ๋กœ ํŒ๋‹จ๋˜๋ฉด ์ƒˆ ์ปค๋„ฅ์…˜์œผ๋กœ ๊ต์ฒด(๊ธฐ๋ณธ๊ฐ’: 120000(2๋ถ„)) 120000
maxLifetime ์ปค๋„ฅ์…˜์˜ ์ตœ๋Œ€ ์ƒ์กด ์‹œ๊ฐ„
โš ๏ธDB๋‚˜ ๋„คํŠธ์›Œํฌ์—์„œ ์„ค์ •๋œ ์ปค๋„ฅ์…˜ ์ตœ๋Œ€ ์œ ์ง€ ์‹œ๊ฐ„๋ณด๋‹ค ์กฐ๊ธˆ ์งง๊ฒŒ ์„ค์ •ํ•  ๊ฒƒ ๊ถŒ๊ณ . (๊ธฐ๋ณธ๊ฐ’: 1800000(30๋ถ„))
1800000
minimumIdle ์ตœ์†Œ ์œ ํœด(idle)์ปค๋„ฅ์…˜ ์ˆ˜(๊ธฐ๋ณธ๊ฐ’: maximumPoolSize๊ฐ’๊ณผ ๋™์ผ) 10
maximumPoolSize ์ปค๋„ฅ์…˜ ํ’€์— ์กด์žฌํ•˜๋Š” ์ปค๋„ฅ์…˜์˜ ์ตœ๋Œ€ ์ˆ˜(๊ธฐ๋ณธ๊ฐ’: 10) 10

์œ„ ์„ค์ •๊ฐ’๋“ค์„ ์„œ๋น„์Šค ์„ฑ๊ฒฉ์— ๋”ฐ๋ผ ์ ์ ˆํ•˜๊ฒŒ ์„ค์ •ํ•˜๋ฉด ๋œ๋‹ค. ์˜ˆ๋ฅผ๋“ค์–ด connectionTimeout์€ ์ปค๋„ฅ์…˜ ํ’€์—์„œ ์ปค๋„ฅ์…˜์„ ์–ป์ง€ ๋ชปํ–ˆ์„ ๋•Œ ๋ช‡์ดˆ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆด ๊ฒƒ์ธ์ง€๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ๊ฐ’์ธ๋ฐ, ๊ธฐ๋ณธ๊ฐ’์€ 30์ดˆ์ด๋‹ค. ์ฆ‰ ์ตœ์•…์˜ ๊ฒฝ์šฐ 30์ดˆ๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๊ณ  ์ฟผ๋ฆฌ๊ฐ€ ์‹คํ–‰๋œ๋‹ค๋Š” ๊ฒƒ์ธ๋ฐ ๋น ๋ฅธ ์‘๋‹ต์ด ์š”๊ตฌ๋˜๋Š” ์„œ๋น„์Šค๋ผ๋ฉด ํ•ด๋‹น ๊ฐ’์„ ์ค„์ด๋Š” ๊ฒƒ์ด ์ข‹๋‹ค. ๋˜ ๋งŽ์€ ํŠธ๋ž˜ํ”ฝ์ด ๋ชฐ๋ฆฌ๋Š” ์„œ๋น„์Šค์˜ ๊ฒฝ์šฐ์—๋„ connectionTimeout์„ ์งง๊ฒŒ ์„ค์ •ํ•˜๊ณ  ์ปค๋„ฅ์…˜์„ ๊ฐ€์ ธ์˜ค์ง€ ๋ชปํ–ˆ์„ ๋•Œ ๋น ๋ฅด๊ฒŒ ์—๋Ÿฌ๋ฅผ ์‘๋‹ตํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค. ์ด๋ฏธ ๋Œ€๊ธฐ์ค‘์ธ ์š”์ฒญ์ด ๋งŽ์€๋ฐ ๊ธฐ๋‹ค๋ฆฌ๋˜ ์‚ฌ์šฉ์ž๊ฐ€ ์žฌ์š”์ฒญ์„ ๋ณด๋‚ธ๋‹ค๋ฉด ๋Œ€๊ธฐ์ค‘์ธ ์š”์ฒญ ๊ฑด์ˆ˜๊ฐ€ ๊ฑท์žก์„ ์ˆ˜ ์—†์ด ๋Š˜์–ด๋‚˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

๋˜ maxLifetime๊ณผ idleTimeout๋„ ์–ผํ• ๋น„์Šทํ•ด๋ณด์ด์ง€๋งŒ ์ ์šฉ ๋Œ€์ƒ๊ณผ ๊ทธ ์šฉ๋„๊ฐ€ ๋‹ค๋ฅด๋‹ค. maxLifetime์€ ์ปค๋„ฅ์…˜์˜ ์ตœ๋Œ€ ์ƒ์กด ์‹œ๊ฐ„์ด๋‹ค. ์œ ํœด(idle)์ƒํƒœ์™€ ์‚ฌ์šฉ์ค‘์ธ ์ƒํƒœ์˜ ์ปค๋„ฅ์…˜์— ๋ชจ๋‘ ์ ์šฉ๋˜์ง€๋งŒ ์‚ฌ์šฉ์ค‘์ธ ์ปค๋„ฅ์…˜์„ ์ œ๊ฑฐํ•˜์ง€๋Š” ์•Š๋Š”๋‹ค. ์˜ˆ๋ฅผ๋“ค์–ด maxLifetime์ด 30๋ถ„์œผ๋กœ ์ ์šฉ๋˜์–ด์žˆ์„ ๋•Œ ์ƒ์„ฑ๋œ์ง€ 30๋ถ„์ด ๋‹ค ๋˜์–ด๊ฐ€๋Š” ์ปค๋„ฅ์…˜์ด ์ฟผ๋ฆฌ ์ˆ˜ํ–‰ ์ค‘ 30๋ถ„์ด ๋œ๋‹ค๊ณ  ํ•ด๋„ ํ•ด๋‹น ์ปค๋„ฅ์…˜์„ ์ œ๊ฑฐํ•˜์ง€ ์•Š๋Š”๋‹ค. ์ดํ›„ ์ž‘์—…์ด ๋๋‚˜๋ฉด ํ•ด๋‹น ์ปค๋„ฅ์…˜์ด ์ œ๊ฑฐ๋œ๋‹ค. ์ด ์„ค์ •๊ฐ’์˜ ๋ชฉ์ ์€ DB์— ํด๋ผ์ด์–ธํŠธ์™€ ์ผ์ • ์‹œ๊ฐ„ ์ƒํ˜ธ์ž‘์šฉ์ด ์—†๋‹ค๋ฉด ์ž๋™์œผ๋กœ ์—ฐ๊ฒฐ์„ ๋Š๋Š” ๊ธฐ๋Šฅ์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ์ฆ‰ DB์ชฝ์—์„œ๋Š” ์—ฐ๊ฒฐ์„ ๋Š์—ˆ๋Š”๋ฐ, ํ•ด๋‹น ์ปค๋„ฅ์…˜์ด ๊ณ„์† ํ’€์— ๋‚จ์•„์žˆ๋‹ค๊ฐ€ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ํ•ด๋‹น ์ปค๋„ฅ์…˜์„ ์‚ฌ์šฉํ•˜๋ ค๊ณ  ํ•˜๋ฉด ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•  ๊ฒƒ์ด๋‹ค. ๊ทธ๋ ‡๊ธฐ์— HikariCP์—์„œ๋Š” DB๋‚˜ ๋„คํŠธ์›Œํฌ์—์„œ ์„ค์ •๋œ ์ปค๋„ฅ์…˜ ์ตœ๋Œ€ ์œ ์ง€ ์‹œ๊ฐ„๋ณด๋‹ค ์กฐ๊ธˆ ์งง๊ฒŒ ์„ค์ •ํ•  ๊ฒƒ์„ ๊ถŒ๊ณ ํ•˜๊ณ  ์žˆ๋‹ค.

idleTimeout์€ ์œ ํœด(idle)์ƒํƒœ์˜ ์ปค๋„ฅ์…˜์— ๋Œ€ํ•ด์„œ๋งŒ ์ ์šฉ๋œ๋‹ค. ์˜ˆ๋ฅผ๋“ค์–ด ์˜ค์ „์— ํŠธ๋ž˜ํ”ฝ์ด ๋งŽ์ด ๋ชฐ๋ ค์„œ 10๊ฐœ์˜ ์ปค๋„ฅ์…˜์ด ์ƒ์„ฑ๋˜์—ˆ์ง€๋งŒ ์˜คํ›„์— ํŠธ๋ž˜ํ”ฝ์ด ๋–จ์–ด์กŒ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜์ž. ์ด ๊ฒฝ์šฐ 10๊ฐœ์˜ ์ปค๋„ฅ์…˜์„ ๋ชจ๋‘ ์ปค๋„ฅ์…˜ํ’€์— ์œ ์ง€ํ•˜๊ณ  ์žˆ์„ ํ•„์š”๊ฐ€ ์—†๋‹ค. ๊ทธ๋ž˜์„œ ์ผ์ • ์‹œ๊ฐ„ ์ด์ƒ ์œ ํœด(idle)์ƒํƒœ์ธ ์ปค๋„ฅ์…˜์€ ๋ถˆํ•„์š”ํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•˜๊ณ  ์ œ๊ฑฐํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

 

์ฝ”๋“œ ์‹ค์Šต

์•„๋ž˜ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ํ†ตํ•ด ์ปค๋„ฅ์…˜ ํ’€์— ๋Œ€ํ•œ ์„ค์ •๊ฐ’์„ ๋ฐ”๊ฟ”๊ฐ€๋ฉฐ ์—ฌ๋Ÿฌ ์ƒํ™ฉ์„ ํ…Œ์ŠคํŠธํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด ์ฝ”๋“œ๋Š” ์ปค๋„ฅ์…˜ ํ’€ ํฌ๊ธฐ ์ œํ•œ์„ 2๋กœ ์„ค์ •ํ•˜๊ณ , ๊ทธ ์ด์ƒ์œผ๋กœ ์ปค๋„ฅ์…˜์„ ๊ฐ€์ ธ์˜ค๋ ค๋Š” ์ฝ”๋“œ์ด๋‹ค. ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•ด์•ผ ํ…Œ์ŠคํŠธ๊ฐ€ ํ†ต๊ณผ๋œ๋‹ค.

์ฐธ๊ณ ๋กœ JdpcTemplate๋‚˜ JPA๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ปค๋„ฅ์…˜์„ ์–ป๊ฑฐ๋‚˜ ๋‹ซ๋Š” ๊ฒƒ์€ ๋‚ด๋ถ€์ ์œผ๋กœ ๊ด€๋ฆฌํ•ด์ฃผ๊ธฐ ๋•Œ๋ฌธ์— ์ง์ ‘ ํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค.

package com.backend.backendbasicsforjuniors.ch01.connectionPool;

import static org.assertj.core.api.Assertions.assertThat;

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import java.sql.Connection;
import java.sql.SQLException;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.autoconfigure.jdbc.JdbcTest;

@JdbcTest
class UserRepositoryTest {
    HikariConfig config = new HikariConfig();

    @BeforeEach
    void setUp() {
        config.setJdbcUrl("jdbc:h2:mem:testdb"); // H2 ์ธ๋ฉ”๋ชจ๋ฆฌ
        config.setUsername("sa");
        config.setPassword("");
        config.setMaximumPoolSize(2); // ํ’€ ํฌ๊ธฐ ์ œํ•œ
        config.setConnectionTimeout(500); // 0.5์ดˆ๋กœ ์งง๊ฒŒ ์„ค์ •
    }

    @Test
    @DisplayName("์ปค๋„ฅ์…˜ ํ’€ ๊ฐœ์ˆ˜ ์ด์ƒ์œผ๋กœ ์š”์ฒญ ๊ฐ€์ ธ์˜ค๊ธฐ")
    void testMaximumPoolSize() throws SQLException {
        try (HikariDataSource dataSource = new HikariDataSource(config)) {
            // ์ปค๋„ฅ์…˜ ์—ฌ๋Ÿฌ ๊ฐœ ๋™์‹œ์— ๊ฐ€์ ธ์˜ค๊ธฐ
            Connection conn1 = dataSource.getConnection();
            Connection conn2 = dataSource.getConnection();

            assertThat(conn1).isNotNull();
            assertThat(conn2).isNotNull();

            // ์ตœ๋Œ€ ํ’€์„ ๋„˜๋Š” ์ปค๋„ฅ์…˜ ์š”์ฒญ → timeout ๋ฐœ์ƒ ํ™•์ธ
            Exception exception = null;
            try {
                dataSource.getConnection(); // 3๋ฒˆ์งธ ์ปค๋„ฅ์…˜
            } catch (SQLException e) {
                exception = e;
            }
            System.out.println(exception);
            assertThat(exception).isNotNull(); // timeout ์˜ˆ์™ธ ํ™•์ธ
        }
    }

}