๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐Ÿ–ฅ๏ธ ์ตœ์ข…ํ”„๋กœ์ ํŠธ/๐Ÿš€ ๊ธฐ๋Šฅ ๊ฐœ์„ 

[๊ธฐ๋Šฅ ๊ฐœ์„ ] ์ฑ„์šฉ ๊ณต๊ณ  ๊ฒ€์ƒ‰ ์†๋„ 48ms → 14ms, ์–ด๋–ป๊ฒŒ ๊ฐ€๋Šฅํ–ˆ์„๊นŒ?

by carrot0911 2025. 4. 3.

๐Ÿš€ QueryDSL์—์„œ Elasticsearch๋กœ, ์ฑ„์šฉ ๊ณต๊ณ  ์กฐํšŒ ์„ฑ๋Šฅ ๊ฐœ์„ 

 

๐Ÿ’ญ ๋ฌธ์ œ ์ธ์‹

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

 

๐Ÿ” Elasticsearch ๋„์ž… ๋ฐฐ๊ฒฝ

์ฑ„์šฉ ๊ณต๊ณ  ๊ฒ€์ƒ‰ ๊ธฐ๋Šฅ์„ ๋‹จ์ˆœ ํ‚ค์›Œ๋“œ ์กฐํšŒ์— ๊ทธ์น˜์ง€ ์•Š๊ณ  ๋ถ€๋ถ„ ๊ฒ€์ƒ‰, ์ž๋™ ์™„์„ฑ ๋“ฑ ๊ฒ€์ƒ‰ ํŽธ์˜ ๊ธฐ๋Šฅ์„ ํ™•์žฅํ•  ํ•„์š”๊ฐ€ ์žˆ์—ˆ๋‹ค.
ํ•˜์ง€๋งŒ MySQL + QueryDSL ๊ธฐ๋ฐ˜์—์„œ๋Š” LIKE, CONCAT, REDEXP ๋“ฑ์œผ๋กœ ๋ณต์žกํ•œ ์กฐ๊ฑด์„ ๊ตฌ์„ฑํ•ด์•ผ ํ–ˆ๊ณ , ์„ฑ๋Šฅ ์ €ํ•˜๋‚˜ ์ธ๋ฑ์Šค ํšจ์œจ์„ฑ ๋ฌธ์ œ๋„ ๊ณ ๋ คํ•ด์•ผ ํ–ˆ๋‹ค.

์ด๋Ÿฐ ๊ตฌ์กฐ์—์„œ๋Š” ๊ฒ€์ƒ‰ ์ •ํ™•๋„ ํ–ฅ์ƒ, ๋น ๋ฅธ ์‘๋‹ต, ๊ฒ€์ƒ‰์–ด ๋‹จ์œ„์˜ ์œ ์—ฐํ•œ ํƒ์ƒ‰ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๊ธฐ์— ํ•œ๊ณ„๊ฐ€ ์žˆ์—ˆ๋‹ค.

Elasticsearch๋Š” n-gram, edge n-gram ๋“ฑ ๊ฐ•๋ ฅํ•œ ํ…์ŠคํŠธ ๋ถ„์„ ๊ธฐ๋Šฅ๊ณผ ๋ถ„์‚ฐ ์ธ๋ฑ์‹ฑ ๊ตฌ์กฐ๋ฅผ ํ†ตํ•ด ๋น ๋ฅธ ๊ฒ€์ƒ‰ ์‘๋‹ต ์†๋„๋ฅผ ์ œ๊ณตํ•œ๋‹ค.
๋˜ํ•œ ์ •ํ™•๋„, ๊ฐ€์ค‘์น˜, ์œ ์‚ฌ๋„ ๊ธฐ๋ฐ˜ ๊ฒ€์ƒ‰ ๋“ฑ ๋‹ค์–‘ํ•œ ๊ธฐ๋Šฅ ํ™•์žฅ ๊ฐ€๋Šฅ์„ฑ์„ ์ œ๊ณตํ•˜๊ธฐ ๋•Œ๋ฌธ์—,
๊ฒ€์ƒ‰ ๊ธฐ๋Šฅ์˜ ์œ ์—ฐ์„ฑ๊ณผ ์„ฑ๋Šฅ ๋ชจ๋‘๋ฅผ ๋งŒ์กฑ์‹œํ‚ค๋Š” ๊ธฐ์ˆ ๋กœ ํŒ๋‹จ๋˜์–ด ๋„์ž…ํ•˜๊ฒŒ ๋˜์—ˆ๋‹ค.

 

๐Ÿง  ๊ฐœ์„  ์•„์ด๋””์–ด: ๊ฒ€์ƒ‰์— ํŠนํ™”๋œ Elasticsearch๋กœ ์ „ํ™˜ํ•˜์ž!

 

