BackEnd๐ŸŒฑ/Etc

์™ธ๋ถ€ API๋ฅผ ์—ฐ๋™ํ•  ๋•Œ ๊ณ ๋ คํ•˜๋ฉด ์ข‹์€ ์ ๋“ค

dkswnkk 2024. 2. 24. 00:37

๊ฐœ์š”

์ตœ๊ทผ ํ”„๋กœ์ ํŠธ์—์„œ ์™ธ๋ถ€ API๋ฅผ ์—ฐ๋™ํ•˜๋Š” ์ผ์ด ๊ต‰์žฅํžˆ ๋งŽ์•˜์—ˆ๋Š”๋ฐ, ์ž‘์—…ํ•˜๋ฉด์„œ ์–ป์€ ๋‹ค์–‘ํ•œ ๊ฒฝํ—˜๊ณผ ์ง€์‹์„ ๊ณต์œ ํ•˜๊ณ ์ž ์ž‘์„ฑํ•˜๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ํ”ผ๋“œ๋ฐฑ์€ ์–ธ์ œ๋“  ํ™˜์˜์ด๋ฉฐ ๋Œ“๊ธ€ ๋‚จ๊ฒจ์ฃผ์‹œ๋ฉด ๊ฐ์‚ฌํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

 

 

1. I/O์™€ ํŠธ๋žœ์žญ์…˜์„ ๋ถ„๋ฆฌํ•ด๋ผ

ํŠธ๋žœ์žญ์…˜์€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€ ํ†ต์‹ ํ•˜๊ธฐ ์œ„ํ•ด ์ปค๋„ฅ์…˜์„ ํ•„์š”๋กœ ํ•œ๋‹ค. ํ•˜์ง€๋งŒ ์ด ์ปค๋„ฅ์…˜์„ ์ƒ์„ฑํ•˜๋Š” ๋ฐ๋Š” ๊ฝค ๋งŽ์€ ๋น„์šฉ์ด ๋“ค๋ฉฐ, ๋Œ€๋ถ€๋ถ„ ์ด๋ฅผ ์ ˆ์•ฝํ•˜๊ธฐ ์œ„ํ•ด ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์„œ๋ฒ„(WAS)๋Š” ์‹คํ–‰ ์‹œ ๋ฏธ๋ฆฌ ์ผ์ • ์ˆ˜์˜ ์ปค๋„ฅ์…˜ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์–ด ํ’€์— ์ €์žฅํ•œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ํด๋ผ์ด์–ธํŠธ์˜ ์š”์ฒญ์ด ๋ฐœ์ƒํ•˜๋ฉด ์ด ํ’€์—์„œ ์ด๋ฏธ ์ƒ์„ฑ๋˜์–ด ์žˆ๋Š” ์ปค๋„ฅ์…˜ ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ์‹์„ ์ด์šฉํ•œ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ์ปค๋„ฅ์…˜ ํ’€์˜ ํฌ๊ธฐ๋Š” ์ œํ•œ๋˜์–ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ๋™์‹œ์— ์ˆ˜๋งŽ์€ ์š”์ฒญ๋“ค์ด ์ปค๋„ฅ์…˜ ํ’€์˜ ๊ฐœ์ˆ˜ ์ด์ƒ์œผ๋กœ ์˜ค๊ฒŒ ๋œ๋‹ค๋ฉด, ์ปค๋„ฅ์…˜์„ ํš๋“ํ•˜์ง€ ๋ชปํ•œ ์š”์ฒญ๋“ค์€ ๋‹ค๋ฅธ ์š”์ฒญ์ด ๋๋‚˜ ์ปค๋„ฅ์…˜์ด ๋ฐ˜๋‚ฉ๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฌ๊ฒŒ ๋˜๊ธฐ ๋•Œ๋ฌธ์— ์ง€์—ฐ์ด ๋ฐœ์ƒํ•˜๊ฒŒ ๋œ๋‹ค.

์ด๋Ÿฌํ•œ ์ด์œ ๋กœ ๋งŒ์•ฝ ํŠธ๋žœ์žญ์…˜ ๋‚ด๋ถ€์— ์™ธ๋ถ€ API๋ฅผ ํ˜ธ์ถœํ•˜๋Š” I/O๋กœ์ง์ด ํฌํ•จ๋˜์–ด ์žˆ๋‹ค๋ฉด, ๋ถˆํ•„์š”ํ•˜๊ฒŒ ํŠธ๋žœ์žญ์…˜์„ ๊ธธ๊ฒŒ ์žก๊ณ  ์žˆ์ง€ ๋ง๋„๋ก ํŠธ๋žœ์žญ์…˜๊ณผ I/O ๋กœ์ง์„ ๋ถ„๋ฆฌํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค. ๋‹ค์Œ์˜ ๋ฐฉ์‹๋“ค์„ ์ด์šฉํ•˜๋ฉด ์†์‰ฝ๊ฒŒ ๋ถ„๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.

  1. ํผ์‚ฌ๋“œ ํŒจํ„ด(Facade Pattern) ์‚ฌ์šฉ
  2. ์ด๋ฒคํŠธ ์‚ฌ์šฉ

