๐ Spring Boot ์ ํ๋ฆฌ์ผ์ด์ ์ผ๋ก ์ด๋น 100๋ง ๊ฑด์ ์์ฒญ ์ฒ๋ฆฌํ๊ธฐ
์ฌ์ด ๋จ๊ณ๋ณ ๊ฐ์ด๋ โจ
Spring Boot ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฒ์ ์์ํ๋ฉด ๋ชจ๋ ๊ฒ์ด ์ํํ๊ฒ ์๋ํฉ๋๋ค. ํ์ง๋ง ๋๊ท๋ชจ ํธ๋ํฝ์์๋ ๊ธฐ๋ณธ ์ค์ ๋ง์ผ๋ก๋ ์ถฉ๋ถํ์ง ์์ต๋๋ค. ์ด๋น 100๋ง ๊ฑด์ ์์ฒญ(RPS) ์ ์ฒ๋ฆฌํ๋ ๊ฒ์ ์ ๋ฐํ ํ๋, ํจ์จ์ ์ธ ์ฝ๋ฉ, ๊ทธ๋ฆฌ๊ณ ์ ์คํ ์ธํ๋ผ ์ค๊ณ๊ฐ ํ์ํ ๋์ ๋ชฉํ์ ๋๋ค. ๐ช
์ด ๊ฐ์ด๋๋ Spring Boot๋ฅผ ๊ทนํ์ ์์ค์ผ๋ก ํ์ฅํ๋ ๋ฐ ํ์ํ ์ค์ํ ์ต์ ํ๋ฅผ ์๋ดํฉ๋๋ค. ํธ๋ํฝ์ด ๋ง์ ์ ์์๊ฑฐ๋ ์ด๋ฒคํธ, ๊ธ๋ก๋ฒ SaaS ์ํฌ๋ก๋ ๋๋ ๋ฏธ์ ํฌ๋ฆฌํฐ์ปฌ API๋ฅผ ์ค๋นํ๊ณ ์๋ค๋ฉด ์ฌ๊ธฐ์์ ์ค์ฉ์ ์ธ ์ธ์ฌ์ดํธ๋ฅผ ์ฐพ์ ์ ์์ ๊ฒ์ ๋๋ค.
1๏ธโฃ ๊ท๋ชจ ๋ฌธ์ ์ดํดํ๊ธฐ
100๋ง RPS๋ฅผ ์ฒ๋ฆฌํ๋ ๊ฒ์ ๋จ์ํ Spring Boot๋ง์ ๋ฌธ์ ๊ฐ ์๋๋ผ ์ ์ฒด ์์คํ ์ ๋ฌธ์ ์ ๋๋ค. ์ด ์์น์ ๋๋ฌํ๋ ค๋ฉด ๋ค์์ด ํ์ํฉ๋๋ค:
- ํจ์จ์ ์ธ ์ฝ๋ ์คํ ๐ฏ - ์์ฒญ๋น ๋ฎ์ CPU ๋ฐ ๋ฉ๋ชจ๋ฆฌ ์ค๋ฒํค๋
- ์ต์ ํ๋ I/O โก - ๊ฐ๋ฅํ ํ ๋ ผ๋ธ๋กํน ๋ฐฉ์
- ์ํ ํ์ฅ์ฑ ๐ - ์ฌ๋ฌ ๋ ธ๋, ๋ก๋ ๋ฐธ๋ฐ์ฑ
- ํจ์จ์ ์ธ ๋ฐ์ดํฐ ์ฒ๋ฆฌ ๐พ - ์บ์ฑ, ๋น๋๊ธฐ ์์ , ์ต์ํ์ DB ๋ณ๋ชฉ ํ์
Spring Boot๋ฅผ ํผ์ฆ์ ํ ์กฐ๊ฐ์ผ๋ก ์๊ฐํ์ธ์. ๋ฐํ์ ํ๊ฒฝ, JVM ๋ฐ ์ธํ๋ผ๋ ๋๊ฐ์ด ์ค์ํฉ๋๋ค.
2๏ธโฃ ์ฌ๋ฐ๋ฅธ Spring Boot ์ํคํ ์ฒ ์ ํํ๊ธฐ
๊ธฐ๋ณธ์ ์ผ๋ก Spring Boot๋ ๋ด์ฅ๋ Tomcat ์๋ฒ๋ฅผ ์ฌ์ฉํฉ๋๋ค. ์ ๋ขฐํ ์ ์์ง๋ง Tomcat์ ๋ธ๋กํน I/O(BIO) ๊ธฐ๋ฐ์ด๋ฏ๋ก ์ฒ๋ฆฌ๋์ด ์ ํ๋ฉ๋๋ค. ๋๊ท๋ชจ์์๋:
- Netty๋ก ์ ํํ๊ธฐ ๐ - Spring WebFlux๋ฅผ ํตํด Netty๋ฅผ ์ฌ์ฉํ์ธ์. Netty๋ ๋ ผ๋ธ๋กํน I/O๋ฅผ ์ฌ์ฉํ๋ฉฐ ๋ ๋ฎ์ ๋ฉ๋ชจ๋ฆฌ ์ค๋ฒํค๋๋ก ํจ์ฌ ๋ ๋ง์ ๋์ ์ฐ๊ฒฐ์ ์ฒ๋ฆฌํ ์ ์์ต๋๋ค.
- ๋ฆฌ์กํฐ๋ธ ํ๋ก๊ทธ๋๋ฐ ๊ณ ์ํ๊ธฐ โ๏ธ -
Mono,Flux๋ฐ ๋ฐฑํ๋ ์ ๋ฅผ ์ฌ์ฉํ์ฌ ์ค๋ ๋ ๊ณ ๊ฐ์ ๋ฐฉ์งํ์ธ์.
Tomcat์ ์ฌ์ฉํด์ผ ํ๋ค๋ฉด ๋ง์ด ํ๋ํด์ผ ํ์ง๋ง, ์ง์ ํ 100๋ง RPS๋ฅผ ์ํด์๋ WebFlux + Netty๊ฐ ๋ ํ๋ช ํ ๊ฒฝ๋ก์ ๋๋ค.
3๏ธโฃ ์ค๋ ๋ ๊ด๋ฆฌ ์ต์ ํํ๊ธฐ
Spring Boot์ ์ฑ๋ฅ์ ์ค๋ ๋ ๊ตฌ์ฑ๊ณผ ๋ฐ์ ํ๊ฒ ์ฐ๊ฒฐ๋์ด ์์ต๋๋ค:
๐ง Tomcat ํ๋ (Tomcat ์ฌ์ฉ ์):
server.tomcat.max-threads=1000
server.tomcat.accept-count=10000
server.tomcat.connection-timeout=20000
โ๏ธ Netty ํ๋ (WebFlux):
Netty๋ ์ด๋ฒคํธ ๋ฃจํ๋ก ์ค๋ ๋๋ฅผ ๊ด๋ฆฌํ๋ฏ๋ก ๋ ์ ์ ์ค๋ ๋๊ฐ ํ์ํฉ๋๋ค. ๋์ ๋ธ๋กํน ํธ์ถ์ ํผํ๋ ๋ฐ ์ง์คํ์ธ์.
โ ๏ธ ์ปจํธ๋กค๋ฌ ๋ด๋ถ์์ ๋ธ๋กํน ํธ์ถ ํผํ๊ธฐ
๋จ์ผ ๋ธ๋กํน DB ๋๋ HTTP ํธ์ถ์ด ์ด๋ฒคํธ ๋ฃจํ๋ฅผ ๋ง์ ์ ์์ต๋๋ค.
๊ฒฝํ ๋ฒ์น: ๋ ๋ง์ ์ค๋ ๋ โ ๋ ๋ง์ ์ฒ๋ฆฌ๋. ํ์ฅ์ฑ์ ๊ทน๋ํํ๋ ค๋ฉด ๋น๋๊ธฐ ๋ฐ ๋ฆฌ์กํฐ๋ธ ํธ์ถ์ ์ฌ์ฉํ์ธ์. ๐ช
4๏ธโฃ JVM ๋ฐ GC ํ๋
JVM์ Spring Boot์ ์์ง์ ๋๋ค. ๊ธฐ๋ณธ๊ฐ์ ์์ ํ์ง๋ง ๋์ RPS์ ์ต์ ํ๋์ด ์์ง ์์ต๋๋ค.
๐ฏ ์ฃผ์ JVM ์ต์ ํ:
-
์ต์ JDK ์ฌ์ฉ(17 ์ด์) โ - ๊ฐ ๋ฆด๋ฆฌ์ค๋ ์ฑ๋ฅ๊ณผ ๋ฉ๋ชจ๋ฆฌ ํจ์จ์ฑ์ ํฅ์์ํต๋๋ค.
-
์ฌ๋ฐ๋ฅธ ๊ฐ๋น์ง ์ปฌ๋ ํฐ(GC) ์ ํ:
- G1GC - ๊ท ํ ์กํ ์ํฌ๋ก๋์ฉ
- ZGC ๋๋ Shenandoah - ์ด์ ์ง์ฐ์ฉ
-
๋ฉ๋ชจ๋ฆฌ ํ ๋น ๐ป - ํ ํฌ๊ธฐ๋ฅผ ๋ช ์์ ์ผ๋ก ์ค์ :
-Xms4g -Xmx4g -XX:+UseG1GC- ์ปจํ ์ด๋ ์ ํ์ ๋ฐ๋ผ ์กฐ์
-
์ปจํ ์ด๋ ์ธ์ ํ์ฑํ:
-XX:+UseContainerSupport
์ ํ๋๋ GC๋ 100๋ง RPS์์๋ ์ง์ฐ ์๊ฐ์ ์์ธก ๊ฐ๋ฅํ๊ฒ ์ ์งํฉ๋๋ค. โฑ๏ธ
5๏ธโฃ ์ ๊ทน์ ์ผ๋ก ์บ์ฑ ํ์ฉํ๊ธฐ
๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ธ๋ถ ์๋น์ค๋ ๊ฐ์ฅ ํฐ ๋ณ๋ชฉ ํ์์ ๋๋ค. ๊ทน๋จ์ ์ธ ๊ท๋ชจ์์๋ ๋ชจ๋ ์์ฒญ๋ง๋ค ์ด๋ค์ ํธ์ถํ ์ฌ์ ๊ฐ ์์ต๋๋ค. ๐ซ
๐ฆ ์บ์ฑ ์ ๋ต:
- ์ธ๋ฉ๋ชจ๋ฆฌ ์บ์ฑ(Caffeine) - ๋ก์ปฌ, ๊ทผ๊ฑฐ๋ฆฌ ์บ์ ์ฑ๋ฅ
- ๋ถ์ฐ ์บ์ฑ(Redis, Hazelcast, Memcached) - ๋ค์ค ๋ ธ๋ ํ๊ฒฝ์ฉ
- HTTP ์๋ต ์บ์ฑ - ๊ฐ๋ฅํ ๊ฒฝ์ฐ ์ ์ ์๋ต ์บ์
- ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฟผ๋ฆฌ ์บ์ฑ - Hibernate์ 2์ฐจ ์บ์ ๋๋ ์ฌ์ฉ์ ์ง์ ์บ์ฑ ์ ๋ต ์ฌ์ฉ
ํฉ๊ธ ๋ฒ์น: ๋ชจ๋ ์์ฒญ๋ง๋ค ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ์ ๋ ํธ์ถํ์ง ๋ง์ธ์! ๐ ์ ์ ํ ์บ์ฑ์ ์ฌ์ฉํ๋ฉด DB๊ฐ ๋ณ๋ชฉ ํ์์ด ์๋ ๋ฐฑ์ ์ด ๋ฉ๋๋ค.
6๏ธโฃ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ํธ์์ฉ ์ต์ ํํ๊ธฐ
Spring Boot ์ฑ์ด ๊ด๊ณํ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์์กดํ๋ ๊ฒฝ์ฐ:
๐ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ต์ ํ:
-
์ปค๋ฅ์ ํ๋ง ์ฌ์ฉ(HikariCP๋ Spring Boot์ ๊ธฐ๋ณธ๊ฐ)
-
HikariCP๋ฅผ ๋์ ์ฒ๋ฆฌ๋์ผ๋ก ํ๋:
spring.datasource.hikari.maximum-pool-size=200spring.datasource.hikari.minimum-idle=50spring.datasource.hikari.idle-timeout=30000spring.datasource.hikari.max-lifetime=600000 -
๋จ์ผ ์ฟผ๋ฆฌ๋ณด๋ค ๋ฐฐ์น ์ฝ์ /์ ๋ฐ์ดํธ ์ ํธ ๐
-
๋ถ์ ์ฟผ๋ฆฌ๋ฅผ ๋ณต์ ๋ณธ์ผ๋ก ์คํ๋ก๋ ๐
-
์ด๊ณ ์ ์ฐ๊ธฐ/์ฝ๊ธฐ ์ํฌ๋ก๋๋ฅผ ์ํด NoSQL(Cassandra, DynamoDB, MongoDB) ๊ณ ๋ ค โก
100๋ง RPS์์ DB๋ ๋จ์ํ ๋ฐ์ดํฐ๋ฒ ์ด์ค๊ฐ ์๋๋ผ ๋ถ์ฐ ์์คํ ์ ๋๋ค. ์ด์ ๋ง๊ฒ ์ค๊ณํ์ธ์. ๐
7๏ธโฃ ์ง๋ ฌํ ์ค๋ฒํค๋ ์ต์ํํ๊ธฐ
์ง๋ ฌํ ๋ฐ ์ญ์ง๋ ฌํ๋ ๋๊ท๋ชจ์์ ์กฐ์ฉํ ํฌ๋ฌ์ ๋๋ค. JSON์ ์ฌ๋์๊ฒ ์น์ํ์ง๋ง CPU ์ง์ฝ์ ์ ๋๋ค. ๐ฐ
๐จ ์ต์ ํ:
- Jackson Afterburner ์ฌ์ฉ์ผ๋ก JSON ์ง๋ ฌํ ์๋ ํฅ์ ๐
- ํด๋ผ์ด์ธํธ์ ์๋ฒ ๋ชจ๋ ์ง์ํ๋ ๊ฒฝ์ฐ ๋ฐ์ด๋๋ฆฌ ํ์(Protobuf, Avro, Smile) ์ ํธ
- ๋คํธ์ํฌ๊ฐ ๋ณ๋ชฉ ํ์์ธ ๊ฒฝ์ฐ์๋ง ์๋ต ์์ถ. ๊ทธ๋ ์ง ์์ผ๋ฉด ์์ถ์ด CPU๋ฅผ ์๋ชจํฉ๋๋ค.
์์ ์ง๋ ฌํ ๋ณ๊ฒฝ์ผ๋ก ์ฒ๋ฆฌ๋์ ๋ ๋ฐฐ๋ก ๋๋ฆด ์ ์์ต๋๋ค! ๐ฏ
8๏ธโฃ ์ํ ํ์ฅ์ผ๋ก ๋ฐฐํฌํ๊ธฐ
๋จ์ผ Spring Boot ์ธ์คํด์ค๋ก๋ 100๋ง RPS๋ฅผ ์ฒ๋ฆฌํ ์ ์์ต๋๋ค. ์ํ์ผ๋ก ํ์ฅํ์ธ์:
โธ๏ธ ํ์ฅ ์ ๋ต:
- Kubernetes + HPA(Horizontal Pod Autoscaler) - CPU/๋ฉ๋ชจ๋ฆฌ ๋๋ ์ฌ์ฉ์ ์ง์ ๋ฉํธ๋ฆญ(RPS, ์ง์ฐ ์๊ฐ)์ ๊ธฐ๋ฐ์ผ๋ก ํ์ฅ
- ์๋น์ค ๋ฉ์(Istio/Linkerd) - ํธ๋ํฝ, ์ฌ์๋ ๋ฐ ์ํท ๋ธ๋ ์ดํน ๊ด๋ฆฌ
- ๋ฌด์ํ ์ค๊ณ ๐ญ - ์ธ์ ๋ฐ์ดํฐ๋ฅผ Redis ๋๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋ณด๊ดํ๊ณ ๋ฉ๋ชจ๋ฆฌ์๋ ์ ๋ ๋ณด๊ดํ์ง ๋ง์ธ์.
์๋ฒ๊ฐ ์๋ ํด๋ฌ์คํฐ ๊ด์ ์ผ๋ก ์๊ฐํ์ธ์. ๐
9๏ธโฃ ๋น๋๊ธฐ ๋ฉ์์ง ๋ฐ ์ด๋ฒคํธ ๊ธฐ๋ฐ ์ํคํ ์ฒ ํ์ฉํ๊ธฐ
๊ทนํ์ ๋ถํ์์๋ ๋๊ธฐ ์์ฒญ-์๋ต ์์คํ ์ด ์ด๋ ค์์ ๊ฒช์ต๋๋ค. ๋น๋๊ธฐ ํ์ดํ๋ผ์ธ์ ๋์ ํ์ธ์:
๐ฎ ๋น๋๊ธฐ ์ ๋ต:
- Kafka, RabbitMQ, Pulsar๋ฅผ ์ฌ์ฉํ์ฌ ๋ถ๋ฆฌ๋ ์ด๋ฒคํธ ์ฒ๋ฆฌ ๐ช
- ๋ฌด๊ฑฐ์ด ์์ (์ด๋ฏธ์ง ์ฒ๋ฆฌ, ๋ถ์, ์๋ฆผ)์ ๋น๋๊ธฐ ํ๋ก ์คํ๋ก๋
- ์์ ์ด ๋ฐฑ๊ทธ๋ผ์ด๋์์ ๊ณ์๋๋ ๋์ ํด๋ผ์ด์ธํธ์ ์ฆ๊ฐ์ ์ธ ์๋ต ๋ฐํ โก
์ด ํจํด์ ์ฑ์ ๊ณผ๋ถํ์ํค์ง ์์ผ๋ฉด์ ๋์ ์์ฒญ ์ฒ๋ฆฌ๋์ ์ ์งํ๋ ๋ฐ ๋์์ด ๋ฉ๋๋ค.
๐ ํ๋กํ์ผ๋ง, ๋ฒค์น๋งํน ๋ฐ ๋ชจ๋ํฐ๋ง
๋งน๋ชฉ์ ์ผ๋ก ์ต์ ํํ ์๋ ์์ต๋๋ค. ์ค์ ๋ฉํธ๋ฆญ์ ์ฌ์ฉํ์ธ์:
๐ ๋๊ตฌ ๋ฐ ๋ฉํธ๋ฆญ:
๋ถํ ํ ์คํธ ๋๊ตฌ: Gatling, JMeter, Locust ํ๋กํ์ผ๋ฌ: YourKit, JFR(Java Flight Recorder), async-profiler ๋ชจ๋ํฐ๋ง: Micrometer + Prometheus + Grafana
๐ฏ ์ฃผ์ํ ์ฃผ์ ๋ฉํธ๋ฆญ:
- ์๋ต ์๊ฐ(p95, p99 ์ง์ฐ ์๊ฐ) โฑ๏ธ
- GC ์ผ์ ์ค์ง ๐๏ธ
- CPU ์ฌ์ฉ๋ฅ ๐ป
- DB ์ฟผ๋ฆฌ ์๊ฐ ๐
๋ชจ๋ํฐ๋ง ์์ด๋ 100๋ง RPS์ ์ ๋ง๋ก ์ค๋น๋์๋์ง ์ ์ ์์ต๋๋ค.
1๏ธโฃ1๏ธโฃ ๋๊ท๋ชจ ๋ฐฐํฌ์ ์ค์ ํ
๐ก ๊ณ ๊ธ ํ:
- JVM ๋ฐ ์บ์ ์๋ฐ์ ๐ฅ - ๋ผ์ด๋ธ ํธ๋ํฝ์ ์ฒ๋ฆฌํ๊ธฐ ์ ์ ์๋ฐ์ ํ์ธ์. ์ฝ๋ ์คํํธ๋ ์ฑ๋ฅ์ ์ ํ์ํต๋๋ค.
- ๋น๋ํ ์๋ต ํผํ๊ธฐ ๐ฏ - ํ์ด๋ก๋๋ฅผ ๊ฐ๋ณ๊ฒ ์ ์งํ์ธ์(์์ธํ ๊ฐ์ฒด๋ณด๋ค ID ์ ํธ).
- CPU ์ง์ฝ์ ์์ ๊ณ ์ โ๏ธ - ๋น๋๊ธฐ ์์ปค์ ๊ณ ์ ํ์ธ์. HTTP ์ค๋ ๋๋ฅผ ์ฐจ๋จํ์ง ๋ง์ธ์.
- ์นด์ค์ค ํ ์คํธ ๐ช๏ธ - ๋ ธ๋ ์ฅ์ , GC ์ผ์ ์ค์ง ๋ฐ DB ์๋ ์ ํ๋ฅผ ์๋ฎฌ๋ ์ด์ ํ์ธ์.
๐ ๊ฒฐ๋ก
Spring Boot๋ฅผ ์ด๋น 100๋ง ๊ฑด์ ์์ฒญ์ผ๋ก ํ์ฅํ๋ ๊ฒ์ ๋ง๋ฒ์ด ์๋๋๋ค. ๊ทธ๊ฒ์ ํ๋ จ, ์ธก์ ๋ฐ ์์ง๋์ด๋ง ์๊ฒฉํจ์ ๋๋ค. ์ฌ๋ฐ๋ฅธ ํ๋๊ณผ ์ํคํ ์ฒ๋ก Spring Boot๋ ์ธํฐ๋ท ๊ท๋ชจ์ ์ํฌ๋ก๋์์ ์ฑ๋ฅ์ ๋ฐํํ ์ ์์ต๋๋ค! ๐โจ
์ฝ์ด์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค! ๐
๐ ์ถ์ฒ
์๋ฌธ: Enable Spring Boot application to handle 1 million requests per second
์ ์: Riya Sharma
๊ฒ์์ฒ: AWS in Plain English
๊ฒ์์ผ: 2025๋ 9์ 23์ผ