QueryDSL์€ MySQL ๊ธฐ๋ฐ˜์œผ๋กœ ๋ณต์žกํ•œ ์กฐ๊ฑด ๊ฒ€์ƒ‰์ด๋‚˜ ์กฐ์ธ ์ฒ˜๋ฆฌ์—๋Š” ๊ฐ•์ ์ด ์žˆ์ง€๋งŒ, ๊ฒ€์ƒ‰ ์ „์šฉ ๊ธฐ๋Šฅ์ด๋‚˜ ์‹ค์‹œ๊ฐ„ ์กฐํšŒ ์„ฑ๋Šฅ์—๋Š” ํ•œ๊ณ„๊ฐ€ ์žˆ์—ˆ๋‹ค.
๋ฐ˜๋ฉด, Elasticsearch๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ธ๋ฑ์‹ฑํ•˜์—ฌ ๋น ๋ฅด๊ฒŒ ๊ฒ€์ƒ‰ํ•  ์ˆ˜ ์žˆ๋Š” ๊ตฌ์กฐ๋ฅผ ๊ฐ–์ถ”๊ณ  ์žˆ๊ณ  ๋ถ„์‚ฐ ์•„ํ‚คํ…์ฒ˜ ๊ธฐ๋ฐ˜์œผ๋กœ ๋Œ€๋Ÿ‰ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ์— ํŠนํ™”๋˜์–ด ์žˆ์–ด
๊ฒ€์ƒ‰ ์„ฑ๋Šฅ๊ณผ ํ™•์žฅ์„ฑ ๋ชจ๋‘์—์„œ ๋” ์ ํ•ฉํ•œ ์„ ํƒ์ด์—ˆ๋‹ค.

โœ… ๋”ฐ๋ผ์„œ, ์ฑ„์šฉ ๊ณต๊ณ  ๊ฒ€์ƒ‰ ๊ธฐ๋Šฅ์„ Elasticsearch ๊ธฐ๋ฐ˜์œผ๋กœ ์ „ํ™˜ํ•˜๊ธฐ๋กœ ๊ฒฐ์ •ํ–ˆ๋‹ค.

 

๐Ÿ”ง ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ

  • Elasticsearch ๋ฒ„์ „: 8.17.2
  • ํ…Œ์ŠคํŠธ ๋„๊ตฌ: Apache JMeter
  • ์š”์ฒญ ๋ฐฉ์‹: HTTP GET
  • ์š”์ฒญ ์ˆ˜: 200๊ฐœ (100๊ฐœ์”ฉ 2ํšŒ)
  • ์„œ๋ฒ„ ํ™˜๊ฒฝ: ๋กœ์ปฌ ์„œ๋ฒ„ (localhost)
  • ํด๋ผ์ด์–ธํŠธ ํ™˜๊ฒฝ: JMeter

๐Ÿ“Š ์„ฑ๋Šฅ ๋น„๊ต ๊ฒฐ๊ณผ

MySQL(QUeryDSL) ์กฐํšŒ ์‹œ 48ms
Elasticsearch ์กฐํšŒ ์‹œ 14ms

ํ•ญ๋ชฉ QueryDSL Elasticsearch ํ–ฅ์ƒ๋ฅ 
ํ‰๊ท  ์‘๋‹ต ์‹œ๊ฐ„ 48ms 14ms 70.8%
์ตœ์†Œ ์‘๋‹ต ์‹œ๊ฐ„ 39ms 9ms 77%
์ตœ๋Œ€ ์‘๋‹ต ์‹œ๊ฐ„ 117ms 41ms 65%
ํ‘œ์ค€ ํŽธ์ฐจ 9.37ms 3.28ms 64%
์ดˆ๋‹น ์ฒ˜๋ฆฌ๋Ÿ‰ 8.63 req/sec 9.5 req/sec + 10.1%
์ˆ˜์‹ ๋Ÿ‰ 8.63KB 65.01KB + 653.5%
์ „์†ก ๋ฐ์ดํ„ฐ 0.57KB 3.94KB + 591.2%

โœ… Elasticsearch ๋„์ž… ํ›„ ์ „๋ฐ˜์ ์ธ ์‘๋‹ต ์†๋„์™€ ์•ˆ์ •์„ฑ, ์ฒ˜๋ฆฌ๋Ÿ‰์ด ๋ชจ๋‘ ๊ฐœ์„ 

 

 