ํผ์‚ฌ๋“œ ํŒจํ„ด(Facade Pattern)์€ ์‚ฌ์šฉํ•˜๊ธฐ ๋ณต์žกํ•œ ํด๋ž˜์Šค ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ํŽธํ•˜๊ฒŒ ๊ฐ„๋‹จํ•œ ์ธํ„ฐํŽ˜์ด์Šค(API)๋กœ ๊ตฌ์„ฑํ•˜๊ธฐ ์œ„ํ•œ ๊ตฌ์กฐ ํŒจํ„ด์ด๋‹ค. ๋ณดํ†ต ์‹œ์Šคํ…œ์ด ๋ณต์žกํ•˜๊ฑฐ๋‚˜ ์‹œ์Šคํ…œ์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋Š” ์™ธ๋ถ€์™€ ๊ฒฐํ•ฉ๋„๊ฐ€ ๋„ˆ๋ฌด ๋†’์„ ๋•Œ ์˜์กด์„ฑ์„ ๋‚ฎ์ถ”๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•œ๋‹ค. ํ˜น์€ ์ˆœํ™˜ ์˜์กด์„ฑ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ๋„ ์ฃผ๋กœ ์‚ฌ์šฉํ•œ๋‹ค.

@Service
public class FacadeExample {
    // ์™ธ๋ถ€ api ์—ฐ๋™ ํด๋ž˜์Šค
    private ExternalApiService apiService;
    
    // ํŠธ๋žœ์žญ์…˜์„ ์ฒ˜๋ฆฌํ•˜๋Š” ํด๋ž˜์Šค
    private DatabaseService databaseService;
    
    public void saveDataFromExternalService(){
        Object data = apiService.getData();
        databaseService.save(data);
    }
}

์œ„ ์˜ˆ์‹œ์—์„œ ํผ์‚ฌ๋“œ ํด๋ž˜์Šค๋Š” ์™ธ๋ถ€ I/O ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์ง‘ํ•˜๊ณ , ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ €์žฅํ•˜๋Š” ์—ญํ• ์„ ํ•œ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์™ธ๋ถ€ API ์š”์ฒญ๊ณผ ํŠธ๋žœ์žญ์…˜์„ ๋ถ„๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.

๋‘ ๋ฒˆ์งธ๋Š” ์ด๋ฒคํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค. ์ด์ „์— ์ด ๊ธ€์—์„œ ํ•œ๋ฒˆ ์ •๋ฆฌํ•œ ์ ์ด ์žˆ๋‹ค.

 

์ด ๋ฐฉ์‹์€ ํŠธ๋žœ์žญ์…˜์ด ์„ฑ๊ณต์ ์œผ๋กœ ์ข…๋ฃŒ๋œ ํ›„์— ํŠน์ • ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒฝ์šฐ์— ํšจ๊ณผ์ ์ด๋‹ค.

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

์–ธ์ œ๋‚˜ ์ •๋‹ต์€ ์—†๊ธฐ ๋•Œ๋ฌธ์— ๋ณธ์ธ์˜ ํ”„๋กœ์ ํŠธ์˜ ๊ทœ์น™๊ณผ ์ƒํ™ฉ์— ์•Œ๋งž์€ ๋ฐฉ๋ฒ•์œผ๋กœ ์ ์šฉํ•˜๋ฉด ๋œ๋‹ค. 

 

 

2. ์Šค๋ ˆ๋“œํ’€๋กœ ์š”์ฒญ TPS๋ฅผ ์กฐ์ ˆํ•ด๋ผ

์™ธ๋ถ€ API๋ฅผ ์—ฐ๋™ํ•  ๋•Œ๋Š” ์šฐ๋ฆฌ ์„œ๋น„์Šค์˜ ์ปดํ“จํŒ… ํ™˜๊ฒฝ๋„ ์ค‘์š”ํ•˜์ง€๋งŒ, ์ƒ๋Œ€๋ฐฉ์˜ ์ปดํ“จํŒ… ํ™˜๊ฒฝ์„ ํŠนํžˆ ๊ณ ๋ คํ•ด์•ผ ํ•œ๋‹ค. ์šฐ๋ฆฌ ์„œ๋น„์Šค๊ฐ€ ์ดˆ๋‹น 100๊ฐœ์˜ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋”๋ผ๋„, ์ƒ๋Œ€๋ฐฉ ์„œ๋ฒ„๋Š” ์ดˆ๋‹น 10๊ฐœ์˜ ์š”์ฒญ๋งŒ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด ํ•ด๋‹น ์„œ๋ฒ„์— ๋ถ€ํ•˜๋ฅผ ๊ฐ€ํ•˜๊ฒŒ ๋˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

์ด๋Ÿฐ ์ƒํ™ฉ์—์„œ๋Š” ์™ธ๋ถ€ API ์š”์ฒญ์„ ์œ„ํ•œ ๋ณ„๋„์˜ ์Šค๋ ˆ๋“œ ํ’€์„ ์ƒ์„ฑํ•˜์—ฌ ์š”์ฒญ ์ฒ˜๋ฆฌ๋Ÿ‰(TPS)์„ ์กฐ์ ˆํ•˜๋Š” ๊ฒƒ์ด ํšจ๊ณผ์ ์ด๋‹ค.

