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

๋ถ„๋ฅ˜ ์ „์ฒด๋ณด๊ธฐ

(46)
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(....
'์‹คํ–‰๊ณ„ํš์—์„œ ๋ฌด์—‡์„ ์ค‘์š”ํ•˜๊ฒŒ ๋ณผ ๊ฒƒ์ธ๊ฐ€?' - ๊ฐœ์ธ์ ์ธ ํ†ต์ฐฐ Real MySQL 8.0 10์žฅ ์‹คํ–‰๊ณ„ํš์„ 150๋งŒ๊ฐœ์˜ ๋”๋ฏธ ๋ฐ์ดํ„ฐ๋ฅผ ํ™œ์šฉํ•ด ๊ณต๋ถ€ํ•˜๋ฉฐ ์ž‘์„ฑํ•œ ๊ธ€์ž…๋‹ˆ๋‹ค."์‹คํ–‰ ๊ณ„ํš์„ ์–ด๋–ป๊ฒŒ ์ฝ์–ด์•ผ ํ•˜๋Š”์ง€, ๋ฌด์—‡์„ ์ฝ์–ด์•ผ ํ•˜๋Š”์ง€?" ์— ๋Œ€ํ•ด ์ œ ๊ฐœ์ธ์ ์ธ ์˜๊ฒฌ์ด ๋“ค์–ด๊ฐ”์Œ์„ ๋ฐํžˆ๋ฉฐ, ๋ถ€์กฑํ•œ ๋ถ€๋ถ„์ด ์žˆ์Œ์„ ๋ฏธ๋ฆฌ ์–‘ํ•ด ๊ตฌํ•ฉ๋‹ˆ๋‹ค.1. ์ธ๋ฑ์Šค๋ฅผ ์„ค์ •ํ•  ๋•Œ ๊ณ ๋ คํ•˜๋Š” ๊ธฐ์ค€ ์ €๋Š” ์ธ๋ฑ์Šค๋ฅผ ์„ค์ •ํ•  ์ปฌ๋Ÿผ์„ ์„ ํƒํ•  ๋•Œ ๋‹ค์Œ 3๊ฐ€์ง€ ๊ธฐ์ค€์„ ์ฃผ๋กœ ๊ณ ๋ คํ•ฉ๋‹ˆ๋‹ค.* ์ถ”๊ฐ€๋กœ, ์ธ๋ฑ์Šค ์„ค์ • ์‹œ ์ฃผ์˜ํ•  ์ ๋“ค์€ ํ•ด๋‹น ๋ชฉ์ฐจ ๋ฒ”์œ„๋ฅผ ๋ฒ—์–ด๋‚จ์œผ๋กœ ์ƒ๋žตํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค! โ“ ์นด๋””๋„๋ฆฌํ‹ฐ(Cardinality)๊ฐ€ ๋†’์€ ์ปฌ๋Ÿผ์ธ๊ฐ€?์นด๋””๋„๋ฆฌํ‹ฐ๋Š” ํ•ด๋‹น ์ปฌ๋Ÿผ์˜ ๊ณ ์œ  ๊ฐ’ ์ˆ˜๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.InnoDB ๊ฐ€ ๋ ˆ์ฝ”๋“œ๋ฅผ ์ฝ์„ ๋•Œ, ์นด๋””๋„๋ฆฌํ‹ฐ๊ฐ€ ๋†’์„์ˆ˜๋ก ๋น ๋ฅด๊ฒŒ ๋ ˆ์ฝ”๋“œ๋ฅผ ๊ฒ€์ƒ‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ, ์นด๋””๋„๋ฆฌํ‹ฐ๊ฐ€ ๋†’์€ ์ปฌ๋Ÿผ์€ ์ธ๋ฑ์Šค๋ฅผ ์„ค์ •ํ•  ๋•Œ ์šฐ..
๋™์‹œ์„ฑ ์ œ์–ด ์‹œ JPA์˜ ๋น„๊ด€์  ๋ฝ(select ... for update)์— ๋Œ€ํ•ด ํšŒ์˜์ ์ธ ์ด์œ  ์ด ๊ธ€์—์„œ๋Š” MySQL์„ ์‚ฌ์šฉํ•ด, ํŠน์ • ๋ ˆ์ฝ”๋“œ์— ๋ฝ์ด ๊ฑธ๋ฆฐ ์ƒํƒœ์—์„œ ๋‹ค๋ฅธ ํŠธ๋žœ์žญ์…˜์ด ํ•ด๋‹น ๋ ˆ์ฝ”๋“œ์— ์–ด๋Š ์ž‘์—…๊นŒ์ง€ ํ—ˆ์šฉํ•˜๋Š”์ง€ ์‹คํ—˜ํ•ด๋ณด๊ณ , MySQL ๋‚ด๋ถ€์—์„œ ์–ธ์ œ ๋ฝ์„ ์‚ฌ์šฉํ•˜๋Š”์ง€ ์•Œ์•„๋ณด๋ฉฐ ๋น„๊ด€์  ๋ฝ์— ๋Œ€ํ•ด ํšŒ์˜์ ์ธ ์ด์œ ๋ฅผ ์–˜๊ธฐํ•˜๋Š” ๊ฐœ์ธ์ ์ธ ๊ธ€์ž…๋‹ˆ๋‹ค. ์ถ”๊ฐ€๋กœ Real MySQL ์„ ์ฝ๊ณ , ๊ณต์œ  ๋ฝ๊ณผ ๋ฐฐํƒ€ ๋ฝ์— ๋ฐฐ๊ฒฝ ์ง€์‹์ด ์žˆ๋Š” ๋ถ„๋“ค์ด ์‰ฝ๊ฒŒ ์ดํ•ด ๋  ๊ฒƒ ๊ฐ™์œผ๋ฉฐ, ๊ฒฐ๋ก ์€ ๋งˆ์น˜๋ฉฐ.. ์— ์ •๋ฆฌํ•ด๋‘์—ˆ์Šต๋‹ˆ๋‹ค. ๋ชฉ์ฐจ๋Š” ๋‹ค์Œ ์ˆœ์„œ๋กœ ์ง„ํ–‰๋ฉ๋‹ˆ๋‹ค.ํ•œ ํŠธ๋žœ์žญ์…˜์—์„œ ๊ณต์œ  ๋ฝ/๋ฐฐํƒ€ ๋ฝ ํš๋“ ์‹œ, ๋‹ค๋ฅธ ํŠธ๋žœ์žญ์…˜์—์„œ ๊ฐ€๋Šฅํ•œ ์ฟผ๋ฆฌ ์†Œ๊ฐœ๊ณต์œ  ๋ฝ/๋ฐฐํƒ€ ๋ฝ ์‚ฌ์šฉ ์‹œ, ๋‹ค๋ฅธ ํŠธ๋žœ์žญ์…˜์—์„œ ์“ฐ๊ธฐ ์ž‘์—…์ด ๋Œ€๊ธฐํ•˜๋Š” ์ด์œ UPDATE / DELETE ์ฟผ๋ฆฌ ์‹œ WHERE ์ ˆ์˜ ์ธ๋ฑ์Šค ์—ฌ๋ถ€์˜ ์ค‘์š”์„ฑMySQL8.0 Repetable Read ์—์„œ Phanto..
Java์˜ ๋™๊ธฐํ™” ๊ธฐ๋ฒ• - synchronized & ReentrantLock ์— ๋Œ€ํ•ด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ˆœ์œผ๋กœ ๊ธ€์ด ์ด์–ด์ง‘๋‹ˆ๋‹ค.synchronized ์†Œ๊ฐœsynchronized vs static synchronized synchronized ๋‹จ์ ์„ ๊ทน๋ณตํ•œ ReentrantLock ์†Œ๊ฐœsynchronized vs ReentrantLock 1. synchronized ์†Œ๊ฐœ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ ํ™˜๊ฒฝ์—์„œ๋Š” ์—ฌ๋Ÿฌ ์Šค๋ ˆ๋“œ๊ฐ€ ๋™์‹œ์— ๊ฐ™์€ ์ž์›์— ์ ‘๊ทผํ•  ๊ฒฝ์šฐ, ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ๋ฌธ์ œ(๋ฐ์ดํ„ฐ ์†์ƒ, ์ถฉ๋Œ ๋“ฑ)๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ๋™๊ธฐํ™”(synchronization) ๊ธฐ๋ฒ•์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.Java์—์„œ ์ œ๊ณตํ•˜๋Š” synchronized ํ‚ค์›Œ๋“œ๋Š” ๋ชจ๋‹ˆํ„ฐ ๋ฝ(Monitor Lock)์„ ์ด์šฉํ•ด ๋™๊ธฐํ™”๋ฅผ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. ๋ชจ๋‹ˆํ„ฐ๋Š” OS๊ฐ€ ์•„๋‹Œ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด ์ˆ˜์ค€์—์„œ ์ œ๊ณตํ•˜๋Š” ๋™๊ธฐํ™” ๋ฉ”์ปค๋‹ˆ์ฆ˜์ž…๋‹ˆ๋‹ค. Java์˜ ๋ชจ๋“  ๊ฐ์ฒด(์ธ..