๐ Spring ๋ถ์ฐ ํ๊ฒฝ์์ ์ธ์ ๊ด๋ฆฌํ๊ธฐ(์ธ์ ํด๋ฌ์คํฐ๋ง)
์๋ ํ์ธ์, ์ด๋ฒ ํฌ์คํ ์์๋ ์ฌ๋ฌ ์๋ฒ ํ๊ฒฝ์์ ์ธ์ ์ ๊ด๋ฆฌํ๋ ๋ฐฉ๋ฒ์ ๋ํด ์ดํด๋ณด๊ฒ ์ต๋๋ค.
(์ฝ๋๋ ๊นํ๋ธ์์ ํ์ธํ์ค ์ ์์ต๋๋ค.)
๋จ์ผ ์๋ฒ์์ ์ธ์ ์ ๊ด๋ฆฌํ๋ค๋ฉด ์๋ฌด๋ฐ ๋ฌธ์ ๊ฐ ์๊ฒ ์ง๋ง, ๋ณดํต ์ค์ผ์ผ ์์ ๋ฑ์ ํตํด ๋ถ์ฐ๋ ์๋ฒ ํ๊ฒฝ์์ ์ธ์ ์ ๊ด๋ฆฌํ ๋(๋ก๊ทธ์ธ ์ ์ ์ ์ธ์ ์ ๋ณด) ์ธ์ ๋ถ์ผ์น ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค.
์์๋ก ์ดํด๋ณผ๊น์?
์ฌ์ฉ์ A๊ฐ localhost:8080ํฌํธ๋ก login ํธ์ถ ์ ์ธ์ ์ด ์์ฑ๋๊ณ JSESSIONID์ ์์์ ๊ฐ์ ์ค์ ํฉ๋๋ค.
JSESSIONID?
- ์ธ์ ์ ์ ์งํ๊ธฐ ์ํด Tomcat Container์์ ๋ฐ๊ธํ๋ Key์ด๊ณ Value๋ฅผ ํตํด ์ธ์ ์ ์ ์งํ ์ ์์ต๋๋ค.
๋์ ๋ฐฉ์?
1. ๋ธ๋ผ์ฐ์ ์ต์ด ์ ๊ทผ ์ Tomcat Response์ JSESSIONID ๊ฐ์ ๋ฐ๊ธํฉ๋๋ค(Set-Cookie)
2. ๋ธ๋ผ์ฐ์ ์ฌ์์ฒญ ์ ์ด์ ์ ๋ฐ๊ธ๋ฐ์ JSESSIONID๋ฅผ Request Headers์ ์ฟ ํค์ ๊ฐ์ ๋ฃ์ด ์๋ฒ์ ์์ฒญํฉ๋๋ค.
3. ํด๋ผ์ด์ธํธ๋ก๋ถํฐ ์ ๋ฌ๋ฐ์ JSESSIONID์ ๊ฐ์ ๊ธฐ์ค์ผ๋ก ์๋ฒ์์๋ ์ธ์ ์ ์ํ๋ฅผ ์ ์งํ ๊ฐ๋ค์ ์ ์ฅํ ์ ์์ต๋๋ค.
JSESSIONID๋ ํฌํธ๋ฒํธ๋ ๋ฌ๋ผ๋ ๋์ผํ ๊ฐ์ ์ ์งํฉ๋๋ค.
๋์ผํ๊ฒ localhost:8080 URL๋ก myName์ ํธ์ถํ๋ฉด ์ด์ ์ ๋ฐ๊ธ๋ฐ์ JSESSIONID๋ฅผ Header์ ์ค์ ํ์ฌ ์์ฒญ์ ๋ณด๋ด๊ณ , ์ ์ฅ๋ ์ธ์ ๋ฐ์ดํฐ๋ฅผ ์ ์์ ์ผ๋ก ๋ฐํํฉ๋๋ค.
๋ง์ฝ ๋ค๋ฅธ ์ปจํ ์ด๋์ธ localhost:8081 URL์ ํธ์ถํ๋ฉด ๋ค๋ฅธ ์๋ฒ๋ฅผ ํธ์ถํ๊ธฐ ๋๋ฌธ์ ๋์ผํ JSESSIONID ๊ฐ์ผ๋ก ์์ฒญ์ด ์ค์ง๋ง ์ธ์ ์ ๋ฐ์ดํฐ๊ฐ ์กด์ฌํ์ง ์๊ธฐ์ ์๋ฌด๋ฐ ๋ฐ์ดํฐ๋ ๋ฐํํ์ง ์์ต๋๋ค.
๋ํ Response Headers์ ์ฟ ํค์ ์๋ก์ด JSESSIONID์ ๊ฐ์ ๋ฐํํ๊ณ , ์ดํ ์์ฒญ์ ํด๋น ๊ฐ์ ํตํด ์์ฒญํฉ๋๋ค.
์์์ ๋ฐ๊ธ๋ฐ์ JSESSIONID ๊ฐ์ผ๋ก ์์ฒญ์ ๋ณด๋ด๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค.
๋ค๋ฅธ ์๋ฒ์ธ localhost:8080์ myName API๋ฅผ ํธ์ถํ๋ฉด ๋ง์ฐฌ๊ฐ์ง๋ก ์ธ์ ๋ฐ์ดํฐ๊ฐ ์กด์ฌํ์ง ์๊ธฐ ๋๋ฌธ์ ์๋ก์ด JSESSIONID ๊ฐ์ ๋ฐํํ๊ณ , ์ดํ ์์ฒญ์ ํด๋น ๊ฐ์ Header์ ๋ฃ์ด์ ์์ฒญํ๊ฒ ๋ฉ๋๋ค.
์ด์ฒ๋ผ Scale-out ๋ฑ์ ํตํด ๋ถ์ฐ๋ ํ๊ฒฝ์์ ์ธ์ ์ ์ฌ์ฉํ ๊ฒฝ์ฐ ๋์ผํ๊ฒ ์ธ์ ์ ์ ์งํ ์ ์์ต๋๋ค.
์ด๋ฌํ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด Session Clustering, Sticky Session, Redis Session Clustering ๋ฑ์ด ์กด์ฌํฉ๋๋ค.
๊ทธ์ค ์ฌ๊ธฐ์๋ Redis Session Clustering ๋ฐฉ์์ผ๋ก ์ฝ๋๋ฅผ ์์ฑํด ๋ณด๊ณ , ๋ค๋ฅธ ๋ฐฉ์์ ๋นํด ์ด๋ ํ ์ด์ ์ด ์๋์ง ์ดํด๋ณด๊ฒ ์ต๋๋ค.
๐ Sticky Session
Sticky session์ ์ธ์ ์ ์ฌ์ฉํด ํธ๋ํฝ์ ๋ถ์ฐํ๋ ๊ธฐ๋ฅ์ผ๋ก ํน์ ์ธ์ ์ ์์ฒญ์ ์ต์ด ์ฒ๋ฆฌํ ์๋ฒ๋ก๋ง ์ ์กํ๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค.
์๋ฅผ ๋ค์ด ํ์ 1์ด ์๋ฒ A์์ ์ธ์ ์ ์์ฑํ๋ค๋ฉด, ์ดํ ํ์ 1์ด ๋ณด๋ด๋ ๋ชจ๋ ์์ฒญ์ ์๋ฒ A๋ก๋ง ์ ์กํ๊ฒ ๋ฉ๋๋ค.
์ด๋ฌํ Sticky session์ ์๋์ ๊ฐ์ ๋จ์ ์ด ์กด์ฌํฉ๋๋ค.
- ๋์ผํ ์ธ์ ์ ๋์ผํ ์๋ฒ๋ก๋ง ์ ์กํ๊ธฐ ๋๋ฌธ์ ํน์ ์๋ฒ์ ์์ฒญ์ด ๋ชฐ๋ ค ๊ณผ๋ถํ๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค.
- ํน์ ์๋ฒ์ ์ฅ์ ๊ฐ ๋ฐ์ํ ์ ํด๋น ์๋ฒ์ ์ฐ๊ฒฐ๋์ด ์๋ ์ธ์ ๋ค์ด ๋ชจ๋ ์์ค๋ ์ ์์ต๋๋ค.
์์ ๊ฐ์ ๋จ์ ์ ํด๊ฒฐํ๊ธฐ ์ํด Session Clustering ๋ฐฉ์์ด ์กด์ฌํฉ๋๋ค.
๐ Session Clustering (์ธ์ ํด๋ฌ์คํฐ๋ง)
Session Clustering์ ๊ฐ๋ ์ ๋จ์ํฉ๋๋ค. ํด๋ฌ์คํฐ๋ง ์ด๋ ๊ฐ๋ ์ด ๊ตฐ์ง, ๋ญ์น๊ธฐ ๋ฑ๊ณผ ๊ฐ์ ์๋ฏธ๋ฅผ ์ง๋๊ณ ์๋๋ฐ์, ์ธ์ ํด๋ฌ์คํฐ๋ง์ ์ฌ๋ฌ WAS๊ฐ ์ธ์ ์ ๊ณต์ ํ์ฌ ๋์ผํ๊ฒ ์ธ์ ์ ๊ด๋ฆฌํ๋ ๋ฐฉ์์ ์๋ฏธํฉ๋๋ค.
์ธ์ ํด๋ฌ์คํฐ๋ง ๋ฐฉ์์ Sticky Session์์ ๋ฐ์ํ๋ 1. ํน์ ์๋ฒ์๋ง ํธ๋ํฝ์ด ๋ง์ด ๋ฐ์ํ๊ฑฐ๋, 2. ์ฅ์ ๋ฐ์ ์ ์ธ์ ์์ค์ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์์ต๋๋ค.
ํ์ง๋ง ์ธ์ ํด๋ฌ์คํฐ๋ง์ ์ธ์ ๋ฐ์ดํฐ๊ฐ ์์ฑ๋ ๋๋ง๋ค ๋ชจ๋ ์๋ฒ์ ์ธ์ ์ ๋ณด๋ฅผ ์ถ๊ฐํด์ผ ํ๊ธฐ ๋๋ฌธ์ ์๋ฒ์ ๋ฉ๋ชจ๋ฆฌ์ ์๋นํ ๋ถ๋ด์ด ๋๋ค๋ ์น๋ช ์ ์ธ ๋จ์ ์ด ์กด์ฌํฉ๋๋ค.
๐ Redis Session Clustering
Redis๋ฅผ ์ด์ฉํ ์ธ์ ํด๋ฌ์คํฐ๋ง ๋ฐฉ์์ ์ธ์ ์ ๊ด๋ฆฌํ ์ ์ฅ์๋ฅผ Redis๋ก ๋ฐ๋ก ๋์ด ์ฌ์ฉํ๋ ๋ฐฉ์์ ๋๋ค.
๊ทธ๋ ๋ค๋ฉด ์ธ์ ์ ๊ด๋ฆฌํ ์ ์ฅ์๋ฅผ RDB๊ฐ ์๋ Redis๋ฅผ ์ฌ์ฉํ๋ฉด ์ด๋ค ์ด์ ์ด ์์๊น์?
๋๋ต์ ์ผ๋ก ์๋์ ๊ฐ์ ์ด์ ์ด ์กด์ฌํ ๊ฒ ๊ฐ์ต๋๋ค.
- ์ธ์ ์ ๋ฐ์ดํฐ ๋ชจ๋ธ์ด ๊ด๊ณํ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ฒ๋ผ ๋ณต์กํ์ง ์์ต๋๋ค.
- ์ธ์ ์ ๋ณดํต ๋ง๋ฃ์๊ฐ์ด ์กด์ฌํ๊ธฐ์ ์์์ฑ์ด ํ์ํ์ง ์์ต๋๋ค.
- ์ธ์ ์ ์ฌ์ฉ์๊ฐ ๋ก๊ทธ์ธ ํ ์์ฒญ์ ํ ๋๋ง๋ค ํ์ธ์ด ํ์ํ๊ธฐ ๋๋ฌธ์ ๊ทธ๋งํผ I/O๊ฐ ๋ง์ด ๋ฐ์ํ๊ณ , RDB๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ์๋ ๋์คํฌ I/O๋ก ์ธํด ์ฑ๋ฅ ์ด์๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค.
๋ฐ๋ผ์ Redis๋ ์ธ์ ์ ์ฅ์์ ์ ํฉํ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ผ๊ณ ํ ์ ์์ต๋๋ค.
Spring Redis Session Clustering ์์ ์ฝ๋
Spring์์ Redis๋ฅผ ์ธ์ ์ ์ฅ์๋ก ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ๊ต์ฅํ ๊ฐ๋จํฉ๋๋ค.
(redis ์ค์น&์ค์ ๊ด๋ จ์ ์๋ตํ๊ฒ ์ต๋๋ค.)
- redis ๊ด๋ จ ์์กด์ฑ์ ์ถ๊ฐํ๊ณ
- application. yml(properties) ํ์ผ์ ์ค์ ์ ์ถ๊ฐํ๊ณ
- API ์์ฒญ ์ HttpSession ์ธํฐํ์ด์ค๋ฅผ ๋งค๊ฐ๋ณ์๋ก ์ถ๊ฐํ์ฌ ์ฌ์ฉํ๋ฉด ๋ฉ๋๋ค.
์ ์ด๋ฏธ์ง๋ฅผ ํ์ธํด ๋ณด๋ฉด localhost:8080 URL๋ก login ์์ฒญ์ ํ์ง๋ง, 8080ํฌํธ์ 8081ํฌํธ ๋ชจ๋ SESSION์ด๋ผ๋ Key๋ฅผ ํตํด ๋์ผํ ๋ฐ์ดํฐ๊ฐ ๋ฐํ๋๋ ๊ฒ์ ๋ณผ ์ ์์ต๋๋ค.
Redis ํ์ธ
- spring:session:expirations:(expire time) = expire time์ ์ญ์ ๋ ์ธ์ ์ ๋ณด๋ค์ ๋ด๊ณ ์์ต๋๋ค. (Set)
- spring:session:sessions:expire:(session id) = ํด๋น ์ธ์ ์ ๋ง๋ฃ Key๋ก ์ฌ์ฉ๋ฉ๋๋ค. (String)
- spring:session:sessions:(session id) = ์ธ์ ์ ์์ฑ ์๊ฐ, ๋ง์ง๋ง ์ธ์ ์กฐํ ์๊ฐ, ์ต๋ ํ์์์ ํ์ฉ์๊ฐ, ์ธ์ ์ ์ ์ฅํ ๋ฐ์ดํฐ๋ฅผ ๋ด๊ณ ์์ต๋๋ค. (Hash)
Hash ํ์ ์ธ spring:session:sessions:(session id)์ ํ์ธํด ๋ณด๋ฉด ์ธ์ ๋ฐ์ดํฐ๊ฐ ์ ์ฅ๋์ด ์๋ ๊ฒ์ ๋ณผ ์ ์์ต๋๋ค.
spring.session.store-type์ ํตํด Session ์ค์ ์ Redis๋ก ์ง์ ํฉ๋๋ค.
Spring Boot์ AutoConfiguration๋ก ์ธํด properties(yml) ํ์ผ์ ์์ ๊ฐ์ด ์ค์ ๋ง ํ๋๊ฒ์ผ๋ก Spring Session์ Redis๋ก ์ค์ ํ๋ ๊ฒ์ด ์์ฝ๊ฒ ๊ฐ๋ฅํฉ๋๋ค.
SessionProperties ํด๋์ค์ StoreType์ ๋ณด๋ฉด Redis ์ธ์๋ MongoDB, JDBC, HAZELCAST(?) ๋ฑ์ ์ค์ ํ ์ ์์ต๋๋ค.
์ดํ Session ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ ๋ ๊ธฐ์กด๊ณผ๋ ๋ฌ๋ฆฌ RedisIndexedSessionRepository ํด๋์ค๋ฅผ ํตํด set์ ์งํํ์ฌ ์ธ์ ๊ณผ ๊ด๋ จ๋ ๋ฐ์ดํฐ๋ฅผ spring:session์ ๊ธฐ๋ณธ ๋ค์์คํ์ด์ค๋ก ๊ฐ key๋ฅผ ์ค์ ํ์ฌ ๊ด๋ฆฌํฉ๋๋ค.
๐ ์ฐธ๊ณ ๋ฌธ์
- https://redis.io/
- https://docs.spring.io/spring-session/docs/1.3.1.BUILD-SNAPSHOT/api/org/springframework/session/data/redis/RedisOperationsSessionRepository.html
- https://docs.spring.io/spring-session/reference/guides/boot-redis.html
๋๊ธ