๋ณ„๋„๋กœ ์Šค๋ ˆ๋“œ ํ’€์„ ์„ค์ •ํ•˜์ง€ ์•Š๊ณ  ์‚ฌ์šฉํ•œ๋‹ค๋ฉด ๊ณตํ†ต ํ’€(common pool)์„ ์‚ฌ์šฉํ•  ๊ฒƒ์ด๋‹ค. ์ด ๊ฒฝ์šฐ, ์šฐ๋ฆฌ ์ปดํ“จํŒ… ํ™˜๊ฒฝ์ด ํ—ˆ์šฉํ•˜๋Š” ํ•œ ์™ธ๋ถ€ API์— ์ œํ•œ ์—†์ด ์š”์ฒญ์„ ๋ณด๋‚ด๊ฒŒ ๋  ๊ฒƒ์ด๋‹ค. ์ด๋ ‡๊ฒŒ ๋˜๋ฉด ์™ธ๋ถ€ API๋ฅผ ์ œ๊ณตํ•˜๋Š” ์„œ๋ฒ„์— ํ—ˆ์šฉ์น˜ ์ด์ƒ์œผ๋กœ ์š”์ฒญ์ด ๊ฐ€๊ฒŒ ๋˜์–ด ํ•ด๋‹น ์„œ๋ฒ„์˜ ์ปดํ“จํŒ… ์†๋„๊ฐ€ ๋Š๋ ค์งˆ ์ˆ˜ ์žˆ๋‹ค. ๋˜ํ•œ ์„œ๋น„์Šค A๊ฐ€ ์žฅ์• ๋ฅผ ์ผ์œผํ‚ค๋ฉด์„œ ์‘๋‹ต์ด ์ง€์—ฐ๋˜๋ฉด ํ’€์— ๋‚จ์€ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์ปค๋„ฅ์…˜์ด ์ค„์–ด๋“ค๋ฉด์„œ ์„œ๋น„์Šค B์™€ C์˜ ์—ฐ๋™๋„ ๋Œ€๊ธฐ ์ƒํƒœ์— ๋†“์ด๊ฒŒ ๋˜๋Š” ์—ฐ์‡„ ์ง€์—ฐ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜๊ฒŒ ๋œ๋‹ค.

์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋ฅผ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ์œ„ ์˜ˆ์‹œ์ฒ˜๋Ÿผ ๊ฐ ์—ฐ๋™ API๋งˆ๋‹ค ๋ณ„๋„์˜ ์Šค๋ ˆ๋“œ ํ’€์„ ์ง€์ •ํ•˜๋ฉด ์†์‰ฝ๊ฒŒ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค. ์œ„์˜ ๊ฒฝ์šฐ์—์„œ๋Š” ์„œ๋น„์Šค A๊ฐ€ ์žฅ์• ๋ฅผ ์ผ์œผ์ผœ๋„ ๊ฐ ์—ฐ๋™ ์„œ๋น„์Šค๋Š” ๋…๋ฆฝ์ ์ธ ์Šค๋ ˆ๋“œ ํ’€์„ ๊ฐ–๊ธฐ ๋•Œ๋ฌธ์—, ์„œ๋น„์Šค B์™€ C์˜ ์—ฐ๋™์€ ์„œ๋น„์Šค A์˜ ์ƒํƒœ์— ์˜ํ–ฅ์„ ๋ฐ›์ง€ ์•Š๋Š”๋‹ค.

๋˜ํ•œ ๋™์‹œ์— ๋งŽ์€ ์š”์ฒญ์ด ๋“ค์–ด์˜ค๋”๋ผ๋„, ์Šค๋ ˆ๋“œ ํ’€์— ์ง€์ •๋œ ์Šค๋ ˆ๋“œ ์ˆ˜๋งŒํผ๋งŒ ๋™์‹œ์— ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๊ณ , ๋‚˜๋จธ์ง€ ์š”์ฒญ๋“ค์€ ํ์—์„œ ๋Œ€๊ธฐํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์™ธ๋ถ€ API ์„œ๋ฒ„์— ๊ฐ€ํ•ด์ง€๋Š” ๋ถ€ํ•˜๋ฅผ ์กฐ์ ˆํ•  ์ˆ˜ ์žˆ๋‹ค.

์‹ค์ œ ์‚ฌ๋ก€๋กœ๋Š” ํ† ์Šค๋ฑ…ํฌ ๋Œ€์ถœ ์‹œ์Šคํ…œ ๊ฐœ๋ฐœ ๊ณผ์ •์—์„œ๋„ ์‚ดํŽด๋ณผ ์ˆ˜ ์žˆ๋‹ค.(SLASH 22 - ํ† ์Šค๋ฑ…ํฌ์˜ ์™„์ „ํžˆ ์ƒˆ๋กœ์šด ๋Œ€์ถœ ์‹œ์Šคํ…œ)

 

 

3. ๋น„๋™๊ธฐ์™€ ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ๋ฅผ ๊ณ ๋ คํ•ด๋ผ

ํ•˜๋‚˜์˜ ๋กœ์ง์—์„œ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์™ธ๋ถ€ API๋ฅผ ์ˆœ์ฐจ์ ์œผ๋กœ ํ˜ธ์ถœํ•˜๋Š” ๊ฒฝ์šฐ, ์ฒ˜๋ฆฌ์‹œ๊ฐ„์ด ์ƒ๋‹นํžˆ ์†Œ์š”๋  ์ˆ˜ ์žˆ๋‹ค. ์ด๋•Œ ๋น„๋™๊ธฐ์™€ ๋ณ‘๋ ฌ์ฒ˜๋ฆฌ๋ฅผ ์ ์šฉํ•˜๋ฉด ์ „์ฒด์ ์ธ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„์„ ํฌ๊ฒŒ ๋‹จ์ถ•ํ•  ์ˆ˜ ์žˆ๋‹ค.

Java์—์„œ๋Š” CompletableFuture๋ฅผ ํ™œ์šฉํ•˜์—ฌ ๋น„๋™๊ธฐ์™€ ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค. CompletableFuture ์‚ฌ์šฉ๋ฒ•์— ๋Œ€ํ•ด์„œ๋Š” ์ด์ „ ๊ธ€์—์„œ ์ž‘์„ฑํ•œ ์ ์ด ์žˆ๋‹ค.

