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

์ „์ฒด ๊ธ€

(49)
Spring Rest Docs ๋„์ž… ์‹œ, Maven๊ณผ Asciidoctor ๋ฌธ๋ฒ•์ด ํ—ท๊ฐˆ๋ฆฌ๋Š” ๋ถ„๋“ค์„ ์œ„ํ•œ pom.xml ์„ค๋ช… Spring Rest Docs๋ฅผ ๊ฒ€์ƒ‰ํ–ˆ์„ ๋•Œ, Maven์— ๋„์ž…ํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•œ pom.xml ์„ค๋ช…์ด ๋ถ€์กฑํ•˜๋‹ค๊ณ  ๋Š๊ผˆ์Šต๋‹ˆ๋‹ค.๊ทธ๋ž˜์„œ ์ด๋ฒˆ ๊ธ€์—์„œ๋Š” Spring Boot์™€ Maven(3.9.9 ๋ฒ„์ „) ํ™˜๊ฒฝ์—์„œ Spring Rest Docs๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ pom.xml ์„ค์ • ๋ฐฉ๋ฒ•์„ ์ •๋ฆฌํ•˜๊ณ , ๊ทธ ๊ณผ์ •์—์„œ Maven ์˜ ๋ฌธ๋ฒ•๋„ ํ•จ๊ป˜ ํ•™์Šตํ•ด๋ณด๋ ค ํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ, pom.xml ์„ค์ • ๊ฐ’๋“ค์ด Asciidoctor์™€ Maven ์ค‘ ๋ˆ„๊ตฌ์˜ ์„ค์ • ๊ฐ’์ธ์ง€ ์ดํ•ดํ•˜๋Š” ๊ฒƒ์ด ์ด ๊ธ€์˜ ๋ชฉํ‘œ์ž…๋‹ˆ๋‹ค.  ๋˜ํ•œ, ์•„๋ž˜ ๊ทธ๋ฆผ๊ณผ ๊ฐ™์€ ๊ฒฐ๊ณผ์ฒ˜๋Ÿผ *.adoc ํŒŒ์ผ์„ HTML๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ .jar ํŒŒ์ผ์— ํฌํ•จ์‹œํ‚ค๊ณ , *.adoc ํŒŒ์ผ์€ ๋„๋ฉ”์ธ๋ณ„๋กœ ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ๋‚˜๋ˆ„์–ด ๊ด€๋ฆฌํ•˜๋Š” ๋ฐฉ์‹๋„ ํ•จ๊ป˜ ๊ตฌํ˜„ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.1. Spring Rest Docs 3.0.3 ..
์ˆ˜์Šต๊ณผ์ œ ๊ฒŒ์‹œํŒ ๊ตฌํ˜„ํ•˜๋ฉฐ ๋‚˜๋Š” ๋ฌด์—‡์„ ๋ฐฐ์› ๋‚˜? ์ˆ˜์Šต๊ธฐ๊ฐ„ 4์ฃผ ๋™์•ˆ '๊ฒŒ์‹œํŒ ๋งŒ๋“ค๊ธฐ' ๊ณผ์ œ๋ฅผ ๋ถ€์—ฌ๋ฐ›์•˜๋‹ค. ์ด ๊ธ€์€ ๊ณผ์ œ๋ฅผ ์ง„ํ–‰ํ•˜๋ฉฐ ๋‚˜๋Š” 1๋‹ฌ์ด๋ผ๋Š” ๊ธด ์‹œ๊ฐ„ ๋™์•ˆ ๋ฌด์—‡์„ ๋ฐฐ์› ๋Š”์ง€ ์ •๋ฆฌํ•˜๊ณ ์ž ํ•œ๋‹ค. ํ”„๋กœ์ ํŠธ ๊ธฐ์ˆ  ์Šคํƒํ”„๋ก ํŠธ์—”๋“œ: ํผ๋ธ”๋ฆฌ์‹ฑ์— JavaScript๋ฅผ ๋ง๋ถ™์—ฌ Ajax ์š”์ฒญ๋ฐฑ์—”๋“œ: Spring Boot, Spring Security, JDBC Template, ThymeleafDB: MySQL๋นŒ๋“œ: MavenAPI ๋ฌธ์„œ: Rest Docs๊ตฌํ˜„ํ•œ ๊ธฐ๋Šฅ์€ ํฌ๊ฒŒ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.์‚ฌ์šฉ์ž, ๊ฒŒ์‹œ๊ธ€, ๋Œ“๊ธ€/๋‹ต๊ธ€, ๊ด€๋ฆฌ์ž CRUD ๊ฒŒ์‹œ๊ธ€ ํŽ˜์ด์ง•, ๊ฒ€์ƒ‰, ์ถœ๋ ฅ ๊ฑด์ˆ˜ ์กฐ๊ฑด๋™์˜์ƒ 1๊ณผ 2๋Š” ๊ฒฐ๊ณผ๋ฌผ์ด๋‹ค.๋™์˜์ƒ 1. ๊ฒŒ์‹œํŒ ํ™ˆ ํ™”๋ฉด ๋™์˜์ƒ 2์˜ ๋กœ๊ทธ์ธํ•œ ์‚ฌ์šฉ์ž๋Š” ๊ด€๋ฆฌ์ž ๊ถŒํ•œ์„ ๊ฐ€์ง„ ์‚ฌ์šฉ์ž๋กœ ๋‹ค๋ฅธ ์‚ฌ์šฉ์ž์˜ ๋ชจ๋“  ๋Œ“๊ธ€/๋‹ต๊ธ€์„ ์‚ญ์ œํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ์ˆ˜์ •์€ ๋ถˆ๊ฐ€ํ•˜๋‹ค.๋™์˜์ƒ 2. ๊ฒŒ..
์ฝ”๋“œ๋กœ ์•Œ์•„๋ณด๋Š” Spring Data Redis์˜ @Cacheable ๋™์ž‘ ์›๋ฆฌ์™€ ํŠธ๋žœ์žญ์…˜์—์„œ @CachePut/@CacheEvict ์‹คํ–‰ ์‹œ์  ๊ธ€์˜ ๋ชฉํ‘œSpring Data Redis์—์„œ @Cacheable ๋ฉ”์„œ๋“œ๋ฅผ ์‹คํ–‰ํ•˜๊ณ , ์บ์‹œ ๋ฏธ์Šค(Cache miss)๋กœ ์ธํ•ด ๋ฐ˜ํ™˜๊ฐ’์ด ์บ์‹œ์— ์ €์žฅ๋˜๋Š” ๊ณผ์ •. ๊ทธ๋ฆฌ๊ณ , @Transactional๊ณผ ํ•จ๊ป˜ @CachePut/@CacheEvict๋ฅผ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ @CachePut/@CacheEvict๊ฐ€ ์–ธ์ œ ์‹คํ–‰๋˜๋Š”์ง€๋ฅผ ๋‚ด๋ถ€ ๊ตฌํ˜„์„ ํ†ตํ•ด ์•„๋Š” ๊ฒƒ์ด ๋ชฉํ‘œ์ž…๋‹ˆ๋‹ค. ๋ณธ ๊ธ€์€ RedisCache์— ํ•œ์ •๋œ ๋‚ด์šฉ์ž„์„ ๋ฏธ๋ฆฌ ์•Œ๋ ค๋“œ๋ฆฝ๋‹ˆ๋‹ค. Spring Cache ์ถ”์ƒํ™” ๊ตฌ์กฐ Spring Cache๋Š” Cache ์ธํ„ฐํŽ˜์ด์Šค์™€ CacheManager ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ†ตํ•ด ์ถ”์ƒํ™”๋ฉ๋‹ˆ๋‹ค This abstraction is materialized by the org.springframework.cache.Cache and org.springf..
RedisTemplate ๋‚ด๋ถ€ ํƒ๊ตฌ: Spring Data Redis๋Š” Lettuce๋ฅผ ์–ด๋–ป๊ฒŒ ์ถ”์ƒํ™”ํ–ˆ๋Š”๊ฐ€? Lettuce ๊ฐ€ ๋ฌด์—‡์ธ์ง€, Spring Data Redis์˜ RedisTemplate ์€ Lettuce ๋ฅผ ์–ด๋–ป๊ฒŒ ์ถ”์ƒํ™”ํ–ˆ๋Š”์ง€ ์•Œ์•„๋ณด๊ณ ์ž ํ•ฉ๋‹ˆ๋‹ค. ๋จผ์ €, Spring Data Redis ๋Š” Lettuce์™€ Jedis ๋ผ๋Š” 2๊ฐœ์˜ ์˜คํ”ˆ ์†Œ์Šค ๋ผ์ด๋ธŒ๋Ÿฌ์™€ ํ†ตํ•ฉ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.Spring Data Redis integrates with Lettuce and Jedis, two popular open-source Java libraries for Redis. Lettuce์™€ Jedis๋Š” "Java์—์„œ Redis์— ์ ‘๊ทผํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฅผ ์ฃผ๊ณ ๋ฐ›์„ ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ฃผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ"์ž…๋‹ˆ๋‹ค.๊ทธ๋ ‡๋‹ค๋ฉด ๊ฐ๊ฐ ๋ฌด์—‡์ธ์ง€ Lettuce๋ถ€ํ„ฐ ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.Lettuce ๋ž€?Lettuce is a scalable thread-safe Redi..
[ํšŒ๊ณ ] 2024๋…„ ํ•œ ํ•ด๋™์•ˆ ์ฝ์€ ์ฑ… ์˜ค๋ธŒ์ ํŠธ๊ฐ์ฒด์ง€ํ–ฅ์„ ๊ณต๋ถ€ํ•œ๋‹ค๋ฉด ๋น ์งˆ ์ˆ˜ ์—†๋Š” ์ฑ…, ใ€Š์˜ค๋ธŒ์ ํŠธใ€‹๋ฅผ ์ฝ์—ˆ๋‹ค. "์—ญํ• ,์ฑ…์ž„,ํ˜‘๋ ฅ" ์„ ์–ด๋–ป๊ฒŒ ๊ตฌํ˜„ํ•˜์ง€?์ฒ˜์Œ ์ฝ์„ ๋•Œ๋Š” Spring์„ ์‚ฌ์šฉํ•ด ๋ณธ ์ ์ด ์—†์–ด ์˜ˆ์ œ์กฐ์ฐจ ์ดํ•ดํ•˜๊ธฐ ์–ด๋ ค์› ๋‹ค. ์—ญํ• , ์ฑ…์ž„, ํ˜‘๋ ฅ์— ๋Œ€ํ•œ ๊ฐœ๋…์„ ๊ธ€๋กœ๋งŒ ์ฝ์—ˆ์„ ๋ฟ, ์‹ค์ œ ์ฝ”๋“œ๋กœ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ์€ ๊ฐ์ด ์˜ค์ง€ ์•Š์•˜๋‹ค. ๋‘ ๋ฒˆ์งธ ์ฝ์„ ๋•Œ๋Š” ์—ญํ• , ์ฑ…์ž„, ํ˜‘๋ ฅ์˜ ๊ฐœ๋…์„ ์ดํ•ดํ•  ์ˆ˜ ์žˆ์—ˆ์ง€๋งŒ, "๋ฉ”์‹œ์ง€๋ฅผ ๋ˆ„๊ฐ€ ์š”์ฒญํ•˜๊ณ , ์–ด๋””๋กœ ๋ณด๋‚ด์•ผ ํ• ๊นŒ?" ๊ฐ™์€ ๊ตฌํ˜„ ๋ ˆ๋ฒจ์˜ ๊ณ ๋ฏผ์ด ๋‚จ์•˜๋‹ค. ๋‹คํ–‰ํžˆ ์ฑ…์—์„œ๋Š” ์ •๋ณด ์ „๋ฌธ๊ฐ€ ํŒจํ„ด์„ ํ™œ์šฉํ•ด ์‰ฝ๊ฒŒ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์†Œ๊ฐœํ•œ๋‹ค. ๋•๋ถ„์— ๊ตฌํ˜„์— ๋Œ€ํ•œ ๊ฐ๊ฐ์„ ์กฐ๊ธˆ์”ฉ ์ตํž ์ˆ˜ ์žˆ์—ˆ๋‹ค. ์„ค๊ณ„์™€ ๊ตฌํ˜„๊ฐ„์˜ ์ดํ•ด ๊ฐ„๊ทน์„ ์ขํžˆ๊ธฐ ์œ„ํ•ด ์ฑ…์„ ๋ฐ˜๋ณตํ•ด์„œ ์ฝ์„์ˆ˜๋ก, ํ˜‘๋ ฅ์ด ์•„๋‹Œ ๋ฉ”์‹œ์ง€๋ถ€ํ„ฐ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ์ด ํŽธํ•˜๋‹จ ๊ฒƒ์„ ๋Š๋ผ๊ฒŒ ๋˜์—ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ ,..
CompletableFuture๋ฅผ ํ™œ์šฉํ•ด ์™ธ๋ถ€ API ํ˜ธ์ถœ์„ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ, ์‘๋‹ต ์‹œ๊ฐ„ 1๋ถ„ โ†’ 14์ดˆ๋กœ ๋‹จ์ถ• ๋ฌธ์ œ ์ƒํ™ฉํ”„๋กœ์ ํŠธ QA์‹œ, ์ฃผ๊ฐ„ ๋ฆฌํฌํŠธ ๊ธฐ๋Šฅ์˜ ์‘๋‹ต ์‹œ๊ฐ„์ด ์‚ฌ์šฉ์ž 1๋ช…๋‹น ์ตœ์•…์˜ ๊ฒฝ์šฐ 2๋ถ„ ์ด์ƒ, ๋Œ€์ฒด๋กœ ํ‰๊ท  1๋ถ„ ์ด์ƒ ์†Œ์š”๋˜๋Š” ๋ฌธ์ œ๊ฐ€ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.   ์ด ๋ฌธ์ œ๋ฅผ ๋ถ„์„ํ•œ ๊ฒฐ๊ณผ, DB ์ฟผ๋ฆฌ๋Š” ์‹คํ–‰ ๊ณ„ํš์ƒ eq_ref ์™€ ref๋กœ ๋น ๋ฅด๊ฒŒ ์ฒ˜๋ฆฌ๋˜๊ณ  ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.์‘๋‹ต ์‹œ๊ฐ„์ด ๊ธธ์–ด์ง„ ์ฃผ์š” ์›์ธ์€ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์—์„œ ์ตœ๋Œ€ 7๋ฒˆ์˜ ์™ธ๋ถ€ API ํ˜ธ์ถœ์„ ๋™๊ธฐ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด์—ˆ์Šต๋‹ˆ๋‹ค.  ์•„๋ž˜ ์ฝ”๋“œ์ฒ˜๋Ÿผ, stream() ๋‚ด๋ถ€์—์„œ ์—ฐ์†์ ์ธ ์™ธ๋ถ€ API ํ˜ธ์ถœ์„ ์ฒ˜๋ฆฌํ•˜๋ฉด์„œ ์ผ์ผ ์„œ๋น„์Šค์™€ Clova AI๊ฐ€ ๋™๊ธฐ์ ์œผ๋กœ ์š”์ฒญ๊ณผ ์‘๋‹ต์„ ์ฃผ๊ณ ๋ฐ›๋Š” ๊ตฌ์กฐ๋กœ ๋™์ž‘ํ•˜๊ณ  ์žˆ์—ˆ๊ณ , ์ด๋ฅผ ๊ฐœ์„ ํ•˜๊ณ ์ž ํ–ˆ์Šต๋‹ˆ๋‹ค.Map> valuesByKey = map.values().stream() ์™ธ๋ถ€ API ํ˜ธ์ถœ, ..
์™œ ๋‚ด CompletableFuture ๋Š” Console ์— ๋กœ๊ทธ๊ฐ€ ์—†๋Š”๊ฐ€? ForkJoinPool ์˜ ๋ฐ๋ชฌ ์Šค๋ ˆ๋“œ๋ฅผ ์•Œ์•„๋ณด์ž CompletableFuture๋ฅผ ํ™œ์šฉํ•œ ๋น„๋™๊ธฐ์—์„œ ์ฝ˜์†”์— ๋กœ๊ทธ๊ฐ€ ๋‚จ์ง€ ์•Š๋Š” ๋ฌธ์ œ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•ด CompletableFuture ์‚ฌ์šฉ๋ฒ•์„ ์ตํžˆ๋Š” ์ค‘, ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ ๋กœ์ง(Task ํด๋ž˜์Šค์˜ doAsyncWithForkJoinPool( ))์—์„œ ์ฝ˜์†”์— ๋กœ๊ทธ๊ฐ€ ๋‚จ์ง€ ์•Š๋Š” ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด์— ๋Œ€ํ•ด ์•Œ์•„๋ณด๊ณ ์ž ํ•ฉ๋‹ˆ๋‹ค. ๋ฌธ์ œ๊ฐ€ ๋˜์—ˆ๋˜ ์ฝ”๋“œ๋กœ ์‹คํ–‰ ๊ฒฐ๊ณผ๋Š” "๋ฉ”์ธ ์ข…๋ฃŒ" ๋งŒ ๋‚˜์˜ฌ ๋ฟ, Thread.currentThread().getName() ๊ด€๋ จ ๋กœ๊ทธ๋Š” ์ฝ˜์†”์— ๋‚˜์˜ค์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.// Main ํด๋ž˜์Šคpublic static void main(String[] args) { Task task = new Task(); CompletableFuture future = task.doAsyncWit..
์™ธ๋ถ€ API ํ˜ธ์ถœ์„ ํŠธ๋žœ์žญ์…˜์—์„œ ๋ถ„๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด FACADE ๊ณ„์ธต์„ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด, OSIV ํ™œ์„ฑํ™” ์—ฌ๋ถ€๋ฅผ ๊ณ ๋ คํ•˜์ž! ๋ฌธ์ œ ์ƒํ™ฉ: ์„œ๋กœ ๋‹ค๋ฅธ ํŠธ๋žœ์žญ์…˜์—์„œ ์—”ํ‹ฐํ‹ฐ ๋ณ€๊ฒฝ ์‹œ ๋ณ€๊ฒฝ๊ฐ์ง€๊ฐ€ ์ž‘๋™ํ•˜๋Š”๊ฐ€? ์™ธ๋ถ€ API ํ˜ธ์ถœ์„ ํŠธ๋žœ์žญ์…˜์—์„œ ๋ถ„๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด FACADE ํŒจํ„ด์„ ๋„์ž…ํ–ˆ์Šต๋‹ˆ๋‹ค.3๊ฐœ์˜ ์„œ๋น„์Šค๋ฅผ ๋ฆฌํŒฉํ† ๋งํ•˜๋ฉฐ, ํŠธ๋žœ์žญ์…˜ ๋ฒ”์œ„ ๋ฐ–์—์„œ ์™ธ๋ถ€ API๋ฅผ ํ˜ธ์ถœํ•˜๋„๋ก ์„ค๊ณ„ํ•˜์˜€๊ณ , ์ฝ”๋“œ ๊ตฌ์กฐ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์•˜์Šต๋‹ˆ๋‹ค. // ํŠธ๋žœ์žญ์…˜์—์„œ ์™ธ๋ถ€ API ํ˜ธ์ถœ์„ ๋ถ„๋ฆฌํ•˜๊ณ ์ž ๋งŒ๋“  Facade ๊ฐ์ฒดpublic class Facade { private final Service1 service1; private final Service2 service2; public ... createSomething(...) { // 1๋ฒˆ ์„œ๋น„์Šค ํŠธ๋žœ์žญ์…˜ ์‹œ์ž‘ EntityA entityA = service1.doSomething(....