๋ฐฐ๊ฒฝ
๊ฐ์ ๋ฉด์ ์ฌ๋ก๋ก ๋ฐฐ์ฐ๋ ๋๊ท๋ชจ ์์คํ ์ค๊ณ ๊ธฐ์ด ์ฑ ์ ์๋ ๋ถํฐ ๊ตฌ๋งค๋ฅผ ํ์๋๋ฐ ํญ์ ์ธ์ ๊ฐ๋ ์ฝ์ด์ผ์ง ํ๊ณ ์๊ฐ๋ง ํ์์ง ๋ณธ๊ฒฉ์ ์ผ๋ก ์ฝ์ง ์์์๋ค.
์ด์ ๋ AI์ ๋ฐ์ ์ผ๋ก ์ฝ๋ฉ์ AI๊ฐ ๋ ์ํ๋ค๋ ์ฌ์ค์ ๋ถ์ ํ ์ ์๋ค. ํ์ง๋ง ์ด ์ํคํ ์ณ ๋ถ๋ถ ํนํ ๋ณต์กํ ์๊ตฌ์ฌํญ์ ์ด๋ค์์ผ๋ก ๊ตฌํ์ ํ๋๊ฒ ์ข์์ง์ ๋ํ ํ๋จํ๋ ๋ฅ๋ ฅ์ ์์ผ๋ก ๋์ฑ ์ค์ํด์ง๊ฒ ๊ฐ๋ค๋ ์๊ฐ์ด ๋ค์๋ค.
The Next Two Years - Addy Osmani ์ต๊ทผ์ ์ด ๊ธ์ ์ฝ๊ณ ๊ณต๊ฐ์ ๋ง์ด ํ๊ฒ๋์๊ณ ๊ทธ๋์ ์ด ์ฑ ์ ๋นจ๋ฆฌ ์ฝ์ผ๋ฉด์ ์ง์ ๊ตฌํ๋ ํด๋ณด๋ ๊ณผ์ ์ ์ง๊ธ ์๋๋ฉด ์ธ์ ํ ๊น๋ ์๊ฐ์ ์ฝ๊ธฐ ์์ํ๋ค.
YouTube ์ฑ๋ ์ฌ๊ธฐ์ ๊ณต๋ถ ๊ธฐ๋ก์ ๋ผ์ด๋ธ ๋ฐฉ์ก์ผ๋ก ๋งค์ผ ์งํ์ ํ๊ณ ์๋ค ใ ใ
๊ณํ
์ด ์ฑ ์๋ ๋ค์ํ ๋๊ท๋ชจ ์ค๊ณ์ ๋ํ ์ฌ๋ก๋ค์ด ์ค๋ ค ์๋ค. ํด๋น ์ฃผ์ ๋ค์ ์ค์ ์ฝ๋์ ํ๊ฒฝ์ ๊ตฌ์ถํด๋ณด๋ฉด์ ์ ์ ๊ฐ์ ์ ํด๋๊ฐ๋ ๊ฒ์ด ๋ชฉํ์ด๊ณ ์ด๋ฐ ๊ณผ์ ์์ ๋ฐฐ์ฐ๊ณ ์ ํ๋๊ฒ์ ๋ค์ํ ๋๋ฉ์ธ์์ ์ด๋ค ์์ผ๋ก ์ค๊ณ๋ฅผ ํ๋ฉด ๋๋์ง๋ฅผ ์ตํ๊ณ ์ด๋ฅผ AI๋ฅผ ํตํด์ ๊ตฌํ์ ํด๋ณด๋ ๊ณผ์ ์ ๊ฒฝํ์ ํ๊ณ ์ ํ๋ค.
๋จ ์ฌ๊ธฐ์ AI๋ฅผ ํตํด์ ๊ตฌํ์ ํ์ง๋ง ๋ชจ๋ ๊ตฌํ ๊ณผ์ ์ ๋ด๊ฐ ์ดํดํ๊ณ ๋์ด๊ฐ๋ ค๊ณ ํ๋ค. ๋ธ๊น์ผ๋ก ํ๋ ค๋ฉด ํ ์ ์๊ฒ ์ง๋ง ์ง๊ธ ์ ๋๋ก ๋ฐฐ์๋์ง ์์ผ๋ฉด ๋์ค์ ์ค๊ณ๋ฅผ ํ ๋ ์ด๊ฒ ์ง๊ธ ์ํฉ์ ์ ํฉํ ์ ํ์ธ์ง์ ์ ์ด๋ฐ ์์ผ๋ก ๊ตฌํ์ ํ๋์ง์ ๋ํด ์ค๋ช ์ ํ ์ ์์ ๊ฒ ๊ฐ์์ ์ด๋ค. ์ ์ ๋งํฌ์์๋ ๊ตฌ๊ธ ํฌ๋กฌ ํ ๋ฆฌ๋ ๋ถ ๊ธ์ฒ๋ผ AI๋ฅผ ํ์ฉํ๋ ๋์์ ๋์ ๊ณต๋ถ ๋ฉํ ๋ก์จ๋ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ์ฌ์ฉํ๋ ค๊ณ ํ๋ค.
์ฐ์ ์์๋ ์ด๋ฐ์์ผ๋ก ์งํ ํ ๊ฒ ๊ฐ๋ค.
- ์ฑํฐ ํ๋๋ฅผ ํ๋ฒ ํ์ด๋ณด๊ณ
- AI์๊ฒ ์ด๋ฐ ์ด๋ฐ ์ํฉ์ ๋ํ ์ค๋ช ๊ณผ ํจ๊ป ์๊ตฌ์ฌํญ๊ณผ ํธ๋ํฝ ๋ฑ์ ๊ฐ์ ํ ์๋๋ฆฌ์ค๋ฅผ ๋ง๋ ๋ค
- ํด๋น ์๊ตฌ์ฌํญ์ ์ํ ์ต์ ๊ตฌํ์ ํ๋ค
- ์ฑ ์์ ์ ์ํ ์ค๊ณ๋ฅผ ํตํด ์๋๋ฆฌ์ค ๋ณ๋ก ํ ์คํธ ๋ฐ ๊ฐ์ ์ ํ๋ค
- ํด๋น ๊ธฐ๋ก์ ๋จ๊ธด๋ค.
Rate Limiter(์ฒ๋ฆฌ์จ ์ ํ ์ฅ์น ์ค๊ณ)
1. ํ๋ก์ ํธ ๋ฐฐ๊ฒฝ
- ์ด์ ์ค์ธ ์ปค๋ฎค๋ํฐ ์๋น์ค์์ ํน์ ๊ฒ์๊ธ์ด๋ ์ธ๊ธฐ API์ ์งง์ ์๊ฐ ๋์ ์์ฒญ์ด ๋ชฐ๋ฆฌ๋ ์ํฉ์ด ๋ฐ์ํ๋ค.ย ์ผ๋ถ๋ ์ ์ ์ฌ์ฉ์ ์ ์ ์ด์ง๋ง,ย ์ผ๋ถ๋ ์๋ก๊ณ ์นจ ๋ฐ๋ณต์ด๋ ๋น์ ์ ํธ์ถ๋ก ์ธํด ์๋ฒ ์์์ ๊ณผ๋ํ๊ฒ ์ฌ์ฉํ๋ค.
- ์ด๋ก ์ธํด ๋ค์ ๋ฌธ์ ๊ฐ ์๊ธด๋ค. (์ ํ๋ฆฌ์ผ์ด์ ์๋ฒ ๋ถํ ์ฆ๊ฐ, DB ์กฐํ๋ ๊ธ์ฆ, ํน์ ์ฌ์ฉ์์ ๊ณผ๋ํ ํธ์ถ๋ก ์ ์ฒด ์ฌ์ฉ์ ๊ฒฝํ ์ ํ, ๋ก๊ทธ์ธ/๋น๋ก๊ทธ์ธ ์ฌ์ฉ์ ๊ฐ ๊ณต์ ํ์ง ์์ ์ฌ์ฉ๋ ๋ถ๋ฐฐ)
- ๊ทธ๋์ API ์์ฒญ ์๋ฅผ ์ผ์ ๊ธฐ์ค์ผ๋ก ์ ํํ๋ ์ฒ๋ฆฌ์จ ์ ํ ์ฅ์น๋ฅผ ์ค๊ณํ๊ณ ๊ตฌํํ๋ค.
2. ์๋น์ค ๊ฐ์
- ์๋น์ค๋ ๊ฒ์๊ธ ์กฐํ ๊ธฐ๋ฅ์ด ์๋ ์ปค๋ฎค๋ํฐ ์๋น์ค๋ผ๊ณ ๊ฐ์ ํ๋ค.
- ๋์ API - GETย /posts/{postId}
- API ํน์งย
- ์กฐํ ์์ฒญ์ด ๋งค์ฐ ๋ง๋ค
- ์ธ๊ธฐ ๊ฒ์๊ธ์ ํธ๋ํฝ์ด ๋ชฐ๋ฆด ์ ์๋ค
- ๋น๋ก๊ทธ์ธ ์ฌ์ฉ์๋ IP ๊ธฐ์ค์ผ๋ก ์๋ณํด์ผ ํ๋ค
- ๋ก๊ทธ์ธ ์ฌ์ฉ์๋ ์ฌ์ฉ์ ID ๊ธฐ์ค์ผ๋ก ์๋ณํ ์ ์๋ค
3. ๋ชฉํ
- ์ด ํ๋ก์ ํธ์ ๋ชฉํ๋ ๋จ์ํ ์์ฒญ์ ๋ง๋ ๊ฒ์ด ์๋๋ผ,ย ํ์ค์ ์ธ ์ ์ฝ์ด ์๋ ํ๊ฒฝ์์ rate limiter๋ฅผ ์ ์ง์ ์ผ๋ก ์ค๊ณยท๊ตฌํยท๊ฐ์ ํ๋ ๊ฒ์ด๋ค.
- ์ต์ข
์ ์ผ๋ก ๋ค์์ ๋ณด์ฌ์ฃผ๋ ๊ฒ์ ๋ชฉํ๋ก ํ๋ค.
- ๋จ์ผ ์๋ฒ ํ๊ฒฝ์์์ ๊ธฐ๋ณธ ์ฒ๋ฆฌ์จ ์ ํ ๊ตฌํ
- ๋์์ฑ ๋ฌธ์ ์ฌํ ๋ฐ ๊ฐ์
- ๋ค์ค ์๋ฒ ํ๊ฒฝ์์์ ํ๊ณ ๋ถ์
- Redis ๊ธฐ๋ฐ ๋ถ์ฐ ์ฒ๋ฆฌ์จ ์ ํ ์ฅ์น ๊ตฌํ
- ์๊ณ ๋ฆฌ์ฆ๋ณ ์ฐจ์ด์ ๋น๊ต
- ๋ถํ ํ ์คํธ๋ฅผ ํตํ ๊ฒ์ฆ
4. ์๊ตฌ์ฌํญ
- ๊ธฐ๋ฅ ์๊ตฌ์ฌํญ
- ๋น๋ก๊ทธ์ธ ์ฌ์ฉ์๋ IP ๊ธฐ์ค์ผ๋ก ์์ฒญ ํ์๋ฅผ ์ ํํ๋ค
- ๋ก๊ทธ์ธ ์ฌ์ฉ์๋ ์ฌ์ฉ์ ID ๊ธฐ์ค์ผ๋ก ์์ฒญ ํ์๋ฅผ ์ ํํ๋ค
- ๊ด๋ฆฌ์๋ ์ ํ ๋์์์ ์ ์ธํ๋ค
- ์ ํ ์ด๊ณผ ์ 429 Too Many Requests ๋ฅผ ๋ฐํํ๋ค
- ์๋ต ํค๋์ ๋จ์ ์์ฒญ ์์ ์ ํ ์ ๋ณด๋ฅผ ํฌํจํ๋ค
- ์ ์ฑ
์๊ตฌ์ฌํญ
- ๋น๋ก๊ทธ์ธ ์ฌ์ฉ์:ย 1๋ถ์ 30ํ
- ๊ด๋ฆฌ์:ย ์ ํ ์์
- ๋น๊ธฐ๋ฅ ์๊ตฌ์ฌํญ
- ๋์ ์์ฒญ ์ํฉ์์๋ ๊ฐ๋ฅํ ํ ์ ํํด์ผ ํ๋ค
- ์๋ฒ๊ฐ ์ฌ๋ฌ ๋์ฌ๋ ๋์ผํ ์ ํ ์ ์ฑ ์ด ์ ์ฉ๋์ด์ผ ํ๋ค
- ์ถํ ๋ค๋ฅธ API์๋ ํ์ฅ ๊ฐ๋ฅํด์ผ ํ๋ค
- ์๊ณ ๋ฆฌ์ฆ ๊ต์ฒด๊ฐ ๊ฐ๋ฅํ๋๋ก ๊ตฌ์กฐ๋ฅผ ๋ถ๋ฆฌํด์ผ ํ๋ค
1์ฐจ ์๋๋ฆฌ์ค : ๋จ์ผ ์๋ฒ + ๋ฉ๋ชจ๋ฆฌ ๊ธฐ๋ฐ Fixed Window
- ๊ฐ์ฅ ๋จ์ํ ๋ฐฉ์
- ์ฌ์ฉ์๋ณ key ์์ฑ -> ํ์ฌ 1๋ถ ์๋์ฐ ๋ด ์์ฒญ ์๋ฅผ ์ ์ฅํ๋ค -> ์ ํ ํ์๋ฅผ ๋์ผ๋ฉด ์ฐจ๋จํ๋ค
- ex) user:123 -> 1๋ถ๋์ 100ํ, ip:10.0.0.1 -> 1๋ถ ๋์ 30ํ
1 | |
-
ํด๋น ํํฐ๋ฅผ ์ธํฐ์ ํฐ์์ ์ฌ์ฉํ์ฌ
rateLimiter.tryAcquire()HTTP ์์ฒญ์ ๊ฐ๋ก์ฑ์ rate limit๋ฅผ ํ๋๋ก ๊ตฌํ์ ํ๋ค. - HashMap ์ฌ์ฉ ์ด์ ?
- ์ฌ์ฉ์๋ณ ์์ฒญ ํ์๋ฅผ key-value๋ก ์ ์ฅํ๊ธฐ ์ํด HashMap์ ์ ํํ๋ค.
- 1์ฐจ์์๋ ๋์์ฑ์ ๊ณ ๋ คํ์ง ์๊ณ , ๊ฐ์ฅ ์ง๊ด์ ์ธ ๋ฐฉ์(getOrDefault + put)์ผ๋ก ๊ตฌํํ๋ค.
- Interceptor ์ ํํ ์ด์ ?
- spring mvc๋ ๋ค์๊ณผ ๊ฐ์ ์์๋ฅผ ๊ฐ์ง๋ค
HTTP ์์ฒญ -> Filter -> DispatcherServlet -> Interceptor -> Controller- ๊ทผ๋ฐ Filter์ ๋นํด Interceptor๋ ๋ spring mvc์ ๊ตฌ์กฐ์ ํนํ๋ ํํฐ ๊ธฐ๋ฅ์ ์ ๊ณต์ ํ๋ค. spring bean์ ์์ฐ์ค๋ฝ๊ฒ ์์กด์ฑ ์ฃผ์ ํ ์ ์๋๊ฒ์ด ๊ฐ์ฅ ํฐ ํน์ง์ด๋ค.
- ๊ทธ๋์ FixedWindowRateLimiter๋ ์คํ๋ง ๋น์ ์์กดํ๋ฏ๋ก ์ฌ์ฉ์ ํ๋ค.
RateLimitInterceptor ํ๋ฆ
1 | |
2์ฐจ ์๋๋ฆฌ์ค: ๋์์ฑ ๋ฌธ์ ์ฌํ ๋ฐ ๊ฐ์
๋ชฉํ
- 1์ฐจ ๊ตฌํ(FixedWindowRateLimiter)์์ ๋์ ์์ฒญ ์ limit์ ์ด๊ณผํ ์์ฒญ์ด ํ์ฉ๋๋ ํ์์ย ์ฌํํ๊ณ ,ย ์์ธ์ ๋ถ์ํ ๋คย ๊ฐ์ ํด๋ณด์
ํ์ฌ ๊ตฌํ์ ๋ฌธ์
1 | |
1 | |
- ๋ง์ฝ 200๊ฐ ์ค๋ ๋๊ฐ ๋์์ ์์ฒญํ๋ฉด ํ์ฉ ์๊ฐ limit๋ฅผ ์ด๊ณผํ ๊น?
- ์ค์ ํ ์คํธ ์ฝ๋๋ฅผ ๋๋ ค๋ณธ ๊ฒฐ๊ณผ allow ๋ ์๊ฐ limit๋ก ์ค์ ํ 100๋ณด๋ค ํฐ ๊ฒฝ์ฐ๊ฐ ์๊ธฐ๋ ๊ฑธ ์ ์ ์๋ค. ์ด์ ๊ฐ ๋ญ๊น?
- ํ์ฌ ์ํ
- ์ง๊ธ FixedWindowRateLimiter ๊ฐ์ ๊ฒฝ์ฐ @Component์ด๋ฏ๋ก ์ฑ๊ธํค ๋น ํ๋๋ง ์กด์ฌ๋ฅผ ํด์ ๋ชจ๋ ์ค๋ ๋๊ฐ HashMap์ ๊ณต์ ํ๊ณ ์๋ค.
getOrDefault()์ฝ๊ธฐ์request.put()์ฐ๊ธฐ๊ฐ ๋ถ๋ฆฌ๋์ด ์๋ค.- ๋จ์ผ ์ค๋ ๋์์๋ ๋ฌธ์ ๊ฐ ์์ง๋ง, ๋์ ์์ฒญ ์ ์ฌ๋ฌ ์ค๋ ๋๊ฐ ๊ฐ์ ๊ฐ์ ์ฝ๊ณ ๊ฐ์ ๊ฐ์ ์ธ ์ ์๋ค
- ์๋ฅผ ๋ค์ด ์ค๋ ๋ A,B,C๊ฐ ์์ผ๋ฉด count๊ฐ ํ์ฌ 99๋ผ๊ณ ๊ฐ์ ์ ํ๋ฉด A ์ค๋ ๋๊ฐ ์ฝ๊ณ ์ฐ๋ ์ฌ์ด์ ์ค๋ ๋ B์ C๋ ํ์ฌ count ๊ฐ์ ์ฝ์ผ๋ฉด ์ฌ์ ํ 99์ด๋ค. ๊ทธ๋์ 3๊ฐ์ ์ค๋ ๋ ๋ชจ๋ ํ์ฉ์ด ๋๋ ๋งค์ง~~ ์ด ๋ฐ์ํ๋ค.
- ๊ทธ๋์ ์ ์ฌ์ง๊ณผ ๊ฐ์ด ํ์ฉ๋ ์์ฒญ ์๊ฐ limit ๋ณด๋ค ๋ ์ปค์ง๋ ๊ฒฝ์ฐ๊ฐ ์๊ธฐ๋ ๊ฒ์ด๋ค. ์ด๋ฏธ ์ด๊ณผ ํ์ฉ๋ B์ C๋ ๋๋๋ฆด ์ ์๋ค
๊ฐ์
- ๊ทธ๋ ๋ค๋ฉด ์ด๋ป๊ฒ ๊ฐ์ ํ ์ ์์๊น? ๊ฒฐ๋ก ๋ถํฐ ๋งํ๋ฉด ConcurrentHashMap + AtomicInteger
1 | |
- ConcurrentHashMap๊ณผ AtomicInteger์ฌ์ฉ ์ด์ ?
- ConcurrentHashMap์ ๋์์ฑ ์ปฌ๋ ์
์ ํ ์ข
๋ฅ๋ก HashMap์ ๊ฐ์ ๋ฒ์ ์ด๋ผ๊ณ ๋ณผ ์ ์๋๋ฐ ์ฌ๋ฌ ์ค๋ ๋๊ฐ ๋์ ์ ๊ฐ์ Map์ ์ ๊ทผํ ๋ ๋ฐ์ดํฐ ์ ํฉ์ฑ์ ๋ณด์ฅํ๋ค.
- HashMap๊ฐ์ ๊ฒฝ์ฐ์๋ ๋์ ์ ๊ทผ ์ ๋ด๋ถ ๊ตฌ์กฐ๊ฐ ๊นจ์ง ์ ์์ง๋ง ConcurrentHashMap์ ๋ด๋ถ์ ์ผ๋ก ๋ฒํท ๋จ์ ๋ฝ์ ์ฌ์ฉํด์ ์ด๋ฅผ ๋ฐฉ์งํ๋ค.
- AtomicInteger ๊ฐ์ ๊ฒฝ์ฐ์๋ ์นด์ดํธ์ ์ฝ๊ธฐ + ์ฆ๊ฐ + ์ฐ๊ธฐ๋ฅผ ํ๋์ ์์์ ์ฐ์ฐ์ผ๋ก
incrementAndGet()์ผ๋ก ์ฒ๋ฆฌํ๋ค. CAS์ฐ์ฐ์ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ ๋ ์ค๋ ๋๊ฐ ๋์์ ํธ์ถํด๋ ๋ฐ๋์ ๋ค๋ฅธ ๊ฐ์ ๋ฐํํ๋ค. ๊ทธ๋์ ๊ฐ์ ๊ฐ์ ์ฝ๊ณ ๊ฐ์ ๊ฐ์ ์ฐ๋ ๋ฌธ์ ๋ฅผ ์ฐจ๋จํ๋ค.int count = request.computeIfAbsent(value, k -> new AtomicInteger(0)).incrementAndGet();์ด ์ฐ์ฐ ์์ฒด๊ฐ ์์์ ์ผ๋ก ์งํ๋๋ ๊ฒ์ด๋ค.
- ์ด์ ์ฌ๋ฌ ์ค๋ ๋๊ฐ ๋์์ ์์ฒญํด๋ ํ์ฉ์๊ฐ limit๋ฅผ ์ด๊ณผํ์ง ์๊ณ ์ ํํ 100์์ ๋ฉ์ถ๊ฒ ๋์๋ค.
- ConcurrentHashMap์ ๋์์ฑ ์ปฌ๋ ์
์ ํ ์ข
๋ฅ๋ก HashMap์ ๊ฐ์ ๋ฒ์ ์ด๋ผ๊ณ ๋ณผ ์ ์๋๋ฐ ์ฌ๋ฌ ์ค๋ ๋๊ฐ ๋์ ์ ๊ฐ์ Map์ ์ ๊ทผํ ๋ ๋ฐ์ดํฐ ์ ํฉ์ฑ์ ๋ณด์ฅํ๋ค.
๋ค์ ํธ
- ์ด์ ๋จ์ผ ์๋ฒ์์ ์๊ธธ์ ์๋ ๋์์ฑ์ ํด๊ฒฐํ์ง๋ง, ์๋ฒ๊ฐ ๋ง์ฝ ์ฌ๋ฌ ๋๋ผ๋ฉด? ๊ฐ ์๋ฒ์ ๋ ๋ฆฝ์ ์ด counter๊ฐ ์๊ธฐ๋๋ฐ ์ผ๊ด์ฑ์ ์ ์งํ ์์๊ฒ ๋๋ค.
- ๊ฒฐ๊ตญ ์ด๋ค ๊ณต์ ์ ์ฅ์๊ฐ ํ์ํ๊ฒ์ธ๋ฐ ๋ค์ํธ์์ ์ด๋ป๊ฒ ํด๊ฒฐ ํด ๋ณผ ์ ์์์ง์ ๋ํด ๋ค๋ค๋ณด์