CompletableFuture๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ๋Š” ์ฃผ์˜์ ์ด ์žˆ๋Š”๋ฐ, ๋ณ„๋„์˜ ์Šค๋ ˆ๋“œ ํ’€์„ ์ง€์ •ํ•ด์ฃผ์ง€ ์•Š์œผ๋ฉด fork join pool์ด ์‚ฌ์šฉ๋œ๋‹ค๋Š” ์ ์ด๋‹ค. fork join pool์€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ „์—ญ์—์„œ ์‚ฌ์šฉํ•˜๋Š” ํ’€๋กœ, ๋„คํŠธ์›Œํฌ I/O ์ž‘์—…๊ณผ ๊ฐ™์ด ๋Œ€๊ธฐ ์‹œ๊ฐ„์ด ๊ธด ์ž‘์—…์—์„œ๋Š” ์Šค๋ ˆ๋“œ๊ฐ€ ๋ธ”๋กœํ‚น๋˜์–ด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๋‹ค๋ฅธ ๋ถ€๋ถ„์— ์˜ํ–ฅ์„ ์ค„ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ I/O ์œ„์ฃผ์˜ ์ž‘์—…์ผ ๊ฒฝ์šฐ ๋ณ„๋„์˜ ์Šค๋ ˆ๋“œํ’€์„ ๊ผญ ์ง€์ •ํ•ด ์ฃผ๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

์Šค๋ ˆ๋“œ ํ’€์˜ ํฌ๊ธฐ๋Š” CPU Bound ์ž‘์—…์˜ ๊ฒฝ์šฐ ์ผ๋ฐ˜์ ์œผ๋กœ (์ฝ”์–ด + 1)๋งŒํผ์„ ์ง€์ •ํ•ด ์ค€๋‹ค. ํ•˜์ง€๋งŒ I/O Bound ์ž‘์—…์—์„œ๋Š” ์ฝ”์–ด ์ˆ˜์˜ 2๋ฐฐ, 3๋ฐฐ, 4๋ฐฐ ํ˜น์€ ๊ทธ ์ด์ƒ์„ ์ƒํ™ฉ์— ๋”ฐ๋ผ ์ง€์ •ํ•œ๋‹ค. ํฌ๊ธฐ๋ฅผ ๊ฒฐ์ •ํ•˜๊ธฐ๊ฐ€ ์–ด๋ ค์šธ ๋•Œ๋Š” ์•„๋ž˜์˜ ๊ณต์‹์„ ์ฐธ๊ณ ํ•˜๋Š” ๊ฒƒ๋„ ์ข‹๋‹ค.

Nthreads = Ncpu * Ucpu * (1 + W/C)

- Ncpu๋Š” ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ CPU ์ฝ”์–ด ์ˆ˜๋ฅผ ์˜๋ฏธํ•˜๋ฉฐ, Runtime.getRuntime().availableProcessors()๊ฐ€ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฐ’์„ ์‚ฌ์šฉํ•œ๋‹ค.
- Ucpu๋Š” CPU ํ™œ์šฉ ๋น„์œจ๋กœ, 0๊ณผ 1 ์‚ฌ์ด์˜ ๊ฐ’์„ ๊ฐ€์ง„๋‹ค.
- W/C๋Š” ๋Œ€๊ธฐ ์‹œ๊ฐ„๊ณผ ๊ณ„์‚ฐ ์‹œ๊ฐ„์˜ ๋น„์œจ์„ ์˜๋ฏธํ•œ๋‹ค.

๊ทธ๋ ‡๋‹ค๋ฉด ์Šค๋ ˆ๋“œํ’€์˜ ๊ฐœ์ˆ˜๋ฅผ ๋ฌด์ž‘์ • ๋งŽ์ด ๋Š˜๋ฆฌ๋ฉด ์„ฑ๋Šฅ์ด ์ข‹์•„์งˆ๊นŒ? ๊ทธ๊ฑด ๋˜ ์•„๋‹ˆ๋‹ค. CPU ์ฝ”์–ด์—์„œ ์‹คํ–‰๋˜๋˜ ์Šค๋ ˆ๋“œ๊ฐ€ ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ๋กœ ๋ฐ”๋€” ๋•Œ๋งˆ๋‹ค Context Switching์ด ๋ฐœ์ƒํ•˜๋ฉฐ ์ด๋กœ ์ธํ•ด CPU ์‹œ๊ฐ„์ด ์ถ”๊ฐ€๋กœ ์†Œ์š”๋œ๋‹ค. ๋”ฐ๋ผ์„œ CPU ์ฝ”์–ด ์ˆ˜๋ฅผ ์ดˆ๊ณผํ•˜๋Š” ์Šค๋ ˆ๋“œ๋ฅผ ์ƒ์„ฑํ•˜๋ฉด Context Switching์œผ๋กœ ์ธํ•œ ์˜ค๋ฒ„ํ—ค๋“œ๊ฐ€ ์ฆ๊ฐ€ํ•˜๊ฒŒ ๋˜๊ณ  ํŠน์ • ๊ฐœ์ˆ˜ ์ด์ƒ๋ถ€ํ„ฐ๋Š” ์„ฑ๋Šฅ์ด ์˜คํžˆ๋ ค ์ €ํ•˜๋  ์ˆ˜ ์žˆ๋‹ค.

 

 

4. ์„œํ‚ท ๋ธŒ๋ ˆ์ด์ปค๋ฅผ ํ†ตํ•ด ํ๋ฆ„์„ ์ œ์–ดํ•ด๋ผ

์™ธ๋ถ€ API๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ํŠน์ • API์— ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜์—ฌ ์—๋Ÿฌ๊ฐ€ ๋‚˜๊ฑฐ๋‚˜ ์‘๋‹ต์ด ์ง€์—ฐ๋˜๋Š” ์ƒํ™ฉ์—์„œ ๊ณ„์†ํ•ด์„œ ํ•ด๋‹น ์™ธ๋ถ€ API๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค๋ฉด ์šฐ๋ฆฌ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์‘๋‹ต๋„ ์ง€์—ฐ๋˜๋Š” ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๋Ÿฐ ๊ฒฝ์šฐ ์„œํ‚ท๋ธŒ๋ ˆ์ด์ปค๋ฅผ ํ™œ์šฉํ•˜์—ฌ ํ๋ฆ„์„ ์ œ์–ดํ•  ์ˆ˜ ์žˆ๋‹ค.

