๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

Spring

(11)
RestTemplate ํ™•์žฅํ•ด์„œ GET ์š”์ฒญ์—๋„ body ๋„ฃ๊ธฐ Spring์˜ RestTemplate์€ ๊ธฐ๋ณธ์ ์œผ๋กœ GET ์š”์ฒญ์— Body๋ฅผ ๋‹ด์•„๋„ ์ „์†กํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.์ด๋ฒˆ ๊ธ€์—์„œ๋Š” RestTemplate์„ ํ™•์žฅํ•˜์—ฌ GET ์š”์ฒญ ์‹œ Body๋ฅผ ํฌํ•จํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์†Œ๊ฐœํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ์‹œ๋Š” RestTemplate์œผ๋กœ OpenSearch์˜ GET _search API๋ฅผ ํ˜ธ์ถœํ•˜๊ณ , ์‘๋‹ต์„ ๋ฐ›๋Š” ๊ณผ์ •์„ ๋‹ค๋ฃน๋‹ˆ๋‹ค.ํ™•์žฅ ์ „·ํ›„์— Search API๋กœ๋ถ€ํ„ฐ ์–ด๋–ค ์‘๋‹ต์ด ์˜ค๋Š”์ง€๋ฅผ ๋กœ๊ทธ ๋น„๊ต๋ฅผ ํ†ตํ•ด ํ™•์ธํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. OpenSearch์˜ Search API๋Š” ์ฟผ๋ฆฌ๊ฐ€ ๊ธธ์–ด์งˆ ์ˆ˜ ์žˆ์–ด, REST ๊ทœ์•ฝ์— ์–ด๊ธ‹๋‚˜๋”๋ผ๋„ GET ์š”์ฒญ์— Body๋ฅผ ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค.๋‹ค๋งŒ ๋ช…์„ธ์ƒ GET /{index_name}/_search๋ฅผ ์‚ฌ์šฉํ•˜์ง€๋งŒ, POST ์š”์ฒญ๋„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. ์ €๋Š” ์ฒ˜์Œ์— ๋ช…์„ธ๋Œ€๋กœ GET ์š”์ฒญ์„..
Spring AOP ๋กœ ์‚ฌ์šฉ์ž๊ฐ€ ๊ฐ€์ง„ ๊ถŒํ•œ์— ๋”ฐ๋ผ ํŠน์ • ๋ฉ”๋‰ด(๊ธฐ๋Šฅ) ์ ‘์† ์ œํ•œํ•˜๊ธฐ ์‚ฌ๋‚ด ์–ด๋“œ๋ฏผ์„ ๊ฐœ๋ฐœํ•˜๋˜ ์ค‘, ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์š”๊ตฌ์‚ฌํ•ญ์ด ์ƒ๊ฒผ์Šต๋‹ˆ๋‹ค."์‚ฌ์šฉ์ž๊ฐ€ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๊ถŒํ•œ ์™ธ์˜ ๋ฉ”๋‰ด(๊ธฐ๋Šฅ)์€ ์ ‘๊ทผํ•  ์ˆ˜ ์—†๋„๋ก ์ œํ•œํ•ด๋‹ฌ๋ผ." ์ด ์š”๊ตฌ์‚ฌํ•ญ์€ AWS์˜ IAM ๊ธฐ๋Šฅ๋งŒํผ ๋ณต์žกํ•˜์ง„ ์•Š์ง€๋งŒ, ๋งฅ๋ฝ์€ ๋น„์Šทํ•ด์„œ IAM ๊ฐœ๋…์„ ๋นŒ๋ ค ์š”๊ตฌ์‚ฌํ•ญ์„ ์„ค๋ช…๋“œ๋ฆฌ๊ณ ์ž ํ•ฉ๋‹ˆ๋‹ค. IAM์˜ ๊ตฌ์„ฑ์š”์†Œ์™€ ์ ‘๊ทผ ์ œ์–ด ๋ฐฉ์‹IAM์˜ ๊ตฌ์„ฑ ์š”์†Œ ์ค‘ ๊ธ€์„ ์„ค๋ช…ํ•˜๋Š”๋ฐ ํ•„์š”ํ•œ ๊ฐœ๋…์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž (User)AWS ๋ฆฌ์†Œ์Šค์— ๋กœ๊ทธ์ธํ•˜๊ฑฐ๋‚˜ API๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ์ฃผ์ฒด๋กœ, ์‹ค์ œ ์‚ฌ๋žŒ๊ณผ 1:1 ๋งคํ•‘๋ฉ๋‹ˆ๋‹ค.์—ญํ•  (Role)AWS์˜ IAM์˜ ์—ญํ• ์€ ์ผ์‹œ์ ์ธ ๊ถŒํ•œ ์œ„์ž„์„ ์œ„ํ•ด ์กด์žฌํ•˜๋Š” ์ž๊ฒฉ์ž…๋‹ˆ๋‹ค. ์ฆ‰, "์‚ฌ์šฉ์ž๊ฐ€ ์—ญํ• ์„ ๊ฐ–๋Š” ๊ฒƒ"์ด ์•„๋‹ˆ๋ผ, ์‚ฌ์šฉ์ž๋‚˜ AWS ์„œ๋น„์Šค๊ฐ€ ํ•„์š”ํ•  ๋•Œ ์—ญํ• ์„ ๋งก์•„์„œ(๊ฐ€์ •ํ•ด์„œ, Assume), ์—ญํ• ์— ์—ฐ๊ฒฐ๋œ ์ •์ฑ… ๊ถŒ..
MultipartFile ์˜ transferTo ์ดํ›„ getBytes ํ˜ธ์ถœ ์‹œ NoSuchFileException ๋ฐœ์ƒ ์›์ธ ์†Œ๊ฐœ ์„œ๋ก MultipartFile ๊ฐ์ฒด๋ฅผ ๋””์Šคํฌ์— ์ €์žฅํ•˜๊ณ , ํ•ด๋‹น ํŒŒ์ผ์„ ์ž„๋ฒ ๋”ฉํ•˜๊ธฐ ์œ„ํ•ด FastAPI๋กœ ๋ฐ”์ด๋„ˆ๋ฆฌ ๋ฐ์ดํ„ฐ๋ฅผ ์ „์†กํ•ด์•ผ ํ•˜๋Š” ์š”๊ตฌ์‚ฌํ•ญ์„ ๊ตฌํ˜„ ์ค‘์ด์—ˆ์Šต๋‹ˆ๋‹ค.ํŒŒ์ผ์„ ๋””์Šคํฌ์— ์ €์žฅํ•˜๊ธฐ ์œ„ํ•ด transferTo() ๋ฅผ ์‚ฌ์šฉํ–ˆ๊ณ , getBytes() ๋ฅผ ํ†ตํ•ด ๋ฐ”์ด๋„ˆ๋ฆฌ ๋ฐ์ดํ„ฐ๋ฅผ ์–ป์œผ๋ ค ํ–ˆ์ง€๋งŒ, ํŒŒ์ผ์„ ์ฐพ์„ ์ˆ˜ ์—†๋‹ค๋Š” NoSuchFileException ์ด ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.Caused by: java.nio.file.NoSuchFileException: C:\Users\...\Local\Temp\tomcat.28080.5183490430648900766 ๊ฐ™์€ MultipartFile ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ–ˆ์ง€๋งŒ ํŒŒ์ผ์„ ์ฐพ์„ ์ˆ˜ ์—†๋‹ค๋Š” ๊ฒƒ์ด ์ดํ•ด๊ฐ€ ๊ฐ€์งˆ ์•Š์•˜์Šต๋‹ˆ๋‹ค.๊ฒฐ๋ก MultipartFile์€ spring.servlet.mu..
OpenFeign ์—์„œ ISO-8601 ๋‚ ์งœ ํฌ๋งท์„ ์œ„ํ•ด FeignFormatterRegistrar ๋ฅผ ๋“ฑ๋กํ•˜๋Š” ์ด์œ  ๊ฐœ์š”OpenFeign์„ ์‚ฌ์šฉํ•ด admin ์„œ๋ฒ„์™€ core ์„œ๋ฒ„ ๊ฐ„์— HTTP ํ†ต์‹ ์„ ํ•˜๋˜ ์ค‘, ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.admin ์„œ๋ฒ„์—์„œ LocalDate ํƒ€์ž…์„ yyyy-MM-dd ํฌ๋งท์œผ๋กœ ์š”์ฒญ์„ ๋ณด๋ƒˆ์Šต๋‹ˆ๋‹ค.๊ทธ๋Ÿฌ๋‚˜ core ์„œ๋ฒ„์—์„œ๋Š” LocalDate ํฌ๋งท์ด yyyy-MM-dd ๋ฅผ ๊ธฐ๋Œ€ํ–ˆ์ง€๋งŒ, yy. M. d. ์œผ๋กœ ์™€์„œ ํฌ๋งท ๋ณ€ํ™˜์— ์‹คํŒจํ•˜๋Š” ์—๋Ÿฌ ๋กœ๊ทธ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.์ด ๋ฌธ์ œ๋Š” ์šฐ์•„ํ•œํ˜•์ œ๋“ค ๊ธฐ์ˆ  ๋ธ”๋กœ๊ทธ์—์„œ ์ œ์‹œํ•œ ๋ฐฉ์‹์œผ๋กœ ๊ฐ„๋‹จํžˆ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:@Beanpublic FeignFormatterRegistrar localDateFeignFormatterRegister() { return registry -> { DateTimeFormatterRegistrar registrar = new ..
ํŠธ๋žœ์žญ์…˜ ๋กค๋ฐฑ ์‹œ ๊ฒฐ์ œ ์ทจ์†Œ ์š”์ฒญํ•˜๊ธฐ - @TransactionalEventListener & ApplicationEventPublisher ๋ชจํ‚น ์ด์Šˆ ์‚ฌ์ด๋“œ ํ”„๋กœ์ ํŠธ์—์„œ ๊ฒฐ์ œ ํ”„๋กœ์„ธ์Šค๋ฅผ ์„ค๊ณ„ํ•˜๋ฉด์„œ, ๊ธฐ์กด์—๋Š” try-catch๋ฅผ ํ™œ์šฉํ•ด ํŠธ๋žœ์žญ์…˜ ๋‚ด๋ถ€์—์„œ ๋ฐœ์ƒํ•˜๋Š” ๋Ÿฐํƒ€์ž„ ์˜ˆ์™ธ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ณ , ๊ฒฐ์ œ ์ทจ์†Œ ์š”์ฒญ์„ ๋ณด๋ƒˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜, ์ด์— ๋Œ€ํ•œ ํ•œ๊ณ„๋ฅผ ๋А๊ผˆ๊ณ  ํŠธ๋žœ์žญ์…˜ ๋กค๋ฐฑ ์‹œ ๊ฒฐ์ œ ์ทจ์†Œ ์š”์ฒญ์„ ๋ช…ํ™•ํ•˜๊ณ  ์ง๊ด€์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด @TransactionalEventListener๋ฅผ ๋„์ž…ํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ธฐ์กด try-catch ๋ฐฉ์‹์˜ ํ•œ๊ณ„ try-catch์—์„œ๋Š” ์ฃผ๋กœ DB ์˜ˆ์™ธ(์˜ˆ: DataIntegrityViolationException)๋‚˜ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์—์„œ ๋ฐœ์ƒํ•˜๋Š” ์˜ˆ์™ธ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ณ , ๊ฒฐ์ œ ์ทจ์†Œ ์š”์ฒญ์„ ๋ณด๋ƒˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ, try-catch๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์˜ˆ์™ธ๋ฅผ ์ •์ƒ์ ์ธ ํ๋ฆ„์œผ๋กœ ์ œ์–ดํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ด๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์ด๋Š” "ํŠธ๋žœ์žญ์…˜์ด ๋กค๋ฐฑ๋˜์—ˆ์„ ๋•Œ ๊ฒฐ์ œ ์ทจ์†Œ๋ฅผ ์ˆ˜ํ–‰ํ•œ๋‹ค"๋ผ๋Š” ์˜..
[ํŠธ๋Ÿฌ๋ธ”์ŠˆํŒ…] RestTemplate ๋กœ๊น… ์ค‘ 404 ์‘๋‹ต์— ๋Œ€ํ•œ FileNotFoundException ํ•ด๊ฒฐ ๊ฒฐ์ œ ์Šน์ธ POST ์š”์ฒญ ์‹œ RestTemplate ๋กœ๊ทธ์—์„œ ๋ฐœ์ƒํ•œ ์˜ค๋ฅ˜ ๊ฒฐ์ œ ๊ธฐ๋Šฅ์„ ๊ฐœ๋ฐœํ•˜๋ฉด์„œ, ๊ฒฐ์ œ ์Šน์ธ ์š”์ฒญ์„ ๋ณด๋‚ด๋Š” RestTemplate์— ํƒ€์ž„์•„์›ƒ์„ ์ ์šฉํ•˜๊ณ , ์š”์ฒญ๊ณผ ์‘๋‹ต์— ๋Œ€ํ•œ ๋กœ๊น…์„ ์ถ”๊ฐ€ํ•˜๊ณ ์ž ํ–ˆ์Šต๋‹ˆ๋‹ค. Baeldung์˜ "RestTemplage Logging" ๊ณผ ๋ง๋‚˜๋‹ˆ ๊ฐœ๋ฐœ์ž๋‹˜์˜ ๋กœ๊น… ์„ ์ฐธ๊ณ ํ•ด์„œ RestTemplate ์— ๋กœ๊ทธ๋ฅผ ์ถ”๊ฐ€ ํ–ˆ์ง€๋งŒ ์‘๋‹ต์„ ๋ฐ›์„ ๋•Œ, FileNotFoundException ์ด ๋ฐœ์ƒํ•˜๋ฉฐ ์•„๋ž˜์™€ ๊ฐ™์€ ์Šคํƒ ํŠธ๋ ˆ์ด์Šค๋ฅผ ํ™•์ธํ–ˆ์Šต๋‹ˆ๋‹ค.java.io.FileNotFoundException: https://api.tosspayments.com/v1/payments/confirmjava.base/sun.net.www.protocol.http.HttpURLConnection..
@Async ์ด๋ฉ”์ผ ์ „์†ก ๊ณ ๋„ํ™”: ์žฌ์‹œ๋„, ์˜ˆ์™ธ ์ฒ˜๋ฆฌ, ํ…Œ์ŠคํŠธ ์ธ์ฆ ์ด๋ฉ”์ผ ์ „์†ก ์‹œ, ๊ฐ„ํ˜น ๋„คํŠธ์›Œํฌ ์˜ค๋ฅ˜๋กœ ์ธํ•ด ๋ฉ”์ผ์ด ์ •์ƒ์ ์œผ๋กœ ์ „์†ก๋˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.์ด๋Ÿฌํ•œ ์ƒํ™ฉ์—์„œ ์‚ฌ์šฉ์ž์—๊ฒŒ ์ฆ‰์‹œ ์˜ค๋ฅ˜๋ฅผ ์•Œ๋ฆฌ๋Š” ๋Œ€์‹ , ์žฌ์‹œ๋„ ๋กœ์ง์„ ํ†ตํ•ด ์ด๋ฉ”์ผ ์ „์†ก ์„ฑ๊ณต ๊ฐ€๋Šฅ์„ฑ์„ ๋†’์ด๋Š” ๊ฒƒ์ด ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์„ ํ–ฅ์ƒํ•˜๋Š” ์ค‘์š”ํ•œ ์š”์†Œ๋ผ๊ณ  ํŒ๋‹จํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ, ์žฌ์‹œ๋„ ์ถ”๊ฐ€ ์‹œ ๊ณ ๋ คํ•œ ๊ฒƒ๋“ค์„ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ชฉ์ฐจ๋กœ ์†Œ๊ฐœํ•ฉ๋‹ˆ๋‹ค.์žฌ์‹œ๋„(@Retryable) ์กฐ๊ฑด ์„ค์ •์žฌ์‹œ๋„ ์˜ˆ์™ธ์™€ ์“ฐ๋ ˆ๋“œ ํ’€ ์˜ˆ์™ธ๋ฅผ ๊ตฌ๋ถ„ํ•ด์„œ ์ฒ˜๋ฆฌํ•˜๊ธฐ์žฌ์‹œ๋„ ๋ฐ ๋ณต๊ตฌ๊ฐ€ ์ž˜ ๋˜์—ˆ๋Š”์ง€ ํ…Œ์ŠคํŠธํ•˜๊ธฐ* ๋น„๋™๊ธฐ์—์„œ ์žฌ์‹œ๋„ ๋กœ์ง ๊ตฌํ˜„์„ ์œ„ํ•ด Baeldung(async-retry)๋ฅผ ์ฐธ๊ณ ํ–ˆ์Šต๋‹ˆ๋‹ค. ์žฌ์‹œ๋„(@Retryable) ์กฐ๊ฑด ์„ค์ •๋จผ์ €, ์ด๋ฉ”์ผ ์ „์†ก์— ์žฌ์‹œ๋„ ์กฐ๊ฑด์„ ์„ค์ •ํ•˜๊ธฐ ์œ„ํ•ด Spring Mail ๊ด€๋ จ ์˜ˆ์™ธ๋ฅผ ์†Œ๊ฐœํ•ฉ๋‹ˆ๋‹ค.MailAuthentic..
์ด๋ฉ”์ผ ์ „์†ก์„ Async-NonBlocking ์ฒ˜๋ฆฌํ•˜๊ธฐ: ์“ฐ๋ ˆ๋“œ ํ’€ ์„ค์ •๊ณผ API ์ตœ๋Œ€ ์‘๋‹ต ์†๋„ 1.4์ดˆ → 0.01์ดˆ @Async ๋ฅผ ๋„์ž…ํ•˜๋ฉฐ ์ปจํ…์ŠคํŠธ ์Šค์œ„์นญ๊ณผ ์“ฐ๋ ˆ๋“œ ๋ฉ”๋ชจ๋ฆฌ ๊ตฌ์กฐ ์ง€์‹์„ ๋ฐ”ํƒ•์œผ๋กœ ์“ฐ๋ ˆ๋“œ ํ’€ ์„ค์ •์„ ํ•™์Šตํ•˜๊ณ  ์ ์šฉํ•˜๋Š” ๊ณผ์ •์„ ์†Œ๊ฐœํ•˜๋ฉฐ Jmeter ๋ฅผ ํ†ตํ•ด API ์‘๋‹ต ์†๋„๊ฐ€ ๊ฐœ์„ ๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•˜๋Š” ๊ณผ์ •์„ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ชฉ์ฐจ๋กœ ์†Œ๊ฐœํ•ฉ๋‹ˆ๋‹ค.์ด๋ฉ”์ผ ์ „์†ก์„ ๋น„๋™๊ธฐ๋กœ ๊ฒฐ์ •ํ•œ ์ด์œ ์“ฐ๋ ˆ๋“œ ํ’€ ์‚ฌ์šฉ ์—ฌ๋ถ€ ๊ณ ๋ ค์“ฐ๋ ˆ๋“œ ํ’€ ์„ค์ • ๊ณ ๋ ค ์‚ฌํ•ญ์“ฐ๋ ˆ๋“œ ํ’€ ์„ค์ •ThreadPoolTaskExecutor ๋™์ž‘ ๋ฐฉ์‹์“ฐ๋ ˆ๋“œ ํ’€ ์˜ค๋ฅ˜ ์ฒ˜๋ฆฌ ์„ค์ •Jmeter ๋กœ @Async ๋„์ž… ์ ์šฉ ์ „๊ณผ ํ›„์˜ API ์‘๋‹ต ์‹œ๊ฐ„์„ ๋น„๊ต@Async ์‚ฌ์šฉ ์‹œ ์ฃผ์˜์  ์ด๋ฉ”์ผ ์ „์†ก์„ ๋น„๋™๊ธฐ๋กœ ๊ฒฐ์ •ํ•œ ์ด์œ ์—์–ด๋น„์•ค๋น„ ํด๋ก  ํ”„๋กœ์ ํŠธ์—์„œ๋Š” ์ด๋ฉ”์ผ ์ธ์ฆ ๊ธฐ๋ฐ˜์˜ ํšŒ์›๊ฐ€์ž…/๋กœ๊ทธ์ธ์„ ์ง„ํ–‰ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฉ”์ผ ์ „์†ก์—๋Š” Spring Mail์˜ JavaMailSender๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์œผ๋ฉฐ..