
๋ฌธ์ ๊ฐ์
๐ก spring-boot-starter-data-jpa๋ฅผ ์์กด์ฑ์ ์ถ๊ฐํ๋ฉด HikariCP๊ฐ ์๋์ผ๋ก ํฌํจ๋ฉ๋๋ค.
Spring Boot ๊ธฐ๋ณธ Connection Pool์ธ HikariCP์ ํต์ฌ ์ค์ ์ ์ดํดํ๊ณ ,
AWS RDS Multi-AZ failover ์ํฉ์์ ์์ ์ ์ผ๋ก ๋ณต๊ตฌํ๋ ๋ฐฉ๋ฒ์ ๋ค๋ฃน๋๋ค.
1. Connection Pool์ด๋?
DB์ ์ฟผ๋ฆฌ๋ฅผ ๋ณด๋ด๋ ค๋ฉด ๋จผ์ ์ฐ๊ฒฐ(Connection)์ ๋ง๋ค์ด์ผ ํฉ๋๋ค.
์ด ์ฐ๊ฒฐ์ ๋ง๋๋ ๋ฐ ์ฝ 50ms๊ฐ ๊ฑธ๋ฆฌ๋๋ฐ, ์์ฒญ๋ง๋ค ๋ง๋ค๊ณ ๋์ผ๋ฉด ๋ญ๋น์
๋๋ค.
[Pool ์์ด] โ ์์ฒญ๋ง๋ค ์ฐ๊ฒฐ์ ์๋ก ๋ง๋ค๊ณ ๋์ (๋๋ฆผ)
์์ฒญ1 โ ์ฐ๊ฒฐ ์์ฑ(50ms) โ ์ฟผ๋ฆฌ โ ์ฐ๊ฒฐ ์ข
๋ฃ
์์ฒญ2 โ ์ฐ๊ฒฐ ์์ฑ(50ms) โ ์ฟผ๋ฆฌ โ ์ฐ๊ฒฐ ์ข
๋ฃ
์์ฒญ3 โ ์ฐ๊ฒฐ ์์ฑ(50ms) โ ์ฟผ๋ฆฌ โ ์ฐ๊ฒฐ ์ข
๋ฃ[Pool ์์ผ๋ฉด] โ ๋ฏธ๋ฆฌ ์ฐ๊ฒฐ์ ๋ง๋ค์ด๋๊ณ ๋น๋ ค์ฐ๊ณ ๋ฐ๋ฉ (๋น ๋ฆ)
Pool: [์ฐ๊ฒฐ1, ์ฐ๊ฒฐ2, ์ฐ๊ฒฐ3, ... ์ฐ๊ฒฐ10] โ ์ฑ ์์ ์ ๋ฏธ๋ฆฌ ์์ฑ
์์ฒญ1 โ ์ฐ๊ฒฐ1 ๋น๋ฆผ โ ์ฟผ๋ฆฌ โ ๋ฐ๋ฉ
์์ฒญ2 โ ์ฐ๊ฒฐ2 ๋น๋ฆผ โ ์ฟผ๋ฆฌ โ ๋ฐ๋ฉ
์์ฒญ3 โ ์ฐ๊ฒฐ1 ๋น๋ฆผ โ ์ฟผ๋ฆฌ โ ๋ฐ๋ฉ โ ๋ฐ๋ฉ๋ ์ฐ๊ฒฐ ์ฌ์ฌ์ฉ!
HikariCP๋ Spring Boot๊ฐ ๊ธฐ๋ณธ์ผ๋ก ์ฌ์ฉํ๋ Connection Pool ๋ผ์ด๋ธ๋ฌ๋ฆฌ์
๋๋ค.
๊ฐ์ฅ ๋น ๋ฅด๊ณ ๊ฐ๋ฒผ์ด ๊ฒ์ผ๋ก ์ ๋ช
ํฉ๋๋ค. ๐๐
2. ํต์ฌ ์ค์ ๊ฐ ํ๋์ฉ ์ดํดํ๊ธฐ
2-1. connection-timeout โ "์ฐ๊ฒฐ ๋น๋ฆฌ๋ ค๊ณ ์ผ๋ง๋ ๊ธฐ๋ค๋ฆด๊น?"
connection-timeout: 3000 # 3์ด
Pool์ ๋จ์ ์ฐ๊ฒฐ์ด ์์ ๋, ์ ์ฐ๊ฒฐ์ ๋ฐ์ ๋๊น์ง ์ต๋ ๋๊ธฐ ์๊ฐ์
๋๋ค.
์์ฒญ โ Pool์ ๋จ์ ์ฐ๊ฒฐ ์์ด?
โโ ์์ โ ๋ฐ๋ก ์ฌ์ฉ
โโ ์์ โ 3์ด ๊ธฐ๋ค๋ฆผ...
โโ 3์ด ์์ ๋ฐ๋ฉ๋ ์ฐ๊ฒฐ ์๊น โ ์ฌ์ฉ
โโ 3์ด ์ง๋จ โ SQLTransientConnectionException ์๋ฌ!
๊ธฐ๋ณธ๊ฐ์ 30์ด์ธ๋ฐ, failover ์ํฉ์์ 30์ด๋ฅผ ๊ธฐ๋ค๋ฆฌ๋ฉด ์ฌ์ฉ์์๊ฒ 30์ด๊ฐ ๋ก๋ฉ์ด ๊ฑธ๋ฆฝ๋๋ค.
3์ด๋ก ์ค์ด๋ฉด ๋นจ๋ฆฌ ์คํจํ๊ณ ๋นจ๋ฆฌ ์ฌ์๋ํ ์ ์์ต๋๋ค.
2-2. keepalive-time โ "๋๊ณ ์๋ ์ฐ๊ฒฐ, ์ด์์๋์ง ํ์ธํ๊ธฐ"
keepalive-time: 60000 # 1๋ถPool์์ ์ฌ์ฉ๋์ง ์๊ณ ๋๊ณ ์๋(idle) ์ฐ๊ฒฐ์ ์ฃผ๊ธฐ์ ์ผ๋ก ping์ ๋ณด๋ด์ ์ด์์๋์ง ํ์ธํฉ๋๋ค.
Pool: [์ฐ๊ฒฐ1(์ฌ์ฉ์ค), ์ฐ๊ฒฐ2(๋๊ธฐ์ค), ์ฐ๊ฒฐ3(๋๊ธฐ์ค)]
โ โ
1๋ถ๋ง๋ค "์ผ ์ด์์์ด?" ํ
โ โ
"์!" โ ์ ์ "..." โ ์ฃฝ์๋ค
โ ๋ฒ๋ฆฌ๊ณ ์ ์ฐ๊ฒฐ ์์ฑ์ ํ์ํ๊ฐ?
Multi-AZ failover๊ฐ ๋ฐ์ํ๋ฉด:
1. Primary DB๊ฐ ์ฃฝ์
2. AWS๊ฐ Standby๋ฅผ ์ Primary๋ก ์น๊ฒฉ (DNS ๋ณ๊ฒฝ)
3. ํ์ง๋ง Pool์ ์๋ ์ฐ๊ฒฐ๋ค์ ์์ง "์ฃฝ์ Primary"๋ฅผ ๊ฐ๋ฆฌํค๊ณ ์์!
Pool: [์ฐ๊ฒฐ1โ์ฃฝ์DB, ์ฐ๊ฒฐ2โ์ฃฝ์DB, ์ฐ๊ฒฐ3โ์ฃฝ์DB]
4. keepalive๊ฐ ping์ ๋ณด๋ โ "๋ค ์ฃฝ์๋ค!" โ ์ ๋ถ ์ ๊ฑฐ
5. ์ ์ฐ๊ฒฐ ์์ฑ โ DNS๊ฐ ์ Primary๋ฅผ ๊ฐ๋ฆฌํด
Pool: [์ฐ๊ฒฐ4โ์DB, ์ฐ๊ฒฐ5โ์DB, ์ฐ๊ฒฐ6โ์DB]
6. ์๋น์ค ๋ณต๊ตฌ!
์ด ์ค์ ์ด ์์ผ๋ฉด ์ฃฝ์ ์ฐ๊ฒฐ์ max-lifetime(30๋ถ)๊น์ง ๊ณ์ ์ฌ์ฉํ๋ ค๊ณ ์๋ํฉ๋๋ค.
๊ทธ 30๋ถ ๋์ ๋ชจ๋ DB ์์ฒญ์ด ์คํจํฉ๋๋ค. ๐ฅฒ๐ฅฒ
2-3. max-lifetime โ "์ฐ๊ฒฐ์ ์๋ช "
max-lifetime: 1800000 # 30๋ถํ๋์ ์ฐ๊ฒฐ์ ์ต๋ 30๋ถ๋ง ์ฌ์ฉํ๊ณ , ํ๊ธฐ ํ ์๋ก ๋ง๋ญ๋๋ค.
์ฐ๊ฒฐ1 ์์ฑ โโโโโโโโ 30๋ถ ๊ฒฝ๊ณผ โโโโโโโโ ํ๊ธฐ โ ์ ์ฐ๊ฒฐ ์์ฑ
์ ๊ณ์ ์ฐ์ง ์๋ ๊ฑธ๊น?
- ๋คํธ์ํฌ ์ฅ๋น(๋ฐฉํ๋ฒฝ, ๋ก๋๋ฐธ๋ฐ์)๊ฐ ์ค๋๋ ์ฐ๊ฒฐ์ ๋์ ์ ์์
- DB ์ค์ ๋ณ๊ฒฝ ์ ๊ธฐ์กด ์ฐ๊ฒฐ์ ๋ฐ์์ด ์ ๋ ์ ์์
- ๋ฉ๋ชจ๋ฆฌ ๋์ ๊ฐ์ ๋ฏธ๋ฌํ ๋ฌธ์ ๊ฐ ๋์ ๋ ์ ์์
์ฃผ๊ธฐ์ ์ผ๋ก ๊ต์ฒดํด์ ํญ์ ๊ฑด๊ฐํ ์ฐ๊ฒฐ์ ์ ์งํ๋ ๊ฒ์
๋๋ค.
AWS RDS๋ idle connection์ ๊ธฐ๋ณธ ์ฝ 30๋ถ ํ ๋์ต๋๋ค.
max-lifetime์ 30๋ถ์ผ๋ก ๋ง์ถ๋ฉด RDS๊ฐ ๋๊ธฐ ์ ์ ์ฐ๋ฆฌ๊ฐ ๋จผ์ ๊ต์ฒดํฉ๋๋ค.
2-4. validation-timeout โ "์ฐ๊ฒฐ์ด ์ ํจํ์ง ํ์ธํ๋ ์๊ฐ"
validation-timeout: 2000 # 2์ดPool์์ ์ฐ๊ฒฐ์ ๊บผ๋ผ ๋, ์ด ์ฐ๊ฒฐ์ด ์์ง ์ธ ์ ์๋ ์ํ์ธ์ง ํ์ธํฉ๋๋ค.
๊ทธ ํ์ธ์ ์ต๋ 2์ด๋ฅผ ๊ธฐ๋ค๋ฆฝ๋๋ค.
Pool์์ ์ฐ๊ฒฐ ๊บผ๋ โ "์ด ์ฐ๊ฒฐ ์์ง ์ธ ์ ์์ด?" (SELECT 1 ์คํ)
โโ 2์ด ์์ ์๋ต โ ์ฌ์ฉ
โโ 2์ด ์ด๊ณผ โ ์ด ์ฐ๊ฒฐ ๋ฒ๋ฆฌ๊ณ ๋ค๋ฅธ ์ฐ๊ฒฐ ์ฌ์ฉ2-5. minimum-idle / maximum-pool-size โ "Pool ํฌ๊ธฐ"
minimum-idle: 5 # ์ต์ 5๊ฐ๋ ํญ์ ๋๊ธฐ
maximum-pool-size: 20 # ์ต๋ 20๊ฐ๊น์ง ํ์ฅํธ๋ํฝ ์ ์ ๋:
Pool: [์ฐ๊ฒฐ1, ์ฐ๊ฒฐ2, ์ฐ๊ฒฐ3, ์ฐ๊ฒฐ4, ์ฐ๊ฒฐ5]
โโโโโ ์ต์ 5๊ฐ๋ ํญ์ ์ ์ง โโโโโ
ํธ๋ํฝ ๋ง์ ๋:
Pool: [์ฐ๊ฒฐ1, ์ฐ๊ฒฐ2, ... ์ฐ๊ฒฐ15, ... ์ฐ๊ฒฐ20]
โโโโโโโ ํ์์ ๋ฐ๋ผ ์ต๋ 20๊ฐ๊น์ง ์๋ ํ์ฅ โโโโโโโ
20๊ฐ ๋ค ์ฌ์ฉ ์ค์ด๋ฉด:
โ connection-timeout(3์ด) ๋์ ๋๊ธฐ
โ 3์ด ๋ด์ ๋ฐ๋ฉ๋ ์ฐ๊ฒฐ์ด ์์ผ๋ฉด ์๋ฌ
์ ์ Pool ํฌ๊ธฐ ๊ณต์ (์ฐธ๊ณ ):
connections = (CPU ์ฝ์ด ์ * 2) + ์ ํจ ๋์คํฌ ์
์: 2 vCPU ์๋ฒ
โ (2 * 2) + 1 = 5 ~ 10๊ฐ๊ฐ ์ ์
โ 20๊ฐ๋ ์ฌ์ ๋ฅผ ๋ ์ค์ Pool์ด ๋๋ฌด ํฌ๋ฉด DB์ ๋ถ๋ด์ด ๋ฉ๋๋ค. db.t4g.micro๋ ์ต๋ ์ฝ 20๊ฐ ์ฐ๊ฒฐ์ ๊ถ์ฅํฉ๋๋ค.
3. ์ค์ ์์ (YAML)
application-prod.yml (Multi-AZ ํ๊ฒฝ)
spring:
datasource:
master:
jdbc-url: ${SPRING_DATASOURCE_MASTER_JDBC_URL}
username: ${SPRING_DATASOURCE_MASTER_USERNAME}
password: ${SPRING_DATASOURCE_MASTER_PASSWORD}
driver-class-name: org.postgresql.Driver
# HikariCP ์ค์
connection-timeout: 3000 # 3์ด โ ๋น ๋ฅธ ์คํจ/์ฌ์๋
validation-timeout: 2000 # 2์ด โ ์ฐ๊ฒฐ ์ ํจ์ฑ ๊ฒ์ฌ
max-lifetime: 1800000 # 30๋ถ โ RDS idle timeout์ ๋ง์ถค
keepalive-time: 60000 # 1๋ถ โ ์ฃฝ์ ์ฐ๊ฒฐ ๊ฐ์ง
minimum-idle: 5 # ์ต์ ์ ์ง ์ฐ๊ฒฐ ์
maximum-pool-size: 20 # ์ต๋ ์ฐ๊ฒฐ ์
application-dev.yml (๋จ์ผ ์ธ์คํด์ค ํ๊ฒฝ)
spring:
datasource:
master:
jdbc-url: ${SPRING_DATASOURCE_MASTER_JDBC_URL}
username: ${SPRING_DATASOURCE_MASTER_USERNAME}
password: ${SPRING_DATASOURCE_MASTER_PASSWORD}
driver-class-name: org.postgresql.Driver
# HikariCP ์ค์ (Dev๋ ๋ณด์์ ์ผ๋ก)
connection-timeout: 3000
validation-timeout: 2000
max-lifetime: 1800000
minimum-idle: 5
maximum-pool-size: 10 # Dev๋ ๋ ์๊ฒ
Devํ๊ฒฝ์ฒ๋ผ Multi-AZ failover๊ฐ ์๋ ๊ฒฝ์ฐ keepalive-time์ ๋ฃ์ง ์์๋ ๋ฉ๋๋ค.
4. Failover ์ ์ ์ฒด ํ๋ฆ
Multi-AZ failover๊ฐ ๋ฐ์ํ์ ๋, HikariCP ์ค์ ์ด ์ด๋ป๊ฒ ์๋น์ค๋ฅผ ๋ณต๊ตฌํ๋์ง ์ ์ฒด ํ๋ฆ์ ๋๋ค. ๐ค
[์ ์ ์ํ]
Pool: [์ฐ๊ฒฐ1โPrimary, ์ฐ๊ฒฐ2โPrimary, ์ฐ๊ฒฐ3โPrimary]
๋ชจ๋ ์์ฒญ ์ ์ ์ฒ๋ฆฌ ์ค
โ Primary ์ฅ์ ๋ฐ์!
[0์ด] AWS๊ฐ failover ์์
- Primary ์ธ์คํด์ค ๋น์ ์ ๊ฐ์ง
- Standby๋ฅผ ์ Primary๋ก ์น๊ฒฉ ์์
- DNS ๋ณ๊ฒฝ ์งํ ์ค
โ
[0~60์ด] ์์ฒญ ์คํจ ๊ตฌ๊ฐ
- Pool์ ๊ธฐ์กด ์ฐ๊ฒฐ๋ก ์ฟผ๋ฆฌ ์๋ โ ์คํจ
- connection-timeout(3์ด) ํ ๋น ๋ฅด๊ฒ ์๋ฌ ๋ฐํ
- ํด๋ผ์ด์ธํธ๋ ์ฌ์๋ ๊ฐ๋ฅ
โ
[~60์ด] keepalive๊ฐ ๊ฐ์ง
- 1๋ถ ์ฃผ๊ธฐ๋ก idle ์ฐ๊ฒฐ์ ping โ ์๋ต ์์
- ์ฃฝ์ ์ฐ๊ฒฐ ์ ๋ถ Pool์์ ์ ๊ฑฐ
- DNS๊ฐ ์ Primary๋ฅผ ๊ฐ๋ฆฌํด
โ
[60~120์ด] ๋ณต๊ตฌ
- ์ ์์ฒญ์ด ๋ค์ด์ด โ Pool์ ์ฐ๊ฒฐ ์์
- HikariCP๊ฐ ์ ์ฐ๊ฒฐ ์์ฑ ์๋
- DNS๊ฐ ์ Primary๋ฅผ ๊ฐ๋ฆฌํค๋ฏ๋ก โ ์ Primary์ ์ฐ๊ฒฐ ์ฑ๊ณต!
- Pool: [์ฐ๊ฒฐ4โ์Primary, ์ฐ๊ฒฐ5โ์Primary]
โ
[~120์ด] ์๋น์ค ์ ์ํ
- ๋ชจ๋ ์์ฒญ ์ ์ ์ฒ๋ฆฌ
- Pool์ด minimum-idle(5๊ฐ)๊น์ง ์๋ ์ฑ์
5. ์ค์ ๊ฐ ์์ฝ ํ
์ค์ ๊ธฐ๋ณธ๊ฐ ๊ถ์ฅ๊ฐ ์ญํ
| connection-timeout | 30์ด | 3์ด | Pool์์ ์ฐ๊ฒฐ ๋๊ธฐ ์๊ฐ |
| keepalive-time | 0 (๋นํ์ฑ) | 60์ด | ์ ํด ์ฐ๊ฒฐ ์์กด ํ์ธ ์ฃผ๊ธฐ |
| max-lifetime | 30๋ถ | 30๋ถ | ์ฐ๊ฒฐ ์ต๋ ์๋ช |
| validation-timeout | 5์ด | 2์ด | ์ฐ๊ฒฐ ์ ํจ์ฑ ๊ฒ์ฌ ์๊ฐ |
| minimum-idle | pool size์ ๋์ผ | 5 | ์ต์ ์ ์ง ์ฐ๊ฒฐ ์ |
| maximum-pool-size | 10 | 10~20 | ์ต๋ ์ฐ๊ฒฐ ์ |
6. ์ฃผ์์ฌํญ
Pool ํฌ๊ธฐ์ DB ์ฐ๊ฒฐ ํ๊ณ
DB๊ฐ ํ์ฉํ๋ ์ต๋ ์ฐ๊ฒฐ ์ โฅ (์๋น์ค ์ ร maximum-pool-size)
์: db.t4g.micro (์ต๋ ~20 ์ฐ๊ฒฐ)
- Event ์๋น์ค Pool: 10๊ฐ
- Partner ์๋น์ค Pool: 5๊ฐ
- ๊ธฐํ: 5๊ฐ
โ ํฉ๊ณ 20๊ฐ โ ํ๊ณ์ ๊ฐ๊น์
Pool ํฌ๊ธฐ๋ฅผ ๋๋ฆฌ๋ ค๋ฉด DB ์ธ์คํด์ค ์ฌ์๋ ํจ๊ป ์ฌ๋ ค์ผ ํฉ๋๋ค.
HikariCP ์ค์ ์์น (Spring Boot)
@ConfigurationProperties(prefix = "spring.datasource.master")๋ก ๋ฐ์ธ๋ฉํ๋ ๊ฒฝ์ฐ,
HikariCP ์์ฑ์ prefix ๋ฐ๋ก ์๋์ ์์นํฉ๋๋ค:
# ์ฌ๋ฐ๋ฅธ ์์น
spring.datasource.master:
jdbc-url: ...
connection-timeout: 3000 # โ ์ฌ๊ธฐ (prefix ๋ฐ๋ก ์๋)
# ์๋ชป๋ ์์น (๋์ ์ ํจ)
spring.datasource.master:
hikari: # โ ์ด๋ ๊ฒ ํ๋ฉด ์ ๋จ
connection-timeout: 3000
'Infra' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
| ECS AutoScaling ๋งค์ปค๋์ฆ (0) | 2026.01.21 |
|---|---|
| EC2์ธ์คํด์ค ํ์ ์ด๋ป๊ฒ ๊ตฌ๋ถํด์ผ ํ ๊น? (0) | 2026.01.21 |