์„œํ‚ท ๋ธŒ๋ ˆ์ด์ปค๋Š” ์ „๊ธฐ ํšŒ๋กœ์—์„œ ๊ณผ๋ถ€ํ•˜๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ํšŒ๋กœ๋ฅผ ๋Š์–ด ํ”ผํ•ด๋ฅผ ์ตœ์†Œํ™”ํ•˜๋Š” ์›๋ฆฌ์—์„œ ์•„์ด๋””์–ด๋ฅผ ์–ป์€ ํŒจํ„ด์ด๋‹ค. API ํ˜ธ์ถœ์— ๋ฌธ์ œ๊ฐ€ ์ƒ๊ฒจ ์ž„๊ณ„์น˜ ์ด์ƒ์˜ ์ง€์—ฐ์‘๋‹ต์ด๋‚˜ ์—๋Ÿฌ์œจ์ด ๋ฐœ์ƒํ•œ๋‹ค๋ฉด ํ•ด๋‹น API ํ˜ธ์ถœ์„ ๋” ์ด์ƒ ํ•˜์ง€ ์•Š๊ณ , ์ฆ‰์‹œ ์—๋Ÿฌ๋ฅผ ๋ฐ˜ํ™˜ํ•˜์—ฌ ์™ธ๋ถ€ ์„œ๋น„์Šค์— ๋Œ€ํ•œ ๋ถˆํ•„์š”ํ•œ ํ˜ธ์ถœ์„ ๋ฐฉ์ง€ํ•˜๊ณ  ์šฐ๋ฆฌ ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ๋น ๋ฅด๊ฒŒ ์‘๋‹ต์„ ๋ณด๋‚ผ ์ˆ˜ ์žˆ๋‹ค. ๋˜ํ•œ ์™ธ๋ถ€ API A๋ฅผ B๋กœ ๋Œ€์ฒด๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค๋ฉด A์˜ ํ˜ธ์ถœ์„ ์ค‘๋‹จํ•˜๊ณ  B๋ฅผ ํ˜ธ์ถœํ•˜๋„๋ก ์ œ์–ดํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

์„œํ‚ท ๋ธŒ๋ ˆ์ด์ปค๋Š” ํฌ๊ฒŒ ์„ธ ๊ฐ€์ง€ ์ƒํƒœ๋ฅผ ๊ฐ€์ง„๋‹ค. 

  • Closed ์ƒํƒœ: ์ •์ƒ์ ์œผ๋กœ ์ž‘๋™ํ•˜๋Š” ์ƒํƒœ์ด๋‹ค. API ํ˜ธ์ถœ์ด ์ž˜ ์ด๋ฃจ์–ด์ง€๊ณ , ์—๋Ÿฌ์œจ์ด ํŠน์ • ์ž„๊ณ„์น˜ ์ดํ•˜์ผ ๊ฒฝ์šฐ ์ด ์ƒํƒœ๋ฅผ ์œ ์ง€ํ•œ๋‹ค.
  • Open ์ƒํƒœ: API ํ˜ธ์ถœ์— ๋ฌธ์ œ๊ฐ€ ์ƒ๊ฒจ ์—๋Ÿฌ์œจ์ด ์ž„๊ณ„์น˜๋ฅผ ์ดˆ๊ณผํ•˜๋ฉด, ์„œํ‚ท ๋ธŒ๋ ˆ์ด์ปค๋Š” Open ์ƒํƒœ๊ฐ€ ๋œ๋‹ค. ์ด ์ƒํƒœ์—์„œ๋Š” ๋ชจ๋“  API ํ˜ธ์ถœ์„ ์ฐจ๋‹จํ•˜๊ณ , ์ฆ‰์‹œ ์—๋Ÿฌ ์‘๋‹ต์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
  • Half-Open ์ƒํƒœ: Open ์ƒํƒœ์—์„œ ์ผ์ • ์‹œ๊ฐ„์ด ์ง€๋‚˜๋ฉด, ์„œํ‚ท ๋ธŒ๋ ˆ์ด์ปค๋Š” Half-Open ์ƒํƒœ๊ฐ€ ๋œ๋‹ค. ์ด ์ƒํƒœ์—์„œ๋Š” ์ผ๋ถ€ API ํ˜ธ์ถœ์„ ํ—ˆ์šฉํ•˜์—ฌ ์™ธ๋ถ€ ์„œ๋น„์Šค๊ฐ€ ์ •์ƒ์œผ๋กœ ๋ณต๊ตฌ๋˜์—ˆ๋Š”์ง€๋ฅผ ํ™•์ธํ•œ๋‹ค. ์ด๋•Œ API ํ˜ธ์ถœ์ด ์„ฑ๊ณตํ•˜๋ฉด ์„œํ‚ท ๋ธŒ๋ ˆ์ด์ปค๋Š” ๋‹ค์‹œ Closed ์ƒํƒœ๋กœ ๋Œ์•„๊ฐ€๊ณ , ์‹คํŒจํ•˜๋ฉด Open ์ƒํƒœ๋ฅผ ์œ ์ง€ํ•œ๋‹ค.

