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

์ „์ฒด ๊ธ€

(64)
Spring Boot์˜ Graceful Shutdown ์–ด๋””๊นŒ์ง€ ์•Œ๊ณ ์žˆ๋‚˜์š”? (SmartLifeCycle, Phased ์™€ ํ•จ๊ป˜ timeout-per-shutdown-phase ์˜คํ•ด ๋ฐ”๋กœ์žก๊ธฐ) ์ด ๊ธ€์—์„œ๋Š” Graceful Shutdown์„ "์šฐ์•„ํ•œ ์ข…๋ฃŒ"๋กœ ์–ธ๊ธ‰ํ•ฉ๋‹ˆ๋‹ค. 1. ์šฐ์•„ํ•œ ์ข…๋ฃŒ ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ ์„ค์ • ์šฐ์•„ํ•œ ์ข…๋ฃŒ ํ…Œ์ŠคํŠธ๋Š” IDE์—์„œ ์‹คํ–‰ ์‹œ ์›ํ™œํ•˜๊ฒŒ ๋™์ž‘ํ•˜์ง€ ์•Š๋Š”๋‹ค๊ณ  ์„ค๋ช…๋˜์–ด ์žˆ์–ด, Linux ์„œ๋ฒ„์—์„œ jar๋ฅผ ์ˆ˜๋™์œผ๋กœ ์ข…๋ฃŒํ•˜๋ฉฐ ํ…Œ์ŠคํŠธ๋ฅผ ์ง„ํ–‰ํ–ˆ์Šต๋‹ˆ๋‹ค.Using graceful shutdown with your IDE may not work properly if it does not send a proper SIGTERM signal. See the documentation of your IDE for more details. 1.1 application.yml ์„ค์ • application.yml์— ์šฐ์•„ํ•œ ์ข…๋ฃŒ๋ฅผ ์„ค์ •ํ•˜์˜€์Šต๋‹ˆ๋‹ค. ์Šคํ”„๋ง ๋ถ€ํŠธ 3.4๋ถ€ํ„ฐ๋Š” ์šฐ์•„ํ•œ ์ข…๋ฃŒ๊ฐ€ ๊ธฐ๋ณธ์œผ๋กœ ์„ค์ •๋˜๋ฉฐ, ..
Disk I/O ๋ฐ”์šด๋“œ ์„œ๋ฒ„๋ฅผ ์œ„ํ•œ ํŽ˜์ด์ง€ ์บ์‹œ(Page Cache) "์›น ๊ฐœ๋ฐœ์ž๋ฅผ ์œ„ํ•œ ๋Œ€๊ทœ๋ชจ ์„œ๋น„์Šค๋ฅผ ์ง€ํƒฑํ•˜๋Š” ๊ธฐ์ˆ "์˜ ๋‚ด์šฉ์„ ์žฌ๊ตฌ์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค. ํŽ˜์ด์ง€ ์บ์‹œ๋ž€?OS๋Š” ๋””์Šคํฌ ์•ก์„ธ์Šค๋ฅผ ์ค„์ด๊ธฐ ์œ„ํ•ด ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ™œ์šฉํ•ฉ๋‹ˆ๋‹ค.ํ”„๋กœ์„ธ์Šค A๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ๊ณ  ๋‚œ ํ›„, ๋” ์ด์ƒ ๊ทธ ๋ฐ์ดํ„ฐ๊ฐ€ ํ•„์š” ์—†์–ด์กŒ๋‹ค๊ณ  ํ•ด์„œ OS๋Š” ๋ฉ”๋ชจ๋ฆฌ์—์„œ ๋ฐ”๋กœ ํ•ด์ œํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.๋ฉ”๋ชจ๋ฆฌ์— ๋ฐ์ดํ„ฐ๋ฅผ ๊ทธ๋Œ€๋กœ ๋‚จ๊ฒจ๋‘๋Š”๋ฐ, ์ด๊ฒƒ์ด ๋ฐ”๋กœ ํŽ˜์ด์ง€ ์บ์‹œ์ž…๋‹ˆ๋‹ค. ์ด ๋•๋ถ„์— ํ”„๋กœ์„ธ์Šค B๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ํ•„์š”ํ•  ๋•Œ ๋””์Šคํฌ๋ฅผ ๋‹ค์‹œ ์ฝ์ง€ ์•Š๊ณ  ๋ฉ”๋ชจ๋ฆฌ์—์„œ ๋ฐ”๋กœ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. * OS์˜ ํŒŒ์ผ ์‹œ์Šคํ…œ๋งˆ๋‹ค ๋””์Šคํฌ ์ฝ๋Š” ๋ฐฉ๋ฒ•์ด ๋‹ค๋ฅผํ…๋ฐ?๋ฆฌ๋ˆ…์Šค์—๋Š” ext3, ext2 ๊ฐ™์€ ์—ฌ๋Ÿฌ ํŒŒ์ผ ์‹œ์Šคํ…œ์ด ์žˆ๊ณ  ๊ฐ๊ฐ ๋””์Šคํฌ๋ฅผ ์ฝ๋Š” ๋ฐฉ๋ฒ•์ด ๋‹ค๋ฅด์ง€๋งŒ, VFS(Virtual File System)๊ฐ€ ์–ด๋–ค ํŒŒ์ผ ์‹œ์Šคํ…œ์„ ์‚ฌ์šฉํ•˜๋“  ํŽ˜์ด์ง€ ์บ์‹œ๋ฅผ ๋™์ผํ•˜๊ฒŒ ์ œ๊ณตํ•ด์ค€๋‹ค๊ณ ..
search_after API ๋กœ OpenSearch์—์„œ 10,000๊ฑด ์ด์ƒ Pagination ์•ˆ๋˜๋Š” ๋ฌธ์ œ ํ•ด๊ฒฐํ•˜๊ธฐ best practice ๊ฐ€ ์•„๋‹ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ฐธ๊ณ  ํ•ด์ฃผ์‹œ๋ฉด ๊ฐ์‚ฌํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.๋ฌธ์ œ ์ƒํ™ฉOpenSearch์—์„œ from๊ณผ size๋ฅผ ํ™œ์šฉํ•ด ํŽ˜์ด์ง• ์ฟผ๋ฆฌ๋ฅผ ์š”์ฒญํ•˜๋˜ ์ค‘, ๋ฐ์ดํ„ฐ๊ฐ€ 10,000๊ฑด์„ ๋„˜์–ด๊ฐ€๋ฉด์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค."Result window is too large, from + size must be less than or equal to: [10000] but was [10008]. See the scroll api for a more efficient way to request large data sets. This limit can be set by changing the [index.max_result_window] index level setting."OpenSearch(El..
Cloud OpenFeign ์˜ ์žฌ์‹œ๋„๋Š” ์–ธ์ œ ๋™์ž‘ํ• ๊นŒ? Retryer.Default ๋™์ž‘ ์›๋ฆฌ์™€ ํ…Œ์ŠคํŠธ README WireMock์— ๋Œ€ํ•œ ์„ค๋ช…์ด ๋ถ€์กฑํ•˜๋ฉฐ, WireMock์„ ์•Œ๊ณ  ์žˆ๋Š” ๊ฐ€์ • ํ•˜์— ์ง„ํ–‰๋ฉ๋‹ˆ๋‹ค. WireMock์— ๋Œ€ํ•œ ์„ค๋ช…์€ ์•„๋ž˜๋ฅผ ์ฐธ๊ณ ํ•ด์ฃผ์„ธ์š”. - Spring Cloud Contract WireMock Docs- Baeldung ์˜ Introduction WireMock- ์šฐ์•„ํ•œ๊ธฐ์ˆ ๋ธ”๋กœ๊ทธ : ์•ผ, ๋„ˆ๋‘ WireMock ์œผ๋กœ ํ…Œ์ŠคํŠธํ•  ์ˆ˜ ์žˆ์–ด Cloud OpenFeign ์— ์žฌ์‹œ๋„๋ฅผ ์œ„ํ•ด Retryer.Default ๋ฅผ ๋นˆ์œผ๋กœ ๋“ฑ๋กํ–ˆ์„ ๋•Œ ์•„๋ž˜ 2๊ฐ€์ง€ ๊ฒฝ์šฐ ์‹œ ์žฌ์‹œ๋„๋ฅผ ํ•˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•˜๊ณ  ํ…Œ์ŠคํŠธ ํ•˜๋Š” ๊ณผ์ •์„ ์†Œ๊ฐœํ•ฉ๋‹ˆ๋‹ค.1. IOException ๋ฐœ์ƒ ์‹œ, ์žฌ์‹œ๋„2. ์‘๋‹ต์— Retry-After ํ—ค๋”๊ฐ€ ์žˆ์–ด์„œ RetryableException์ด ๋ฐœ์ƒํ•  ๋•Œ, ์žฌ์‹œ๋„ ์„œ๋ก : Feig..
์ƒ๊ด€ ์„œ๋ธŒ์ฟผ๋ฆฌ๋ฅผ ๊ฐœ์„ ํ•˜์—ฌ API ์‘๋‹ต 2.5์ดˆ์—์„œ 0.2์ดˆ๋กœ ๊ฐœ์„ ํ•˜๊ธฐ ์„œ๋ก  ์•ฝ 2.5์ดˆ๊ฐ€ ๊ฑธ๋ฆฌ๋˜ ๋Œ€ํ™” ๋ชฉ๋ก ์กฐํšŒ API์˜ ์‘๋‹ต ์‹œ๊ฐ„์„ 0.2์ดˆ๋กœ ๊ฐœ์„ ํ•˜๋ฉฐ ๋ฐฐ์šด ์ƒ๊ด€ ์„œ๋ธŒ์ฟผ๋ฆฌ์™€ Hash Join, Nested Loop Join ์˜ ํŠน์ง•์„ ๊ณต์œ ํ•ฉ๋‹ˆ๋‹ค.๋ฌธ์ œ๋Œ€ํ™” ๋ชฉ๋ก ์กฐํšŒ API๋ฅผ Postman์œผ๋กœ ํ…Œ์ŠคํŠธํ•œ ๊ฒฐ๊ณผ, ์‘๋‹ต ์‹œ๊ฐ„์ด ์•ฝ 2.5์ดˆ๋‚˜ ๊ฑธ๋ ธ์Šต๋‹ˆ๋‹ค. ์›์ธ ํŒŒ์•… ํ•ด๋‹น API๋Š” DB ์ ‘๊ทผ์„ ์ด 3๋ฒˆ ํ•˜๋Š” ๊ตฌ์กฐ์˜€๊ธฐ์— ๋ณ‘๋ชฉ ์ง€์ ์„ ๋น ๋ฅด๊ฒŒ ํŒŒ์•…ํ•˜๊ธฐ ์œ„ํ•ด IntelliJ Profiler๋กœ ๊ฐ ์ฟผ๋ฆฌ์˜ ์‹คํ–‰ ์‹œ๊ฐ„์„ ์ธก์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.์ธก์ • ๊ฒฐ๊ณผ์ฒซ ๋ฒˆ์งธ ์ฟผ๋ฆฌ๋Š” ์•„๋ž˜ ์‚ฌ์ง„์˜ ์กฐํšŒ ์กฐ๊ฑด 5๊ฐ€์ง€(๊ฒ€์ƒ‰์–ด, ์„œ๋น„์Šค, ์นดํ…Œ๊ณ ๋ฆฌ ๋ช…, ์‚ฌ์šฉ์ž ๋ฐ˜์‘, ๋Œ€ํ™”์ผ์ž)๋ฅผ ํ•„ํ„ฐ๋งํ•ด์„œ ํŽ˜์ด์ง€ ๋‹น ๋ณด์—ฌ์ค„ ๋Œ€ํ™” UUID 10๊ฐœ๋ฅผ ์ถ”์ถœํ•˜๋Š” ์ฟผ๋ฆฌ๋กœ, 102ms ๊ฐ€ ๊ฑธ๋ ธ์Šต๋‹ˆ๋‹ค. ๋‘ ๋ฒˆ์งธ ์ฟผ๋ฆฌ๋Š” ์•„๋ž˜ ์‚ฌ์ง„์˜ ๋Œ€ํ™” UUID ๋งˆ๋‹ค ์‚ฌ์šฉ์ž ..
๋ณต์žกํ•จ ๋Œ€์‹  ๋‹จ์ˆœํ•จ ์ถ”๊ตฌํ•˜๊ธฐ - RestTemplate ํ™•์žฅ ๋˜๋Œ๋ฆฌ๊ธฐ ๊ธฐ๋Šฅ ๊ตฌํ˜„ ์ค‘, RestTemplate์œผ๋กœ OpenSearch์˜ GET _search API๋ฅผ ํ˜ธ์ถœํ•˜๊ณ , ์‘๋‹ต์„ ๋ฐ›์•„์•ผ ํ–ˆ์Šต๋‹ˆ๋‹ค. OpenSearch์˜ Search API๋Š” ์ฟผ๋ฆฌ๊ฐ€ ๊ธธ์–ด์งˆ ์ˆ˜ ์žˆ์–ด, HTTP ๊ทœ์•ฝ์— ์–ด๊ธ‹๋‚˜๋”๋ผ๋„ GET ์š”์ฒญ์— Body๋ฅผ ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ €๋Š” ์ฒ˜์Œ์— _search API ๋ช…์„ธ๋Œ€๋กœ GET + body์š”์ฒญ์„ ์‚ฌ์šฉํ–ˆ์ง€๋งŒ, RestTemplate์ด GET์— Body๋ฅผ ๋‹ด์•„์ฃผ์ง€ ์•Š๋Š”๋‹ค๋Š” ์‚ฌ์‹ค์„ ๊นจ๋‹ซ๊ณ  GET + body ์š”์ฒญ์„ ์œ„ํ•œ RestTemplate ํ™•์žฅ ์ž‘์—…์„ ์ง„ํ–‰ํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜, OpenSearch ๋Š” HTTP ๊ทœ์•ฝ์„ ์œ„ํ•ด _search API ๋ฅผ GET ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ POST ๋„ ์ง€์›ํ•˜๋Š” ๊ฒƒ์„ ์•Œ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.๊ทธ ๊ณผ์ •์—์„œ ๋ฐฐ์šด "๋ณต์žกํ•จ ๋ณด๋‹ค๋Š” ๋‹จ์ˆœํ•จ"์„, ๊ทธ๋ฆฌ๊ณ  RestTem..
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..