๐Ÿ”Ž ๋ถ„์„ ๋ฐ ํ•ด์„

  • ์‘๋‹ต ์‹œ๊ฐ„
    Elasticsearch ์ ์šฉ ํ›„, ํ‰๊ท  ์‘๋‹ต ์‹œ๊ฐ„์€ ์•ฝ 70.8%, ์ตœ๋Œ€ ์‘๋‹ต ์‹œ๊ฐ„์€ ์•ฝ 65% ๊ฐœ์„ ๋˜๋ฉฐ
    ์‹ค์‹œ๊ฐ„ ๊ฒ€์ƒ‰ ์„œ๋น„์Šค์— ์ ํ•ฉํ•œ ์‘๋‹ต ์„ฑ๋Šฅ์„ ํ™•๋ณดํ–ˆ๋‹ค.
  • ํ‘œ์ค€ํŽธ์ฐจ
    ์‘๋‹ต ์‹œ๊ฐ„์˜ ๋ณ€๋™ ํญ์ด ์ค„์–ด๋“  ๊ฒƒ๋„ ์ฃผ๋ชฉํ•  ๋งŒํ•˜๋‹ค.
    Elasticsearch๋Š” QueryDSL์— ๋น„ํ•ด ๋ณด๋‹ค ์•ˆ์ •์ ์ด๊ณ  ์ผ๊ด€๋œ ์„ฑ๋Šฅ์„ ๋ณด์—ฌ์คฌ๋‹ค.
  • ์ดˆ๋‹น ์ฒ˜๋ฆฌ๋Ÿ‰
    ์ดˆ๋‹น ์ฒ˜๋ฆฌ ๊ฐ€๋Šฅํ•œ ์š”์ฒญ ์ˆ˜๊ฐ€ ์•ฝ 10% ์ฆ๊ฐ€
    ํ•˜์—ฌ,
    ํŠธ๋ž˜ํ”ฝ์ด ๋งŽ์€ ์ƒํ™ฉ์—์„œ๋„ ๋” ๋งŽ์€ ์š”์ฒญ์„ ์•ˆ์ •์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ๋Ÿ‰
    Elasticsearch๋Š” ๋ฐ์ดํ„ฐ ์ˆ˜์‹  ๋ฐ ์ „์†ก๋Ÿ‰์ด ์••๋„์ ์œผ๋กœ ๋†’์•˜์œผ๋ฉฐ,
    ๋” ๋งŽ์€ ์–‘์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋น ๋ฅด๊ฒŒ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋Š” ๊ตฌ์กฐ์ž„์„ ์˜๋ฏธํ•œ๋‹ค.

Elasticsearch๋Š” ๋‹จ์ˆœํžˆ ๋น ๋ฅด๊ธฐ๋งŒ ํ•œ ๊ฒƒ์ด ์•„๋‹ˆ๋ผ
๋” ์•ˆ์ •์ ์ด๊ณ , ํ™•์žฅ์„ฑ ์žˆ๋Š” ๊ฒ€์ƒ‰ ํ™˜๊ฒฝ์„ ๋งŒ๋“ค์–ด์ฃผ๋Š” ๋ฐ ํšจ๊ณผ์ ์ธ ๊ธฐ์ˆ ์ž„์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค.

 

๐Ÿ“Œ ๊ธฐ์ˆ ์  ์ฐจ์ด ์š”์•ฝ

ํ•ญ๋ชฉ MySQL + QueryDSL Elasticsearch
์ฒ˜๋ฆฌ ๊ตฌ์กฐ ๋””์Šคํฌ ๊ธฐ๋ฐ˜ RDB ๋ฉ”๋ชจ๋ฆฌ ๊ธฐ๋ฐ˜ ์ธ๋ฑ์Šค
๊ฐ•์  ๋ณต์žกํ•œ ์กฐ์ธ, ํŠธ๋žœ์žญ์…˜ ๋น ๋ฅธ ๊ฒ€์ƒ‰, ๋Œ€์šฉ๋Ÿ‰ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ
์•ฝ์  ๋Œ€๋Ÿ‰ ์กฐํšŒ ์‹œ ๋Š๋ฆผ ๋ณต์žกํ•œ ๋กœ์ง ์ฒ˜๋ฆฌ์—” ๋ถ€์ ํ•ฉ
์ ํ•ฉํ•œ ์šฉ๋„ ์ƒ์„ธ ํ•„ํ„ฐ๋ง, ๊ด€๋ฆฌ ๊ฒ€์ƒ‰, ์ถ”์ฒœ, ํ‚ค์›Œ๋“œ ๊ธฐ๋ฐ˜ ํƒ์ƒ‰

 

 

โœ… ์ •๋ฆฌ ๋ฐ ํšŒ๊ณ 

Elasticsearch ์ „ํ™˜์œผ๋กœ ๋‹จ์ˆœ ๋ฐ์ดํ„ฐ ์กฐํšŒ๋ฅผ ๋„˜์–ด์„œ,
๊ฒ€์ƒ‰ ๊ธฐ๋Šฅ ์ž์ฒด๊ฐ€ ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์˜ ์ค‘์‹ฌ์ด ๋˜๋Š” ๊ตฌ์กฐ๋ฅผ ๊ตฌ์ถ•ํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค.

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

๐Ÿ“Œ MySQL ๊ธฐ๋ฐ˜ QueryDSL ๊ฒ€์ƒ‰์€ ์ •๋ฐ€ํ•œ ์กฐ๊ฑด ์ฟผ๋ฆฌ๋‚˜ ๋ฐ์ดํ„ฐ ๊ด€๋ฆฌ์—๋Š” ๊ฐ•์ ์ด ์žˆ์—ˆ์ง€๋งŒ, ๊ฒ€์ƒ‰ ์ž์ฒด๊ฐ€ ํ•ต์‹ฌ์ธ ์„œ๋น„์Šค์—์„œ๋Š” Elasticsearch๊ฐ€ ํ›จ์”ฌ ๋” ์ ํ•ฉํ•˜๋‹ค๋Š” ๊ฒฐ๋ก ์— ๋„๋‹ฌํ•˜๊ฒŒ ๋˜์—ˆ๋‹ค.