์„œํ‚ท ๋ธŒ๋ ˆ์ด์ปค๋ฅผ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ๋Š” Netflix์˜ Hystrix, Resilience4J ๋“ฑ์ด ์žˆ์œผ๋‹ˆ ํ™œ์šฉํ•˜๋ฉด ์ข‹๋‹ค.

 

 

5. Rate Limit์„ ๊ฑธ์–ด๋ผ

์ผ์ • ์‹œ๊ฐ„ ๋™์•ˆ ๋™์ผํ•œ ์š”์ฒญ์ด ์ง€๋‚˜์น˜๊ฒŒ ๋งŽ์ด ๋“ค์–ด์˜ค๋Š” ๊ฒƒ์„ ์ œ์–ดํ•˜๊ฑฐ๋‚˜, ํŠน์ • ๊ธฐ๊ด€์—์„œ ์ผ์ • ์‹œ๊ฐ„ ๋™์•ˆ API ํ˜ธ์ถœ ํšŸ์ˆ˜๋ฅผ ์ œํ•œํ•˜๋Š” ๋“ฑ์˜ ์ƒํ™ฉ์—์„œ Rate Limit ๊ธฐ๋Šฅ์„ ์ ์šฉํ•˜๋ฉด ์ข‹์€ ์„ ํƒ์ด ๋  ์ˆ˜ ์žˆ๋‹ค.

์ฒ˜๋ฆฌ์œจ ์ œํ•œ์„ ์œ„ํ•œ ๋‹ค์–‘ํ•œ ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด ์žˆ์œผ๋ฉฐ ๊ฐ๊ฐ์˜ ์ƒํ™ฉ์— ์•Œ๋งž๊ฒŒ ์ ์šฉํ•˜๋ฉด ๋œ๋‹ค.

  • ํ† ํฐ ๋ฒ„ํ‚ท ์•Œ๊ณ ๋ฆฌ์ฆ˜:  ๋ฒ„ํ‚ท์— ์ผ์ • ์‹œ๊ฐ„๋งˆ๋‹ค ํ† ํฐ์ด ์Œ“์ด๊ณ , ์š”์ฒญ์ด ๋“ค์–ด์˜ฌ ๋•Œ๋งˆ๋‹ค ํ† ํฐ์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ์‹์ด๋‹ค. ๋ฒ„ํ‚ท์— ํ† ํฐ์ด ์—†๋‹ค๋ฉด ์š”์ฒญ์„ ๋ฐ›์ง€ ์•Š์œผ๋ฉฐ, ์ผ์ •ํ•œ ์†๋„๋กœ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐ ์ ํ•ฉํ•˜๋‹ค.
  • ๋ˆ„์ถœ ๋ฒ„ํ‚ท ์•Œ๊ณ ๋ฆฌ์ฆ˜: ๋ฒ„ํ‚ท์— ์š”์ฒญ์ด ์Œ“์ด๊ณ  ์ผ์ • ์†๋„๋กœ ๋ฒ„ํ‚ท์—์„œ ๋ˆ„์ถœ๋˜์–ด ์ฒ˜๋ฆฌ๋˜๋Š” ๋ฐฉ์‹์ด๋‹ค. ๋ฒ„ํ‚ท์ด ๊ฐ€๋“ ์ฐผ์„ ๋•Œ ์ถ”๊ฐ€๋กœ ๋“ค์–ด์˜ค๋Š” ์š”์ฒญ์€ ๊ฑฐ๋ถ€๋˜๋ฉฐ, ์š”์ฒญ์˜ ํญ๋ฐœ์ ์ธ ์ฆ๊ฐ€๋ฅผ ๋ง‰๋Š” ๋ฐ ์œ ์šฉํ•˜๋‹ค.
  • ๊ณ ์ • ์œˆ๋„์šฐ ์•Œ๊ณ ๋ฆฌ์ฆ˜: ์‹œ๊ฐ„์„ ์ผ์ •ํ•œ ์œˆ๋„์šฐ๋กœ ๋‚˜๋ˆ„๊ณ , ๊ฐ ์œˆ๋„์šฐ์—์„œ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ์š”์ฒญ์˜ ์ˆ˜๋ฅผ ์ œํ•œํ•˜๋Š” ๋ฐฉ์‹์ด๋‹ค. ์œˆ๋„์šฐ๊ฐ€ ๋ฐ”๋€Œ๋ฉด ์š”์ฒญ ์ˆ˜๋Š” ์ดˆ๊ธฐํ™”๋˜๋ฉฐ, ๊ตฌํ˜„์ด ๊ฐ„๋‹จํ•˜์ง€๋งŒ ์œˆ๋„์šฐ ๋ณ€๊ฒฝ ์‹œ์ ์— ์š”์ฒญ์ด ๋ชฐ๋ฆด ์ˆ˜ ์žˆ๋Š” ๋ฌธ์ œ๊ฐ€ ์žˆ๋‹ค.
  • ์Šฌ๋ผ์ด๋”ฉ ๋กœ๊ทธ ์•Œ๊ณ ๋ฆฌ์ฆ˜: ๊ณ ์ • ์œˆ๋„์šฐ ์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•œ ๋ฐฉ์‹์œผ๋กœ, ๊ฐ ์š”์ฒญ์„ ๋กœ๊ทธ๋กœ ๊ธฐ๋กํ•˜๊ณ  ์ผ์ • ์‹œ๊ฐ„ ๋™์•ˆ์˜ ๋กœ๊ทธ ์ˆ˜๋ฅผ ํ™•์ธํ•˜์—ฌ ์š”์ฒญ์„ ์ œํ•œํ•œ๋‹ค. ์ด ๋ฐฉ์‹์€ ์ •ํ™•ํ•œ ์š”์ฒญ ์ˆ˜๋ฅผ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ๋กœ๊ทธ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๋ฐ ์ถ”๊ฐ€์ ์ธ ๋น„์šฉ์ด ๋“ ๋‹ค.
  • ์Šฌ๋ผ์ด๋”ฉ ์œˆ๋„์šฐ ์•Œ๊ณ ๋ฆฌ์ฆ˜: ๊ณ ์ • ์œˆ๋„์šฐ์™€ ์Šฌ๋ผ์ด๋”ฉ ๋กœ๊ทธ๋ฅผ ๊ฒฐํ•ฉํ•œ ๋ฐฉ์‹์œผ๋กœ, ์œˆ๋„์šฐ๋ฅผ ์ผ์ • ๊ฐ„๊ฒฉ์œผ๋กœ ์Šฌ๋ผ์ด๋”ฉํ•˜๋ฉด์„œ ์š”์ฒญ์„ ์ œํ•œํ•œ๋‹ค. ์ด ๋ฐฉ์‹์€ ๊ณ ์ • ์œˆ๋„์šฐ์˜ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ณ  ์Šฌ๋ผ์ด๋”ฉ ๋กœ๊ทธ๋ณด๋‹ค ํšจ์œจ์ ์œผ๋กœ ์š”์ฒญ์„ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.

Guava, Resilience4j, Bucket4j ๋“ฑ์˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํ™œ์šฉํ•˜๋ฉด, Rate Limit ๊ธฐ๋Šฅ์„ ์‰ฝ๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค. ์ธํ„ฐ๋„ท์— ์ด์— ๊ด€ํ•œ ๋‹ค์–‘ํ•œ ์ž๋ฃŒ๋“ค์ด ๋งŽ์œผ๋‹ˆ ์ž์„ธํ•œ ํ•™์Šต์„ ์›ํ•œ๋‹ค๋ฉด ์ฐพ์•„๋ณด๊ธธ ๋ฐ”๋ผ๋ฉฐ, ์ฑ…์œผ๋กœ ํ•™์Šตํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ๊ฐ€์ƒ ๋ฉด์ ‘ ์‚ฌ๋ก€๋กœ ๋ฐฐ์šฐ๋Š” ๋Œ€๊ทœ๋ชจ ์„ค๊ณ„ ์‹œ์Šคํ…œ ์„ค๊ณ„ ๊ธฐ์ดˆ 1๊ถŒ์—์„œ ์ฐพ์•„๋ณผ ์ˆ˜ ์žˆ๋‹ค.

 

 

6. ํƒ€์ž„์•„์›ƒ์„ ์„ค์ •ํ•ด๋ผ

Java์—์„œ RestTemplate๋‚˜ WebClient๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ, ํƒ€์ž„์•„์›ƒ์„ ๋ช…์‹œ์ ์œผ๋กœ ์„ค์ •ํ•˜์ง€ ์•Š์œผ๋ฉด ๋ฌด์ œํ•œ์œผ๋กœ ์„ค์ •๋œ๋‹ค. ์ด๋Ÿฌํ•œ ์ƒํ™ฉ์—์„œ ๋™์‹œ์— ๋Œ€๊ธฐํ•˜๋Š” ์™ธ๋ถ€ ์—ฐ๋™ ๊ฐœ์ˆ˜๊ฐ€ ๋งŽ์•„์ง€๋ฉด, ๋‚ด ์„œ๋น„์Šค์˜ ์†๋„๋Š” ์ ์ฐจ ๋Š๋ ค์ง€๊ฒŒ ๋˜๋ฉฐ ์ตœ์•…์˜ ๊ฒฝ์šฐ ๋ชจ๋“  ์Šค๋ ˆ๋“œ๊ฐ€ ๋Œ€๊ธฐ ์ƒํƒœ์— ๋น ์ ธ ๋‹ค๋ฅธ ํด๋ผ์ด์–ธํŠธ ์š”์ฒญ์— ์‘๋‹ตํ•  ์ˆ˜ ์žˆ๋Š” ์Šค๋ ˆ๋“œ๊ฐ€ ๋‚จ์•„์žˆ์ง€ ์•Š๊ฒŒ ๋œ๋‹ค. ๋”ฐ๋ผ์„œ ํƒ€์ž„์•„์›ƒ ์„ค์ •์€ ๋ฐ˜๋“œ์‹œ ํ•„์š”ํ•˜๋‹ค.

๋ณดํ†ต ์—ฐ๊ฒฐ ํƒ€์ž„์•„์›ƒ(Connection Timeout)๊ณผ ์ฝ๊ธฐ ํƒ€์ž„์•„์›ƒ(Read Timeout)์„ 1์ดˆ์—์„œ 5์ดˆ ์ด๋‚ด๋กœ ์„ค์ •ํ•œ๋‹ค. ์ผ๋ฐ˜์ ์œผ๋กœ ์ •์ƒ์ ์ธ ํ†ต์‹ ์ธ ๊ฒฝ์šฐ ๋Œ€๋ถ€๋ถ„ ์ด ์•ˆ์— ์™„๋ฃŒ๋˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ํ•˜์ง€๋งŒ ์ƒํ™ฉ์— ๋‹ฌ๋ผ์งˆ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ, ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์ƒํ™ฉ์— ์•Œ๋งž๊ฒŒ ์ ์šฉํ•˜๋ฉด ๋œ๋‹ค.

  • ์—ฐ๊ฒฐ ํƒ€์ž„์•„์›ƒ(Connection Timeout): ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์„œ๋ฒ„์— ์—ฐ๊ฒฐ์„ ์‹œ๋„ํ•˜๊ณ , ์—ฐ๊ฒฐ์ด ์„ฑ๊ณตํ•  ๋•Œ๊นŒ์ง€์˜ ์‹œ๊ฐ„์„ ์˜๋ฏธํ•œ๋‹ค. ๋„คํŠธ์›Œํฌ ์ƒํƒœ๋‚˜ ์„œ๋ฒ„์˜ ๊ฐ€์šฉ์„ฑ ๋“ฑ์— ๋”ฐ๋ผ ๋ณ€ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์ฝ๊ธฐ ํƒ€์ž„์•„์›ƒ(Read Timeout): ์„œ๋ฒ„์™€ ์—ฐ๊ฒฐ์ด ์„ฑ๊ณตํ•œ ํ›„, ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์‘๋‹ต์„ ๊ธฐ๋‹ค๋ฆฌ๋Š” ์‹œ๊ฐ„์„ ์˜๋ฏธํ•œ๋‹ค. ์™ธ๋ถ€ ์„œ๋น„์Šค์˜ ์ฒ˜๋ฆฌ ์†๋„์— ๋”ฐ๋ผ ๋ณ€ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

 

7. ์บ์‹ฑ ์ฒ˜๋ฆฌ๋ฅผ ๊ณ ๋ คํ•ด๋ผ

์™ธ๋ถ€ API๋กœ๋ถ€ํ„ฐ ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•ด์˜ค๋Š” ๊ฒฝ์šฐ, ํ•ด๋‹น ๋ฐ์ดํ„ฐ๊ฐ€ ์‹ค์‹œ๊ฐ„ ์„ฑ์ด ์ง™์€ ๊ฐ’์ด ์•„๋‹ˆ๋ผ๋ฉด ๋งค๋ฒˆ ์š”์ฒญ์„ ๋ณด๋‚ด๋Š” ๊ฒƒ๋ณด๋‹ค๋Š” ์บ์‹ฑ๋œ ๊ฐ’์„ ์‘๋‹ตํ•˜๋Š” ๊ฒƒ๋„ ์ข‹์€ ๋ฐฉ๋ฒ•์ด๋‹ค. API ์—ฐ๋™ ๊ณผ์ •์„ ์•„๋ฌด๋ฆฌ ์ตœ์ ํ™”ํ•˜๋”๋ผ๋„ ์• ์ดˆ์— ๋ถˆํ•„์š”ํ•œ ํ˜ธ์ถœ์„ ์ค„์ด๋Š” ๊ฒƒ์ด ๊ฐ€์žฅ ํšจ์œจ์ ์ธ ๋ฐฉ๋ฒ•์ผ ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ๋ช…์‹ฌํ•˜์ž.

 

 

8. ์žฌ์‹œ๋„ ์ฒ˜๋ฆฌํ•ด๋ผ

API ํ†ต์‹ ์€ ๋„คํŠธ์›Œํฌ ์ด์Šˆ ๋“ฑ์œผ๋กœ ๊ฐ„ํ—์ ์œผ๋กœ ์‹คํŒจํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฏ€๋กœ ํ•œ ๋ฒˆ์˜ ํ˜ธ์ถœ์ด ์‹คํŒจํ–ˆ์„ ๋•Œ ์ฆ‰์‹œ ์‹คํŒจ ์‘๋‹ต์„ ๋ฐ˜ํ™˜ํ•˜๊ธฐ๋ณด๋‹ค๋Š”, ์ผ์ • ํšŸ์ˆ˜๋งŒํผ ์š”์ฒญ์„ ์žฌ์‹œ๋„ํ•˜๋Š” ๊ฒƒ์ด ๋” ํšจ์œจ์ ์ผ ์ˆ˜ ์žˆ๋‹ค.

Spring์€ ์ด๋Ÿฐ ์žฌ์‹œ๋„ ์ฒ˜๋ฆฌ๋ฅผ ์‰ฝ๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋„๋ก spring-retry ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ RetryTemplate์„ ์ œ๊ณตํ•œ๋‹ค. RestTemplate์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ์—๋Š” RetryTemplate์„ ๊ตฌํ˜„ํ•ด์•ผ ํ•˜๋ฉฐ, WebClient๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ์—๋Š” WebClient ์ž์ฒด์—์„œ ์žฌ์‹œ๋„ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ณ„๋„๋กœ ๊ตฌํ˜„ํ•  ํ•„์š” ์—†์ด ์žฌ์‹œ๋„ ํšŸ์ˆ˜๋งŒ ์ง€์ •ํ•ด ์ฃผ๋ฉด ๋œ๋‹ค. 

์•„๋ž˜๋Š” RestTemplate์™€ WebClient์—์„œ ์žฌ์‹œ๋„ ๋กœ์ง์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค.

@Configuration
class RestTemplateConfig {

    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplateBuilder()
                .setConnectTimeout(Duration.ofSeconds(5))
                .setReadTimeout(Duration.ofSeconds(5))
                .additionalInterceptors(clientHttpRequestInterceptor())
                .build();
    }

    public ClientHttpRequestInterceptor clientHttpRequestInterceptor() {
        return (request, body, execution) -> {
            RetryTemplate retryTemplate = new RetryTemplate();
            retryTemplate.setRetryPolicy(new SimpleRetryPolicy(3));
            try {
                return retryTemplate.execute(context -> execution.execute(request, body));
            } catch (Throwable throwable) {
                throw new RuntimeException(throwable);
            }
        };
    }

}
WebClient webClient = WebClient.create("http://example.com");
webClient.get()
    .uri("/some-data")
    .retrieve()
    .bodyToMono(String.class)
    .retryWhen(Retry.backoff(3, Duration.ofSeconds(1))) // ์žฌ์‹œ๋„ ํšŸ์ˆ˜์™€ ๊ฐ„๊ฒฉ ์„ค์ •
    .subscribe();