๋ง์ง ์์ฝ ์๋น์ค๋ ์ฌ์ฉ์๋ค์ด ์์ฝ๊ฒ ๋ง์ง์ ์์ฝํ ์ ์๋๋ก ๋์์ฃผ๋ ์์คํ ์ ๋๋ค. ์ด ์๋น์ค๋ฅผ ๊ฐ๋ฐํ๊ฒ ๋ ์ด์ ๋, ๋ง์ ์ฌ๋๋ค์ด ๋ง์ง ์์ฝ ๊ณผ์ ์์ ๊ฒช๋ ๋ถํธํจ์ ํด์ํ๊ณ ์ ํ๊ธฐ ๋๋ฌธ์ ๋๋ค. ์ด๋ฒ ํ๋ก์ ํธ์์๋ ๋ค์ํ ๊ธฐ์ ์ ํ์ฉํด ์ง๊ด์ ์ด๊ณ ํธ๋ฆฌํ ์์ฝ ๊ฒฝํ์ ์ ๊ณตํ๋ ๊ฒ์ ๋ชฉํ๋ก ํ๊ณ ์์ต๋๋ค.
-
๋๊ท๋ชจ ํธ๋ํฝ ๋์
- Jmeter๋ฅผ ํ์ฉํด์ ๋์์ฑ ๋ฌธ์ ๊ฐ ์๊ธด ๊ธฐ๋ฅ๋ค ๋ฐ๊ฒฌ ํ ๋์์ฑ ํด๊ฒฐ ๋๊ธฐ์ด ๋ฐ ํธ๋ํฝ ์ฒ๋ฆฌ ๊ณผ์ ์์ Redis ๊ธฐ๋ฐ ๊ตฌ์กฐ๋ก ์ ํํด ์์ ์ ์ธ ์ฑ๋ฅ์ ํ๋ณด.
-
์ฑ๋ฅ ์ต์ ํ
- Redis์ RAtomicLong, RScoreSortedSet, RQueue, RMap ๋ฑ์ ๋น๊ตํ์ฌ ์ฑ๋ฅ์ ํ ์คํธํ๊ณ ์ต์ ์ ๋ฐ์ดํฐ ๊ตฌ์กฐ๋ฅผ ์ ํํด ์ฒ๋ฆฌ ์๋๋ฅผ ๊ฐ์ .
- Redis ๊ธฐ๋ฐ ์บ์ฑ์ผ๋ก ์ค์๊ฐ ์ํ ์กฐํ ์ฑ๋ฅ์ 3๋ฐฐ ํฅ์.
- Redisson์ ์ฌ์ฉํ์ฌ CPU ์ ์ ์จ 50% ๊ฐ์ ๋ฐ ์์ ์ ๋ฐ์ดํฐ ์ฒ๋ฆฌ ๊ตฌํ.
- Redis ์บ์ฑ์ ์ด์ฉํด์ 100๋ง๊ฑด ๋ฐ์ดํฐ์์ ์์์ ์ด๋ฆ์ ์กฐํํ ๋ 1048.9ms์์ 4.32ms๋ก ์ฝ 24278% ํฅ์๋์์ต๋๋ค.
- ์ดํ, ์๋ผ์คํฑ ์์น๋ฅผ ์ฌ์ฉํด์ ๊ฒ์ ์๋ ๊ฐ์ ๋ฐ ๊ฒ์ ์ ํ๋ ํฅ์
-
์ด์ ๋ฐ ๋ฐฐํฌ ํจ์จํ
- Jenkins, Docker, Github Actions, AWS EC2์ ์ด์ฉํ CI/CD ํ์ดํ๋ผ์ธ ๊ตฌ์ถ์ผ๋ก ๋ฐฐํฌ ์๋ํ.
- Slack ์๋ฆผ์ ์ค์ ํ์ฌ ๋ฐฐํฌ ์ํ ๋ฐ ์๋ฃ ์ฌ๋ถ๋ฅผ ์ค์๊ฐ์ผ๋ก ํ์๋ค์๊ฒ ์ ๋ฌํด ํ์ ํจ์จ์ฑ ๊ฐํ.
- ๋ณด์ ๊ทธ๋ฃน ์ค์ ๊ณผ SSL ์ธ์ฆ์๋ฅผ ์ ์ฉํ์ฌ ๋ณด์์ฑ์ ๊ฐํํ ๋ฐฐํฌ ํ๊ฒฝ ๊ตฌ์ถ.
-
๋์ฉ๋ ๋ฐ์ดํฐ ์ฒ๋ฆฌ ์๋ํ
- Spring Batch์ Scheduler๋ฅผ ํตํด ์ง๊ณ๋ฅผ ์๋ํํ๊ณ QueryDSL๋ฅผ ํตํด ํจ์จ์ ์ธ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ ๊ทผ ๋ฐ ์ฒ๋ฆฌ ์ต์ ํ
- ์ฒ๋ฆฌ๋ ๋ฐ์ดํฐ๋ฅผ ๋ค์ํ ์ํฐํฐ๋ก ๋ถ์ฐ ์ ์ฅํ์ฌ ํ์ ๋ถ์ ๋ฐ ๋ณด๊ณ ์ ์ต์ ํ๋ ๊ตฌ์กฐ ๊ตฌํ
-
์น ํฌ๋กค๋ง
- ์์์ ์ด๋ฆ๊ณผ ์ง์ญ๋ช ์ถ์ถ ํ "๋ง์ง" ํค์๋ ์ถ๊ฐ ํ์ฌ ๋ค์ด๋ฒ ๊ธฐ๋ฐ ์น ํฌ๋กค๋ง
- Redis ์บ์ ๋ฐ ec2 ํ๋ก์ ip๋ฅผ ํ์ฉํ์ฌ ๋ค์ด๋ฒ ip๋ฐด ๊ฐ๋ฅ์ฑ ์ถ์
๐ ์์ฝ ๋๊ธฐ์ด ๋์์ฑ ์ด์
โ ๏ธ ๋ฌธ์ ๋ฐ๊ฒฌ
- ํ์: JMeter๋ก 1,000๋ช ์ ์ ์ ๊ฐ ๋์์ ๋๊ธฐ์ด์ ๋ฑ๋กํ์ ๋, ๋ฐ๊ถ ๋ฒํธ๊ฐ ์ค๋ณต์ผ๋ก ๋ฐ์ํ๋ ๋์์ฑ ์ด์๊ฐ ํ์ธ๋์์ต๋๋ค.
๐ ์ํฉ ๋ถ์
- ๋ถ์: ๋๊ธฐ์ด ๋ฑ๋ก ๋ก์ง์ ๋์์ ์ ๊ทผ ์ ๋ฐ๊ถ๋ฒํธ๊ฐ ์์ฐจ์ ์ผ๋ก ์ฌ๋ฐ๋ฅด๊ฒ ์ฆ๊ฐํ์ง ์๊ณ ์ค๋ณต๋ ๋ฒํธ๊ฐ ์ ์ฅ๋๋ ๋ฌธ์ ๊ฐ ์์์ต๋๋ค.
๐ 1์ฐจ ์๋: synchronized ์ฌ์ฉ
- ๋ฐฉ๋ฒ: ๋ฐ๊ถ๋ฒํธ ์ฆ๊ฐ ๋ถ๋ถ์
synchronizedํค์๋๋ฅผ ์ ์ฉํ์ฌ ๋์์ฑ ์ ์ด๋ฅผ ์๋ํ์ต๋๋ค. - ๊ฒฐ๊ณผ: ์ค๋ณต์ด ์ค์ด๋ค์์ง๋ง ์์ ํ ํด๊ฒฐ๋์ง๋ ์์์ต๋๋ค.
@Transactional๋ก ์ธํดsynchronized๊ฐ ๋๋ ํ ์ปค๋ฐ ์์ ์์ ๋ค๋ฅธ ์ค๋ ๋๋ค์ด ๊ฐ์ ๋ณ๊ฒฝํ์ฌ ๋ฐ์ํ ๋ฌธ์ ์์ ํ์ธํ์ต๋๋ค.
๐ 2์ฐจ ์๋: ๋น๊ด์ ๋ฝ(Pessimistic Lock) ์ ์ฉ
- ๋ฐฉ๋ฒ: ๋์์ฑ ์ถฉ๋ ๊ฐ๋ฅ์ฑ์ด ๋์ ํ๊ฒฝ์ ๊ณ ๋ คํด, ๋น๊ด์ ๋ฝ์ ์ฌ์ฉํ์ฌ ๋ฐ๊ถ๋ฒํธ ํ ์ด๋ธ์ ์ค๋ณต ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ์ต๋๋ค.
- ๊ฒฐ๊ณผ: ์ค๋ณต ๋ฌธ์ ๋ ํด๊ฒฐ๋์์ผ๋, ๋์ ํธ๋ํฝ ์ํฉ์์ ๋ฐ๋๋ฝ์ด ๋ฐ์ํ์ฌ ์ผ๋ถ ํธ๋์ญ์
์ด ๋กค๋ฐฑ๋์์ต๋๋ค.
show engine innodb status๋ช ๋ น์ด๋ก ๋ฐ๋๋ฝ ๋ก๊ทธ๋ฅผ ๋ถ์ํ ๊ฒฐ๊ณผ, ๋์ผํstoreId์waiting_number๊ฐ์ ์ฝ์ ํ๋ ค๋ ํธ๋์ญ์ ๊ฐ์ ์ถฉ๋๋ก ๋ฐ๋๋ฝ์ด ๋ฐ์ํ ๊ฒ์ ํ์ธํ์ต๋๋ค.
๐ก 3์ฐจ ์๋: Redis๋ก ์ ํ
- ๋ฐฉ๋ฒ: RDB ๋์ Redis๋ฅผ ์ฌ์ฉํ์ฌ ์ฑ๊ธ ์ค๋ ๋ ๊ธฐ๋ฐ์ผ๋ก ์์ฐจ์ ์ฒ๋ฆฌ๋ฅผ ์ ๋ํ์ต๋๋ค. Redis๋ ๋ฉ๋ชจ๋ฆฌ ๊ธฐ๋ฐ์ด๋ฏ๋ก Lock ์์ด๋ ํจ์จ์ ์ผ๋ก ๋์์ฑ์ ๊ด๋ฆฌํ ์ ์์์ต๋๋ค.
- ๊ฒฐ๊ณผ: ์ฒ๋ฆฌ์จ์ด ์ฝ 43.2% ๊ฐ์ ๋์๊ณ , ์๋ต ์๊ฐ๋ ์ฝ 30.8% ๋จ์ถ๋์์ต๋๋ค.
- ๋ํ, Redis์ ๋ฐ์ดํฐ ํ๋ฐ์ฑ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํ ์ถ๊ฐ์ ์ธ ์ฒ๋ฆฌ๋ฅผ ๊ณ ๋ฏผํ์์ต๋๋ค.
- ๋ ๋์ค ํด๋ฌ์คํฐ ๊ตฌ์ฑ ๋ฐ AOF ์ต์ ์ถ๊ฐ
- ๋ ๋์ค ์๋ฒ ๋ค์ด ์ ์ฌ๋ ์๋ฆผ ๊ธฐ๋ฅ
- ๋ํ, Redis์ ๋ฐ์ดํฐ ํ๋ฐ์ฑ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํ ์ถ๊ฐ์ ์ธ ์ฒ๋ฆฌ๋ฅผ ๊ณ ๋ฏผํ์์ต๋๋ค.
๐ ์์์ ๊ฒ์ ๊ธฐ๋ฅ ์๋ ํฅ์
-
๋ฐฐ๊ฒฝ
- 100๋ง๊ฑด ์ ๋์ ํฐ ๋ฐ์ดํฐ๋ฅผ LIKE๋ฅผ ํตํด ๊ฒ์
-
๋ฌธ์
- ๊ฒ์ ์๋๊ฐ 1์ด ์ ๋๋ก ๋๋ ค ๊ฒ์ ์๋ ํฅ์์ด ํ์ํจ
-
ํด๊ฒฐ ๋ฐฉ์
- ๊ฒ์ ์๋๋ฅผ ํฅ์ ์ํฌ ์ ์๋ ๋ฐฉ๋ฒ
- index๋ฅผ ์ ์ฉํ๋ค.
- Redis ์บ์๋ฅผ ์ด์ฉํ๋ค.
1์ฐจ ์๋: index๋ฅผ ์ ์ฉ
- Single Index: ํ๋์ ์ปฌ๋ผ์ ์ธ๋ฑ์ค๋ฅผ ์ค์ ํ์ฌ ํด๋น ์ปฌ๋ผ์ ๋ํ ๊ฒ์์ ์ต์ ํ
- ์ธ๋ฑ์ค๋ฅผ ํ๊ณ ๊ฒ์๋ ๋ด์ฉ์ 0.843 sec -> 0.031 sec๋ก ์๋๊ฐ ํฅ์๋จ
- Single Index๋ฅผ ํ๊ณ ๊ฒ์๋ ๋ด์ฉ์ ์๋๊ฐ ๋นจ๋ผ์ก์ง๋ง ์ธ๋ฑ์ค๋ฅผ ํ์ง ์๋ ๋ด์ฉ์ ์๋ํฅ์์ด ์๋จ
- Single Index ํน์ฑ์ "๊ฒ์์ด%"๋ง ์ธ๋ฑ์ค๋ฅผ ํ๊ณ , "%๊ฒ์์ด" ๋๋ "%๊ฒ์์ด%"๋ ์ธ๋ฑ์ค๋ฅผ ํ์ง ์๋ ๋ฌธ์ ๊ฐ ๋ฐ์ํจ
- Full text index: ์ ๋ฌธ ๊ฒ์ ์ธ๋ฑ์ค๋ก ํ
์คํธ ๊ธฐ๋ฐ์ ๊ฒ์์ ์ต์ ํ ํ๊ธฐ ์ํ ์ธ๋ฑ์ค
- full text index ๋ํ "๊ฒ์์ด%"๋ง ์ธ๋ฑ์ค๋ฅผ ํ๋ ๋ฌธ์ ๊ฐ ๋ฐ์
- Full text index N-Gram: n-gram ๋ฐฉ์์ full text index์ single index์ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์์๊ฒ ๊ฐ์ ๋์
- full text index๋ก ์ธํด ๊ฒ์์ ์ ํ๋๋ Like๋ณด๋ค ๋์์ก์ง๋ง ์๋๋ ๋ ๋๋ ค์ง๋ ํ์์ด ๋ฐ์
- ์ ํ์์ ์ด์ ๋ฅผ ์ฐพ์๋ณธ ๊ฒฐ๊ณผ full text index์ n-gram์ ๊ฒฝ์ฐ ์ ๋์ด ๊ฒ์์์๋ like๋ณด๋ค ๋น ๋ฅธ ์ฑ๋ฅ์ ๋ณด์ฌ์ฃผ์์ง๋ง ์ ๋ฏธ์ด ๊ฒฝ์ฐ์๋ like๋ณด๋ค ๋๋ฆฐ ์๋๋ฅผ ๋ณด์ฌ์ฃผ์ด ์ผ๊ด๋ ๊ฒ์์๋๊ฐ ๋์ค์ง ์๋ ๋ฌธ์ ๊ฐ ๋ฐ์
- ๊ฐ๋ like๋ณด๋ค 10๋ฐฐ ์ ๋ ๋๋ฆฐ ๋ฌธ์ ๊ฐ ๋ฐ์
2์ฐจ ์๋: Redis ์บ์ฑ ์ ์ฉ
- Redis ์บ์ฑ ์ ๋ต์ ๋ง๋์ง? ์์์ ์ ๋ด์ฉ๊ณผ ์ด๋ฆ์ ๋ณ๊ฒฝ์ด ์ ๊ณ , ๊ฒ์์ด ๋งค์ฐ ๋ง๊ธฐ ๋๋ฌธ์ Redis ์บ์ฑ์ ์ ํฉํ๋ค๊ณ ์๊ฐ
- Redis์๋ ํ์ด์ง ์ฒ๋ฆฌ๋ ๊ฒฐ๊ณผ๋ฅผ ๋ฃ์ ์ ์์ด dto๋ฅผ ๋ฐ๋ก ๋ง๋ค์ด์ 10๊ฑด์ฉ ์ ์ฅ
- ๊ฒฐ๊ณผ: 1048ms -> 4.32ms๋ก ์๋๊ฐ ํฅ์๋จ
- ๊ฒ์ ์๋๋ฅผ ํฅ์ ์ํฌ ์ ์๋ ๋ฐฉ๋ฒ
-
๊ฒฐ๊ณผ
- ๊ฒ์ ์๋๊ฐ 1048.90ms์์ 4.32ms๋ก ํฅ์๋์๋ค.
โ๏ธ ๋์์ฑ ๋ฌธ์ ํด๊ฒฐ
- ๋ฐฐ๊ฒฝ
- ๊ฐ๊ฒ, ๋ฉ๋ด, ๋ฆฌ๋ทฐ ์ข์์ ๊ธฐ๋ฅ
- ๋ฌธ์
- ์ฌ๋ฌ ์ฌ์ฉ์๊ฐ ๋์์ ๋์ผํ ๊ฐ๊ฒ, ๋ฉ๋ด, ํน์ ๋ฆฌ๋ทฐ์ ๋ํด ์ข์์๋ฅผ ๋๋ฅด๊ฑฐ๋ ์ทจ์ํ๋ ์์ฒญ์ ๋ณด๋ผ ๊ฒฝ์ฐ ๋ฌธ์ ๊ฐ ๋ฐ์
- ์ข์์ ์ค๋ณต ์ ์ฅ: ๋ ๊ฐ์ "์ข์์"๊ฐ ์ค๋ณต์ผ๋ก ์ ์ฅ๋์ด ์ค์ ์ํ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ํ๊ฐ ๋ถ์ผ์นํ๊ฒ ๋จ.
- ์ค๋ณต ์ทจ์: ์ด๋ฏธ ์ทจ์๋ ์ข์์๋ฅผ ๋ค์ ์ทจ์ํ๋ ค๊ณ ์๋ํ๋ ์ํฉ์ด ๋ฐ์ํ์ฌ ๋ฐ์ดํฐ ๋ฌด๊ฒฐ์ฑ์ ํด์นจ.
- ์ข์์ ์์ ๋ถ์ผ์น: ์์ฒญ์ด ๊ฒฝํฉํ๋ ๋์ ์ข์์ ์ถ๊ฐ์ ์ทจ์๊ฐ ํผ์ฌ๋์ด ์ต์ข ์ ์ธ ์ข์์ ์๊ฐ ๋น์ ์์ ์ผ๋ก ๊ธฐ๋ก๋จ.
- ํด๊ฒฐ ๋ฐฉ์
- Redisson์ ๋ถ์ฐ ๋ฝย RLock์ ๋์
- ๋ฝ ์์ฑ ๋ฐ ๊ด๋ฆฌ: Redis์ RLock์ ์ฌ์ฉํ์ฌ ๋ฆฌ์์ค๋ณ๋ก ๊ณ ์ ํ ๋ฝ ํค๋ฅผ ์์ฑํฉ๋๋ค. ์: lock:like:<entity_id> ํํ์ ํค๋ฅผ ์ฌ์ฉํด ํน์ ๊ฐ๊ฒ, ๋ฉ๋ด, ๋ฆฌ๋ทฐ์ ๋ํ ๋ฝ์ ๊ฐ๋ณ์ ์ผ๋ก ๊ด๋ฆฌ.
- ๋ฝ ํ๋: lock.tryLock ๋ฉ์๋๋ฅผ ํตํด ๋ฝ์ ํ๋ํฉ๋๋ค. ๋๊ธฐ ์๊ฐ ๋์ ๋ฝ์ ์๋ํ๋ฉฐ, ๋ฝ์ ํ๋ํ๋ฉด ์ง์ ๋ ์๊ฐ ๋์ ๋ค๋ฅธ ์ค๋ ๋๊ฐ ํด๋น ๋ฆฌ์์ค์ ์ ๊ทผํ์ง ๋ชปํ๋๋ก ๋ณด์ฅ.
- ๋์์ฑ ์ ์ด: ๋ฝ์ ํตํด ํ ๋ฒ์ ํ๋์ ์ค๋ ๋๋ง toggleLike ๋ฉ์๋๋ฅผ ์คํํ๋๋ก ๋ณด์ฅํฉ๋๋ค.
- ๋ฝ ํด์ : ์์ ์ด ์๋ฃ๋๋ฉด ๋ฝ์ ํด์ ํ์ฌ ๋ค๋ฅธ ์์ฒญ์ด ํด๋น ๋ฆฌ์์ค๋ฅผ ์ฒ๋ฆฌํ ์ ์๋๋ก ํ์ฉ.
- ๊ฒฐ๊ณผ
- ์ข์์ ์ค๋ณต ๋ฐฉ์ง: ๋์ผํ ๋ฆฌ์์ค์ ๋ํด ๋์ ์ ๊ทผ์ด ์ง๋ ฌํ๋์ด, ๋ ๊ฐ์ "์ข์์"๊ฐ ์ค๋ณต์ผ๋ก ์ ์ฅ๋๋ ๋ฌธ์ ๋ฅผ ๋ฐฉ์ง.
- ์ข์์ ์ทจ์ ์ค๋ณต ๋ฐฉ์ง: ์ด๋ฏธ ์ทจ์๋ ์ข์์์ ๋ํด ์ถ๊ฐ์ ์ธ ์ทจ์ ์์ฒญ์ด ๋ฌด์๋จ.
- ๋ฐ์ดํฐ ์ผ๊ด์ฑ ๋ณด์ฅ: ์ข์์ ์ถ๊ฐ ๋ฐ ์ทจ์๊ฐ ๊ต์ฐจ๋๋ ์ํฉ์์๋ ์ต์ข ์ ์ธ ์ข์์ ์๊ฐ ์ ํํ ๋ฐ์๋จ.
- ์ฑ๋ฅ ์ ํ ์ต์ํ: Redis์ ๋ฉ๋ชจ๋ฆฌ ๊ธฐ๋ฐ ์ฒ๋ฆฌ๋ก ์ธํด ๋ฝ์ ์ฌ์ฉํ๋ ์์ ์์๋ ์ฑ๋ฅ ์์ค์ด ์ต์ํ๋จ.
โฐ ์คํ๋ง ๋ฐฐ์น ๋์
- ๋ฐฐ๊ฒฝ
- ์คํ๋ง ๋ฐฐ์น ๋์
- ์ ์ฐ ๋๋ ์จ์ดํ ๋ฐ์ดํฐ๋ ์ค์๊ฐ ์ฒ๋ฆฌ๋ณด๋ค๋ ์์คํ ๋ถ๋ด์ด ์ ์ ์๊ฐ๋์ ์ผ๊ด์ ์ผ๋ก ์ฒ๋ฆฌํ ํ์์ฑ์ ์ํด ๋ฐฐ์น ๋ฐฉ์์ ์ ํ
- ์์ ์ ์ธ ์ด์์ ์ํด ๋ฉ์ธ DB์ ๋ฐฐ์น ๋ฉํ๋ฐ์ดํฐ DB๋ฅผ ๋ถ๋ฆฌํ์ฌ ๋ ๋ฆฝ์ ์ธ ๋ฐ์ดํฐ ๊ด๋ฆฌ ๊ตฌ์กฐ๋ฅผ ๊ตฌ์ฑ
- ๋ฐฐ์น ๋ฉํ๋ฐ์ดํฐ ํ
์ด๋ธ ์์ฑ ํ์ํ
- ๋ฉํ๋ฐ์ดํฐ ์ ์ฉ DB๋ฅผ ๋๋๋ ๊ตฌ์กฐ๋ก ์ ํ
- ๋ฉํฐ DataSource ๊ตฌ์ฑ
- ๋ฉ์ธ๋ฐฐ์น MetaDBConfig๊ณผ DataDBConfig๋ก ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋ชจ๋ ๊ตฌ๋ถ
- ์คํ๋ง ๋ฐฐ์น ๋์
- ๋ฌธ์
- DB ๋ถ๋ฆฌ ์ค์ ์๋ฌ
- application.yml์ ์ค์ ์๋ฌ๋ก ์ธํ ๋ฉํ ํ ์ด๋ธ ์์ฑ ๋ถ๊ฐ
- ์นด๋ฉ๋ฌธ๋ฒ -> ์ค๋ค์ดํฌ๋ฌธ๋ฒ ๋ณํ ์๋ฌ
- DB์ ์ ๊ทผํ์ฌ Query๋ก ๋ณํ์ ๋ฌธ๋ฒ ๋ณํ์ด ์๋๋ ์๋ฌ ๋ฐ์
- DB ๋ถ๋ฆฌ ์ค์ ์๋ฌ
- ํด๊ฒฐ ๋ฐฉ์
- DB ๋ถ๋ฆฌ ํด๊ฒฐ ๋ฐฉ๋ฒ
- DB์ ๋ง๋ ์คํค๋ง๋ฅผ ์ฐพ์์ ์ถ๊ฐ ์ค์
- ์นด๋ฉ๋ฌธ๋ฒ -> ์ค๋ค์ดํฌ๋ฌธ๋ฒ ๋ณํ ํด๊ฒฐ ๋ฐฉ๋ฒ
- CamelCaseToUnderscoresNamingStrategy ์ถ๊ฐ ์ค์
- SpringImplicitNamingStrategy ์ถ๊ฐ ์ค์
- DB ๋ถ๋ฆฌ ํด๊ฒฐ ๋ฐฉ๋ฒ
- ๊ด๋ จ ๋งํฌ : https://github.com/final17/batch
๐ฆ ์ ์ฉ ๊ธฐ์ ์์ธ๋ณด๊ธฐ
- Redis
- ์ ์ฉ ์์น: ์บ์ ์๋ฒ, ๋๊ธฐ์ด, ์ข์์ ๊ธฐ๋ฅ, ์กฐํ ์
- ์ฌ์ฉ ์ด์ : ๋์์ฑ ์ ์ด์ ์บ์ฑ์ ์ํด ๋ ๋์ค๋ฅผ ์ฌ์ฉํ์์ต๋๋ค.
- Redis Cluster
-
์ ์ฉ ์์น: ๋ ๋์ค, Docker-compose๋ก ๊ตฌ์ฑ
- ์ฌ์ฉ ์ด์ : ๊ณ ๊ฐ์ฉ์ฑ์ ์ํด ๋ ๋์ค ํด๋ฌ์คํฐ ๊ตฌ์ฑ ๋ฐ AOF ์ต์ ์ ์ ์ฉํ์์ต๋๋ค.
docker-compose.yml
services: redis-master-1: container_name: redis-master-1 image: redis:latest command: > sh -c 'echo "bind 0.0.0.0" > /etc/redis.conf && echo "port 7001" >> /etc/redis.conf && echo "cluster-enabled yes" >> /etc/redis.conf && echo "cluster-config-file node.conf" >> /etc/redis.conf && echo "cluster-node-timeout 5000" >> /etc/redis.conf && echo "cluster-announce-port 7001" >> /etc/redis.conf && echo "cluster-announce-ip ${HOST_IP}" >> /etc/redis.conf && echo "cluster-announce-bus-port 17001" >> /etc/redis.conf && echo "protected-mode no" >> /etc/redis.conf && redis-server /etc/redis.conf' ports: - "7001:7001" - "17001:17001" networks: - redis-cluster-network redis-master-2: container_name: redis-master-2 image: redis:latest command: > sh -c 'echo "bind 0.0.0.0" > /etc/redis.conf && echo "port 7002" >> /etc/redis.conf && echo "cluster-enabled yes" >> /etc/redis.conf && echo "cluster-config-file node.conf" >> /etc/redis.conf && echo "cluster-node-timeout 5000" >> /etc/redis.conf && echo "cluster-announce-port 7002" >> /etc/redis.conf && echo "cluster-announce-ip ${HOST_IP}" >> /etc/redis.conf && echo "cluster-announce-bus-port 17002" >> /etc/redis.conf && echo "protected-mode no" >> /etc/redis.conf && redis-server /etc/redis.conf' ports: - "7002:7002" - "17002:17002" networks: - redis-cluster-network redis-master-3: container_name: redis-master-3 image: redis:latest command: > sh -c 'echo "bind 0.0.0.0" > /etc/redis.conf && echo "port 7003" >> /etc/redis.conf && echo "cluster-enabled yes" >> /etc/redis.conf && echo "cluster-config-file node.conf" >> /etc/redis.conf && echo "cluster-node-timeout 5000" >> /etc/redis.conf && echo "cluster-announce-port 7003" >> /etc/redis.conf && echo "cluster-announce-ip ${HOST_IP}" >> /etc/redis.conf && echo "cluster-announce-bus-port 17003" >> /etc/redis.conf && echo "protected-mode no" >> /etc/redis.conf && redis-server /etc/redis.conf' ports: - "7003:7003" - "17003:17003" networks: - redis-cluster-network redis-replica-1: container_name: redis-replica-1 image: redis:latest command: > sh -c 'echo "bind 0.0.0.0" > /etc/redis.conf && echo "port 7004" >> /etc/redis.conf && echo "cluster-enabled yes" >> /etc/redis.conf && echo "cluster-config-file node.conf" >> /etc/redis.conf && echo "cluster-node-timeout 5000" >> /etc/redis.conf && echo "cluster-announce-port 7004" >> /etc/redis.conf && echo "cluster-announce-ip ${HOST_IP}" >> /etc/redis.conf && echo "cluster-announce-bus-port 17004" >> /etc/redis.conf && echo "protected-mode no" >> /etc/redis.conf && redis-server /etc/redis.conf' ports: - "7004:7004" - "17004:17004" networks: - redis-cluster-network redis-replica-2: container_name: redis-replica-2 image: redis:latest command: > sh -c 'echo "bind 0.0.0.0" > /etc/redis.conf && echo "port 7005" >> /etc/redis.conf && echo "cluster-enabled yes" >> /etc/redis.conf && echo "cluster-config-file node.conf" >> /etc/redis.conf && echo "cluster-node-timeout 5000" >> /etc/redis.conf && echo "cluster-announce-port 7005" >> /etc/redis.conf && echo "cluster-announce-ip ${HOST_IP}" >> /etc/redis.conf && echo "cluster-announce-bus-port 17005" >> /etc/redis.conf && echo "protected-mode no" >> /etc/redis.conf && redis-server /etc/redis.conf' ports: - "7005:7005" - "17005:17005" networks: - redis-cluster-network redis-replica-3: container_name: redis-replica-3 image: redis:latest command: > sh -c 'echo "bind 0.0.0.0" > /etc/redis.conf && echo "port 7006" >> /etc/redis.conf && echo "cluster-enabled yes" >> /etc/redis.conf && echo "cluster-config-file node.conf" >> /etc/redis.conf && echo "cluster-node-timeout 5000" >> /etc/redis.conf && echo "cluster-announce-port 7006" >> /etc/redis.conf && echo "cluster-announce-ip ${HOST_IP}" >> /etc/redis.conf && echo "cluster-announce-bus-port 17006" >> /etc/redis.conf && echo "protected-mode no" >> /etc/redis.conf && redis-server /etc/redis.conf' ports: - "7006:7006" - "17006:17006" networks: - redis-cluster-network redis-cluster-entry: container_name: redis-cluster-entry image: redis:latest command: redis-cli --cluster create redis-master-1:7001 redis-master-2:7002 redis-master-3:7003 redis-replica-1:7004 redis-replica-2:7005 redis-replica-3:7006 --cluster-replicas 1 --cluster-yes depends_on: - redis-master-1 - redis-master-2 - redis-master-3 - redis-replica-1 - redis-replica-2 - redis-replica-3 networks: - redis-cluster-network networks: redis-cluster-network: driver: bridge
- MYSQL
- ์ ์ฉ ์์น: AWS RDS
- ์ฌ์ฉ ์ด์ : ๋ฐ์ดํฐ๋ฒ ์ด์ค ๊ด๋ฆฌ ์์ (๋ฐฑ์ , ํจ์น, ๋ชจ๋ํฐ๋ง ๋ฑ) ์๋ํํ์ฌ ๋ถ๋ด์ ์ค์ฌ์ฃผ๊ณ ์ฅ์ ๋ฐ์์ ์๋์ผ๋ก ๋์ฒด ์ธ์คํด์ค๋ก ์ ํํ์ฌ ๊ณ ๊ฐ์ฉ์ฑ์ ์ ๊ณต.
-
Jenkins
- ์ ์ฉ ์์น: AWS EC2์ ๋ฐฐํฌ
-
์ฌ์ฉ ์ด์ : ์๋ํ๋ ๋น๋์ ๋ฐฐํฌ ํ์ดํ๋ผ์ธ ๊ด๋ฆฌ๋ก ์ผ๊ด๋ ๋ฐฐํฌ ํ๋ก์ธ์ค ๊ตฌํ.
Main Project Jenkins ๊ตฌ์ฑ
pipeline { agent any environment { AWS_PUBLIC_IP = 'ubuntu@3.36.56.171' DOCKER_HUB = 'aysel0413' DOCKER_IMAGE = 'project-w' DOCKER_TAG = '0.1' } stages { stage('start') { steps { slackSend ( channel: '#jenkins', color: '#FFFF00', message: "START: Job ${env.JOB_NAME} [${env.BUILD_NUMBER}]" ) } } stage('Git Clone') { steps { git branch: 'dev', credentialsId: 'github-access-token', url: 'https://github.com/final17/project-w.git' } } stage('Build') { steps { dir('./') { sh 'chmod +x ./gradlew' sh './gradlew clean bootJar' } } } stage('Test') { steps { // ํ ์คํธ ๋จ๊ณ ์คํ dir('./') { sh './gradlew test' } } } stage('DockerFile Build') { steps{ dir("./") { script { dockerimage = docker.build("${DOCKER_HUB}/${DOCKER_IMAGE}:${DOCKER_TAG}") } } } } stage('Docker Image Push') { steps { script { withDockerRegistry(credentialsId:"docker-access-token") { dockerimage.push() } } } } stage('Deploy') { steps { sshagent(credentials: ['aws_key']) { sh ''' ssh -o StrictHostKeyChecking=no ${AWS_PUBLIC_IP} << EOF docker container stop app docker image prune -f docker pull ${DOCKER_HUB}/${DOCKER_IMAGE}:${DOCKER_TAG} docker run -d --rm -p 8080:8080 --env-file ./config/.env --name app ${DOCKER_HUB}/${DOCKER_IMAGE}:${DOCKER_TAG} exit EOF ''' } } } } post { success { slackSend ( channel: '#jenkins', color: '#00FF00', message: """ SUCCESS: Job ${env.JOB_NAME} [${env.BUILD_NUMBER}] """ ) } failure { slackSend ( channel: '#jenkins', color: '#FF0000', message: "FAIL: Job ${env.JOB_NAME} [${env.BUILD_NUMBER}]" ) } } }
-
- ์ ์ฉ ์์น: AWS EC2์ ๋ฐฐํฌ
-
Docker
- ์ ์ฉ ์์น: ๋ชจ๋ ์๋น์ค ์ปจํ ์ด๋ํ
- ์ฌ์ฉ ์ด์ : ํ๊ฒฝ ์ด์์ฑ์ ๋์ฌ ์ด์ ํ๊ฒฝ ๊ฐ์ ์ผ๊ด์ฑ์ ๋ณด์ฅํ๊ณ ๋ฐฐํฌ ์๋ ๊ฐ์ . ์ปจํ ์ด๋๋ฅผ ํตํด ์๋น์ค ๊ฐ์ ์์กด์ฑ์ ๊ฒฉ๋ฆฌํ์ฌ ์์ ์ ์ธ ์ด์ ํ๊ฒฝ ๊ตฌ์ถ.
-
Github Actions
- ์ ์ฉ ์์น: CI/CD ํ์ดํ๋ผ์ธ
- ์ฌ์ฉ ์ด์ : ์ฝ๋ ํธ์์ ๋ฐ๋ฅธ ์๋ํ๋ ์ฝ๋ ํ์ง ๊ฒ์ฌ์ ๋น๋, ํ ์คํธ, ๋ฐฐํฌ ๊ณผ์ ์ ํตํด ๊ฐ๋ฐ ์๋์ ํ์ง์ ๋์์ ์ ์ง.
-
ELKB
- ์ ์ฉ ์์น: ํตํฉ ๊ฒ์, AWS EC2์ ๋ชจ๋ํฐ๋ง ํ๊ฒฝ ๊ตฌ์ถ
- ์ฌ์ฉ ์ด์ : ํตํฉ ๋ก๊น ๊ณผ ๋ชจ๋ํฐ๋ง์ ์ํ ํ๋ซํผ์ผ๋ก ์์คํ ๋ก๊ทธ ์์ง ๋ฐ ๋ถ์์ ํตํด ๋น ๋ฅธ ๋ฌธ์ ํ์ง ๋ฐ ๋์. Elasticsearch๋ฅผ ํตํ ๋ฐ์ดํฐ ์ธ๋ฑ์ฑ ๋ฐ ๊ฒ์, Logstash๋ก ๋ค์ํ ๋ก๊ทธ ๋ฐ์ดํฐ๋ฅผ ์์ง ๋ฐ ๋ณํ, Kibana ๋์๋ณด๋๋ฅผ ํตํ ์๊ฐํ, Beats๋ก ์๋ฒ์์์ ๋ก๊ทธ์ ๋ฉํธ๋ฆญ ๊ฒฝ๋ ์์ง์ ํตํด ์์คํ ์ ์ค์๊ฐ ์ํ๋ฅผ ํจ๊ณผ์ ์ผ๋ก ํ์ .
๊ฒฐ์ API ์ฐ๋
-
์ธ๋ถ PG์ฌ์ ๊ฒฐ์ API๋ฅผ ์ฐ๋ํ์ฌ ๊ฒฐ์ ์ ๋ณด๋ฅผ ์ฒ๋ฆฌํ๊ณ , ๊ฒฐ๊ณผ๋ฅผ DB์ ์ ์ฅํจ์ผ๋ก์จ ๊ฒฐ์ ์ ๋ณด๋ฅผ ์ถ์
-
Spring์ REST API์ ํธ๋์ญ์ ์ด๋ฒคํธ ๋ฆฌ์ค๋๋ฅผ ํ์ฉํ์ฌ ๊ฒฐ์ API์์ ์ฐ๋์ ํจ์จ์ ์ผ๋ก ์ฒ๋ฆฌ
์ ์ฐ Spring Batch
-
์ค์๊ฐ ์ฒ๋ฆฌ ๋์ , ์์คํ ๋ถํ๊ฐ ์ ์ ์๊ฐ๋์ ๋ฐฐ์น ๋ฐฉ์์ผ๋ก ์ ์ฐ์ ์ํํ๋ฉฐ, ๋ณ๋์ ์๋ฒ ํ๊ฒฝ์ ํ์ฉํ์ฌ ๋ถํ๋ฅผ ์ต์ํ.
- ํ๋ก์ธ์ค ํ๋ฆ:
๊ฒฐ์ ์๋ฃ ๋ฐ์ดํฐ ์กฐํโ์์๋ฃ ๊ณ์ฐโ์ ์ฐ ๊ฒฐ๊ณผ ์ ์ฅ.
- ํ๋ก์ธ์ค ํ๋ฆ:
-
์คํ๋ง ๋ฐฐ์น์ ์ค์ผ์ค๋ฌ๋ฅผ ํ์ฉํ์ฌ ์ ์ฐ ์์ ์ ์๋ํํ๊ณ , ๋ฐฐ์น๊ฐ ์์คํ ๋ถํ๊ฐ ์ ์ ์๊ฐ์ ์คํ๋๋๋ก ์ค์
-
๊ด๋ จ ๋งํฌ : https://github.com/final17/batch
ํตํฉ ๊ฒ์
-
์ฌ์ฉ์๊ฐ ์ ๋ ฅํ ํค์๋๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๋ฉ๋ด, ์ฃผ์, ๊ฐ๊ฒ๋ช ์ ๊ฒ์ํ ์ ์๋ ํตํฉ ๊ฒ์ ๊ธฐ๋ฅ ์ ๊ณต
-
์ฃผ์์ ์ง์ญ๋ณ ์นดํ ๊ณ ๋ฆฌ๋ฅผ ์ ํํด ์ํ๋ ๊ฒ์ ๊ฒฐ๊ณผ๋ฅผ ๋ ์ธ๋ถ์ ์ผ๋ก ํ์ ๊ฐ๋ฅ
-
๋๋์ ๋ฐ์ดํฐ๋ฅผ ๋น ๋ฅด๊ฒ ๊ฒ์ํ๊ณ ๋์ ์ ํ๋๋ก ๊ฒฐ๊ณผ๋ฅผ ์ ๊ณตํ๊ธฐ ์ํด Elasticsearch๋ฅผ ํ์ฉํ์ฌ ์ต์ ํ๋ ๊ฒ์ ํ๊ฒฝ ์ ๊ณต
์จ์ดํ ๋๊ธฐ์ด
-
ํด๋ฆญ ํ ๋ฒ์ผ๋ก ์จ์ดํ ๋๊ธฐ์ด์ ๋ฑ๋กํ๊ฑฐ๋ ์ทจ์ํ ์ ์๋ ์ง๊ด์ ์ธ ์ฌ์ฉ์ ์ธํฐํ์ด์ค ์ ๊ณต
-
์ฌ์ฉ์์๊ฒ ํ์ฌ ๋๊ธฐ ์๋ฒ๊ณผ ์์ ๋๊ธฐ ์๊ฐ์ ์ค์๊ฐ์ผ๋ก ์๋ฆผ ์ ๊ณต, ๋๊ธฐ ์ค์ธ ๊ณ ๊ฐ์ ํธ์์ฑ ๊ทน๋ํ
-
๋น ๋ฅด๊ณ ์ ํํ ๋๊ธฐ์ด ๊ด๋ฆฌ ๋ฐ ์๋ฒ ์ฒ๋ฆฌ๋ฅผ ์ํด Redis๋ฅผ ํ์ฉํ ์ค์๊ฐ ๋ฐ์ดํฐ ์ฒ๋ฆฌ๋ก ์์ ์ฑ๊ณผ ํจ์จ์ฑ ํ๋ณด
๐์์ฝ๋ถํฐ ๊ฒฐ์ , ๊ทธ๋ฆฌ๊ณ ์ ์ฐ๊น์ง: ํจ์จ์ ์ธ ํ๋ก์ธ์ค ๊ตฌ์ถ ์ฌ์
๐ณ ๊ฒฐ์ API ์ฐ๋
ํธ๋ฌ๋ธ ์ํ
์์ฝ CRUD ์์ ์งํ ํ ๊ฒฐ์ ๋ฅผ ์ฒ๋ฆฌํ๊ธฐ ์ํด ํ ์คํ์ด๋จผํธ API๋ฅผ ์ฐ๋ํ๋ฉด์ ๊ฐ๋ฐ์ ์งํํ์๊ณ ๊ฒฐ์ ์์คํ ์ ๊ฐ๋ฐํ๋ ๊ณผ์ ์์ ํ ์คํ์ด๋ฅผ ํตํ ๊ฒฐ์ API๋ฅผ ๊ตฌํํ๋ ์ค์ ๋ฐ์ดํฐ ํ์ฑ ๋ฌธ์ ์ ์ง๋ฉดํ๊ฒ ๋์์ต๋๋ค. API๋ก ์๋ต๋ฐ์ ๋ฐ์ดํฐ๊ฐ ์์ฑํ ํ์๊ณผ ๋ค๋ฅด๊ฒ ๋ฐํ๋์๊ณ ์ด๋ฅผ ์ ์ ํ ์ฒ๋ฆฌํ์ง ๋ชปํ๋ ์ํฉ์ด ๋ฐ์ํ์ต๋๋ค. ์ด๋ก ์ธํด ๊ฒฐ์ ์ ๋ณด๊ฐ ์ ์ฅ๋์ง ์์ ๋ฌธ์ ๊ฐ ์๊ฒผ์ต๋๋ค.
API์ ์๋ต ๋ฐ์ดํฐ ๊ตฌ์กฐ๋ฅผ ๋ค์ ํ์ ํ๊ธฐ ์ํด API ๋ฌธ์๋ฅผ ๋ฉด๋ฐํ ์ดํด๋ณด๊ณ ๋ฌธ์์์ ์ ๊ณตํ๋ ๋ฐ์ดํฐ ํ์์ ๋ง์ถฐ์ ํ์ํ ํ๋๋ค์ ์ถ์ถํ์ฌ ๊ฒ์ฆํ๊ณ API ์๋ต์ ์ ํํ ์ฒ๋ฆฌํ ์ ์๋๋ก ํ์ต๋๋ค.
ํ ์ด๋ธ ์ํฐํฐ์ ๊ตฌ์กฐ๋ฅผ ์ฌ๊ฒํ ํ์ฌ ๊ฐ ํ๋๊ฐ ๋ฐ์ดํฐ ํ์ ๊ณผ ์ผ์นํ๋์ง ํ์ธํ์ต๋๋ค. ์ด๋ฅผ ๋ฐํ์ผ๋ก ์ค์ ๊ฒฐ์ ์ ๊ฒฐ์ ์ทจ์ ๊ธฐ๋ฅ์ ํตํด ํ๋ฆ์ ์ ๊ฒํ์ต๋๋ค. ๋ํ ์ ์ด๋ฏธํฐ๋ฅผ ํตํด ์ต๋ํ ๋ง์ด API๋ฅผ ํธ์ถํด๋ณด๋ฉฐ ๋ฌธ์ ๊ฐ ์๋์ง ๊ฒ์ฆํ์ต๋๋ค. ์ด ๋ชจ๋ ๊ณผ์ ์ ํตํด ์ต์ข ์ ์ผ๋ก ๊ฒฐ์ ์์คํ ์ ์์ ์ฑ๊ณผ ์ ๋ขฐ์ฑ์ ํ๋ณดํ ์ ์์์ต๋๋ค.
๊ฒฐ์ ํ ์คํธ
ํ ์คํธ ํด์ผํ๋ ๋ถ๋ถ์ ๊ฒฐ์ ์์ฒญ ์ ๊ฒ์ฆ๋ถ๋ถ์ผ๋ก ํ๋จํ๊ณ ํด๋น ๋ถ๋ถ์ Jmeter๋ฅผ ๊ฑธ์ด์ ํ ์คํธ๋ฅผ ์งํํด๋ณด์์ต๋๋ค.
| ํ ์คํธ ๋ด์ฉ | ์ํ ์ | ํ๊ท ์๋ต ์๊ฐ (ms) | ์ต์ ์๋ต ์๊ฐ (ms) | ์ต๋ ์๋ต ์๊ฐ (ms) | ์ค๋ฅ์จ (%) | ์ฒ๋ฆฌ๋ (req/sec) |
|---|---|---|---|---|---|---|
| ๊ธฐ๋ณธ | 2140 | 502 | 17 | 1689 | 4.67 | 189.9 |
| RedissonLock | 1844 | 1831 | 18 | 2318 | 5.42 | 53.8 |
| Async | 1968 | 518 | 8 | 1046 | 5.08 | 183.6 |
| RedissonLock + Async | 1852 | 1669 | 16 | 3743 | 5.40 | 58.9 |
๐ ์์์ ๊ฒ์ ๊ธฐ๋ฅ ์๋ ํฅ์
๋ฐฐ๊ฒฝ
-
100๋ง๊ฑด ์ ๋์ ํฐ ๋ฐ์ดํฐ๋ฅผ LIKE๋ฅผ ํตํด ๊ฒ์ ๋ฌธ์
-
๊ฒ์ ์๋๊ฐ 1์ด ์ ๋๋ก ๋๋ ค ๊ฒ์ ์๋ ํฅ์์ด ํ์ํจ
๐งพ ์์ฌ ๊ฒฐ์
๊ฒ์์ ๊ณ ๋ํ ์ํค๋ ๋ฐฉ๋ฒ
- ํ์ด์ง๋ค์ด์ : ๊ฒ์ ๊ฒฐ๊ณผ๊ฐ ๋ง์ ๊ฒฝ์ฐ ํ ๋ฒ์ ๋ชจ๋ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๊ธฐ ์๊ณ , ํ์ด์ง๋ค์ด์ ์ ์ ์ฉํ์ฌ ํ์ํ ๋ถ๋ถ๋ง ์กฐํํ๋๋ก ํ ์ ์์ต๋๋ค. 2. JPA ์ฟผ๋ฆฌ ์ต์ ํ ๋ฐ Indexing: ๋ฐ์ดํฐ๋ฒ ์ด์ค ํ ์ด๋ธ์ ์ธ๋ฑ์ค๋ฅผ ์ค์ ํ์ฌ ๊ฒ์ ์๋๋ฅผ ๋์ผ ์ ์์ต๋๋ค. 3. Redis ์บ์ฑ ์ ์ฉ: ์์ฃผ ์กฐํํ๋ ์์์ ๋ฐ์ดํฐ๋ฅผ Redis์ ์บ์ฑํ์ฌ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์กฐํ ๋น๋๋ฅผ ์ค์ผ ์ ์์ต๋๋ค.
์ด์ค์์ ํ์ด์ง๋ค์ด์ ์ ์ ์ฉ์ ์๋ฃํ์๊ณ , Indexing์ ํ๋ ๊ฒ์ด ์ ํฉํ๋ค๊ณ ์๊ฐ์ ํ์ฌ Indexing์ ์ ์ฉํ์์ต๋๋ค. ๊ทธ ํ์ Redis ์บ์ฑ์ ์ ์ฉํ์์ต๋๋ค.
์ธ๋ฑ์ค ์ข ๋ฅ
- ๋จ์ผ ์ธ๋ฑ์ค(Single Index): ํ๋์ ์ปฌ๋ผ์ ์ธ๋ฑ์ค๋ฅผ ์ค์ ํ์ฌ ํด๋น ์ปฌ๋ผ์ ๋ํ ๊ฒ์์ ์ต์ ํ ํฉ๋๋ค. 2. ๋ณตํฉ ์ธ๋ฑ์ค(Composite Index): ์ฌ๋ฌ ์ปฌ๋ผ์ ์กฐํฉํ์ฌ ์ธ๋ฑ์ค๋ฅผ ์์ฑํ๋ ๋ฐฉ์์ผ๋ก, ํน์ ์กฐํฉ์ ๋ํ ์ต์ ์ ์ฑ๋ฅ์ ์ ๊ณต 3. ์ ๋ํฌ ์ธ๋ฑ์ค(Unique Index): ์ค๋ณต์ด ํ์ฉ๋์ง ์๋๋ก ํ๋ ์ธ๋ฑ์ค 4. ์ ๋ฌธ๊ฒ์ ์ธ๋ฑ์ค(Full-Text Index): ํ ์คํธ ๊ธฐ๋ฐ์ ๊ฒ์์ ์ต์ ํ ํ๊ธฐ ์ํ ์ธ๋ฑ์ค
์ด์ค์์ Full-Text Inex๊ฐ ํ ์คํธ ๊ธฐ๋ฐ์ ๊ฒ์์ผ๋ก ์ ํฉํ๋ค๊ณ ์๊ฐํ์ฌ ์ ์ฉํ์์ต๋๋ค.
ํด๊ฒฐ ์์
- Full-Text Index ์ ์ฉ
- Full-Text Index๋ฅผ ์ฌ์ฉํ๋ฉด ํค์๋ ๊ฒ์์ ์ง์ํ์ง ์์ต๋๋ค.("๊ฒ์์ด"๋ง ๊ฒ์์ด ๊ฐ๋ฅํ๊ณ "%๊ฒ์์ด", "๊ฒ์์ด%", "%๊ฒ์์ด%")
- Full-Text Index์์ N-Gram์ ์ฌ์ฉํ๊ธฐ
- Full-Text๋ ์์ ๊ฐ์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ์ฌ N-Gram์ ์ฌ์ฉํ์์ต๋๋ค. N-Gram์ ์ฌ์ฉํ๋ฉด ์์์ ๋ฐ์ํ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์์์ต๋๋ค.

- ํ์ง๋ง Like๋ง ์ฌ์ฉํ ๊ฒฐ๊ณผ์ Full-Text Index N-Gram์ ์ฌ์ฉํ ๊ฒฐ๊ณผ๋ฅผ ํ์ธํด๋ณด๋ฉด "์๋ผ", "๋๊นจ๋น"๋ฅผ ๊ฒ์ํ๋ฉด ๋น ๋ฅด๊ณ , "์๋น"์ ๋์ด ์๋๊ฐ ๋น์ทํ๊ณ , "์ฐ๊ฐ", "๊ตญ๋ฐฅ"์ N-Gram๋ฐฉ์์ด ๋๋ฆฐ ๊ฒ์ ํ์ธํ ์ ์์์ต๋๋ค.
- N-Gram์ด ๋๋ฆฐ ์ด์ ๋ N-Gram์ ํน์ ๊ฒ์ ์ ์ธ๋ฐํ ์ผ์น ๊ฒ์์ ๊ฐ๋ฅํ๊ฒ ํ์ง๋ง ๋ ๋๋ ค์ง ์ ์๊ธฐ ๋๋ฌธ์ด์์ต๋๋ค.
- ์ ํ๋๋ ํฅ์๋์์ง๋ง ์๋๊ฐ ๋ง์ด ๋๋ ค์ง๊ธฐ ๋๋ฌธ์ ์ ํฉํ์ง ์๋ค๊ณ ์๊ฐํ์์ต๋๋ค.
- Single Index ๊ฑธ์ด๋ณด๊ธฐ
- ์ฒ์์ผ๋ก ๋์๊ฐ ๊ฐ์ฅ ๊ธฐ๋ณธ์ ์ธ index์ธ Single Index๋ฅผ ๊ฑธ์ด๋ณด์์ต๋๋ค
- ์ธ๋ฑ์ฑ ์ ์ฉ ๋ฒ์
- ์ธ๋ฑ์ฑ ์์ด LIKE๋ง ์ฌ์ฉํ์ฌ ๊ฒ์ํ์ ๋

- ์ธ๋ฑ์ฑ ์ฌ์ฉํ์ ๋

- Redis ์บ์ฑ ์ฌ์ฉํ๊ธฐ
- ์์์ ๋ฐ์ดํฐ๋ ์์ฃผ ์กฐํ๋๊ณ , ๋ณ๊ฒฝ์ด ์ ๊ณ ์ฝ๊ธฐ ๋น์จ์ด ๋์ ๋ฐ์ดํฐ๋ผ๊ณ ์๊ฐํ์ฌ Redis ์บ์ฑ ๋์์ ์ ํฉํ๋ค๊ณ ์๊ฐํ์์ต๋๋ค.
- ์ฒ์ ํ์ด์ง ์ฒ๋ฆฌ๋ ๋ฐ์ดํฐ๋ฅผ redis์ ๋ฃ์ผ๋ ค๊ณ ํ์ ์๋ฌ๊ฐ ๋์ค๋ฉด์ ๋ฃ์ ์ ์์์ต๋๋ค.

- ๊ทธ๋์ ํ์ด์ง ์ฒ๋ฆฌ๋ ๋ฐ์ดํฐ๋ฅผ dto๋ฅผ ์๋ก ๋ง๋ค์ด์ ํด๊ฒฐํ์์ต๋๋ค.
- Redis ๊ฒฐ๊ณผ
- ์๋๊ฐ 1048.90ms โ 4.32ms๋ก ๋นจ๋ผ์ง ๊ฒ์ ํ์ธ ํ ์ ์์ต๋๋ค.
โ๏ธ ์กฐํ์, ์ข์์ ๋ถ์ฐ๋ฝ ์ ์ฉ
- ๋ถ์ฐ ์์คํ ํ๊ฒฝ์์์ ๋ฐ์ดํฐ ์ผ๊ด์ฑ ๋ณด์ฅ, ์ฑ๋ฅ, ๊ทธ๋ฆฌ๊ณ ํ์ฅ์ฑ ์ธก๋ฉด์์ ๊ฐ์ฅ ์ ํฉํ ์๋ฃจ์ ์ด๊ธฐ ๋๋ฌธ
-
๋น๊ด์ ๋ฝ
ํธ๋์ญ์ ๋ด์์ ํ ๋จ์๋ก ๋ฝ์ ๊ฑธ์ด ๋ฐ์ดํฐ๋ฅผ ๋ณดํธ. ์ฅ์ : ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋ ๋ฒจ์์ ๊ฐ๋ ฅํ ๋์์ฑ ์ ์ด ๊ฐ๋ฅ. ์ถ๊ฐ ๋๊ตฌ ์์ด ๋ฐ์ดํฐ๋ฒ ์ด์ค ๊ธฐ๋ฅ๋ง์ผ๋ก ๊ตฌํ ๊ฐ๋ฅ. ๋จ์ : ๋ฝ์ด ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ง์ ๊ฑธ๋ฆฌ๋ฏ๋ก, ํธ๋์ญ์ ์ด ์ค๋ ์ง์๋๋ฉด ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ฑ๋ฅ์ด ์ ํ๋จ. ๋ถ์ฐ ํ๊ฒฝ(๋ฉํฐ ์ธ์คํด์ค)์์๋ ์ฌ์ฉํ ์ ์์. ๋ฝ ๊ฒฝํฉ์ด ์ฌํ๋ฉด ๋ฐ๋๋ฝ ๋ฐ์ ๊ฐ๋ฅ -
๋๊ด์ ๋ฝ
๋ฐ์ดํฐ๋ฅผ ์ฝ์ ํ ์ ๋ฐ์ดํธ ์์ ์ ๋ฐ์ดํฐ์ ๋ฒ์ ์ ํ์ธํ์ฌ ๋์์ฑ ์ถฉ๋์ ๊ฐ์ง. -
์ฅ์ : ๋ฝ์ ๊ฑธ์ง ์์ผ๋ฏ๋ก ์ฑ๋ฅ์ด ๋ฐ์ด๋จ. ์ถฉ๋ ๋ฐ์์ด ์ ์ ํ๊ฒฝ์์ ์ ํฉ.
-
๋จ์ : ์ถฉ๋์ด ๋น๋ฒํ ๊ฒฝ์ฐ ์ฑ๋ฅ์ด ์ ํ๋จ(์ฌ๋ฌ ๋ฒ ์ฌ์๋ ํ์). ์ถฉ๋ ๊ฐ์ง ํ ๋กค๋ฐฑ ๋ฐ ์ฌ์๋ ๋ก์ง์ด ๋ณต์กํด์ง ์ ์์. ๋ถ์ฐ ํ๊ฒฝ์์ ์ฌ์ฉํ๋ ค๋ฉด ์ถ๊ฐ์ ์ธ ๊ตฌํ ํ์.
- ๋ถ์ฐ ํ๊ฒฝ ์ง์: ๋ฉํฐ ๋ ธ๋/๋ฉํฐ ์ธ์คํด์ค์์๋ ๋์.
- ์ฑ๋ฅ: ๋ฉ๋ชจ๋ฆฌ ๊ธฐ๋ฐ Redis๋ฅผ ์ฌ์ฉํ์ฌ ๋ฝ ์ฒ๋ฆฌ ์๋๊ฐ ๋น ๋ฆ.
- ๋ฐ๋๋ฝ ๋ฐฉ์ง: ์๋ TTL๋ก ๋ฐ๋๋ฝ ๊ฐ๋ฅ์ฑ์ ์ ๊ฑฐ.
- ํ์ฅ์ฑ: ํด๋ฌ์คํฐ ๊ตฌ์ฑ์ ํตํด ๋์ ํ์ฅ์ฑ๊ณผ ๊ฐ์ฉ์ฑ ์ ๊ณต.
- ์ ์ฐ์ฑ: ๋จ์ผ ๋ฆฌ์์ค๋ ํน์ ์์ ๋จ์๋ก ๋ฝ ๊ด๋ฆฌ๊ฐ ๊ฐ๋ฅ.
๐ Elastic search ํตํฉ ๊ฒ์
DB์์ LIKE ์ฐ์ฐ์ ํตํด ํค์๋ ๊ฒ์์ ์ํํด ๋ณด์์ต๋๋ค.
- ๋ฐ์ดํฐ ๊ฐ์: 100๋ง ๊ฑด
- ๊ฒ์ ์ปฌ๋ผ: ์ฌ์ ๋ช , ์ฌ์ ํํ, ์ฃผ์, ๋๋ก๋ช ์ฃผ์, ๋ฉ๋ด
- ๊ฒฐ๊ณผ: ์ฝ 5์ด ์์

DB ์ปฌ๋ผ์ ์ธ๋ฑ์ค๋ฅผ ์ถ๊ฐํด ์ฑ๋ฅ์ ๊ฐ์ ํด๋ณด๋ ค ํ์ผ๋, LIKE ์ฐ์ฐ์์ %ํค์๋%์ ๊ฐ์ด ์์๊ณผ ๋์ ์์ผ๋์นด๋๋ก ๋๋ฌ์ธ๋ฉด ์ธ๋ฑ์ค๊ฐ ๋ฌด์ฉ์ง๋ฌผ์ด ๋๋ ๊ฒ์ ํ์ธํ์ต๋๋ค.
-
%ํค์๋%๋ฅผ ์ฌ์ฉํ ๊ฒฝ์ฐ ์ฑ๋ฅ ๊ฐ์ ํจ๊ณผ๊ฐ ์์์ผ๋ฉฐ,ํค์๋%๋ก ์์ํ๋ ๊ฒฝ์ฐ์๋ง ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ ์ ์์์ต๋๋ค.

MySQL์ Full-Text Search๋ฅผ ์ฌ์ฉํด ๊ฒ์์ ๊ตฌํํด ๋ณด์์ต๋๋ค.
@Query(value = "SELECT * FROM store WHERE MATCH(business_name, full_location_address, full_road_name_address, business_type) AGAINST(:keyword IN NATURAL LANGUAGE MODE)", nativeQuery = true)
List<Store> searchByKeyword(@Param("keyword") String keyword, Pageable pageable);๊ฒ์ ์ฑ๋ฅ์ด ๊ฐ์ ๋์์ผ๋, ์ํ๋ ๊ฒ์ ๊ฒฐ๊ณผ๊ฐ ์ ํํ๊ฒ ๋์ค์ง ์์ ํตํฉ ๊ฒ์์ผ๋ก๋ ๋ถ์ ํฉํ๋ค๊ณ ํ๋จํ์ต๋๋ค.

DB์์์ ๊ฒ์ ๋์ Elasticsearch๋ฅผ ์ฌ์ฉํ๊ธฐ๋ก ํ์ต๋๋ค. Elasticsearch๋ฅผ ๋์ ํ ์ด์ ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
- ๊ธฐ์กด DB ๊ฒ์์ ํ๊ณ
- ์ฑ๋ฅ: SQL์ LIKE ๊ฒ์์
%ํค์๋%๊ตฌ์กฐ์ธ ๊ฒฝ์ฐ ์ธ๋ฑ์ค๋ฅผ ํ์ฉํ ์ ์์ด ๋ฐ์ดํฐ๊ฐ ๋ง์์๋ก ์๋๊ฐ ๋๋ ค์ง๋๋ค. - ์ ํ๋ ๊ฒ์ ๊ธฐ๋ฅ: Full-Text Search๋ ์ฌ์ฉ์ ์๋๋ฅผ ์ธ๋ฐํ๊ฒ ๋ฐ์ํ๊ธฐ ์ด๋ ค์ ๋ณตํฉ ์กฐ๊ฑด ์ฒ๋ฆฌ์ ๊ฒ์ ์ ํ๋์ ํ๊ณ๊ฐ ์์ต๋๋ค.
- ์ฑ๋ฅ: SQL์ LIKE ๊ฒ์์
- Elasticsearch์ ์ฅ์
- ์ฑ๋ฅ: ์ญ์์ธ ๊ตฌ์กฐ๋ก ๊ฒ์ ์๋๊ฐ ๋งค์ฐ ๋น ๋ฆ ๋๋ค.
- ์ ๊ตํ ๊ฒ์: ํํ์ ๋ถ์๊ธฐ(Nori)๋ฅผ ํตํด ํ๊ตญ์ด ๊ฒ์ ์ต์ ํ ๋ฐ ํ๋๋ณ ๊ฐ์ค์น ์ค์ ์ผ๋ก ๊ฒ์ ๊ฒฐ๊ณผ์ ํ์ง ๋์ต๋๋ค.
- ์ ์ฐํ ๊ฒ์: Fuzzy ๊ฒ์, ๋ถ๋ถ ๋งค์นญ, ๋ณตํฉ ์ฟผ๋ฆฌ ๋ฑ์ ์ง์ํด ๋ค์ํ ์ฌ์ฉ์ ์๊ตฌ๋ฅผ ์ถฉ์กฑํ ์ ์์ต๋๋ค.
- ํ์ฅ์ฑ๊ณผ ์ค์๊ฐ์ฑ: ์ค์๊ฐ ์์ธ๊ณผ ์ํ ํ์ฅ์ผ๋ก ๋ฐ์ดํฐ ์ฆ๊ฐ์๋ ์์ ์ ์ธ ์ฑ๋ฅ์ ์ ์งํ ์ ์์ต๋๋ค.
- ๊ฐ๋จํ
multi_match์ฟผ๋ฆฌ๋ฅผ ํตํด ํ๋๋ณ ๊ฐ์ค์น๋ฅผ ์ฃผ์ด ๊ฒ์ํ์ ๋, 100๋ง๊ฑด์ ๋ฐ์ดํฐ์์ 30ms ๋ด์ ๊ฒ์ ๊ฒฐ๊ณผ๋ฅผ ์ป์ ์ ์์์ง๋ง,์์ธ ์ด๋ฐฅ๊ฒ์ ์ ๊ด๋ จ์ด ์์ด๋ณด์ด๋ ๊ฐ๊ฒ๊ฐ ๊ฒ์ ๊ฒฐ๊ณผ ์์์ ๋์ค๋ ๋ฌธ์ ๋ฅผ ๋ฐ๊ฒฌํ์ต๋๋ค.
์ฌ์ฉ์๊ฐ ์์ธ์ ์ํ๊ตฌ ์ด๋ฐฅ์ง์ ๊ฒ์ํ๋ฉด, ๊ธฐ๋ํ๋ ๊ฒฐ๊ณผ๋ ์์ธ ์ํ๊ตฌ์ ์์นํ ์ด๋ฐฅ์ง์
๋๋ค. ๊ทธ๋ฌ๋ ๊ธฐ์กด multi_match ์ฟผ๋ฆฌ๋ ๋ค์๊ณผ ๊ฐ์ ํ๊ณ๊ฐ ์์ต๋๋ค.
- ํค์๋๋ฅผ ํ ํฐํํ์ฌ ๊ฐ๊ฒ๋ช , ์ฃผ์, ๋ฉ๋ด ๋ฑ์ ํ๋์์ ์ผ๋ถ๋ผ๋ ๋งค์นญ๋๋ ๊ฒฝ์ฐ ๊ฒฐ๊ณผ๋ก ๋ฐํ๋ฉ๋๋ค.
- ์ด๋ก ์ธํด ์์ธ์ด ์๋ ๋ค๋ฅธ ์ง์ญ์ ์ด๋ฐฅ์ง์ด ๋์ ์ ์๋ฅผ ๋ฐ์ ์์์ ๋ ธ์ถ๋ ์ ์์ต๋๋ค.
์๋ฅผ ๋ค์ด:
- ๊ธฐ๋ํ๋ ๊ฒฐ๊ณผ: ์์ธ ์ํ๊ตฌ ์ด๋ฐฅ์ง
- ์ค์ ๊ฒฐ๊ณผ: ์์ธ์ด ์๋ ๋ค๋ฅธ ์ง์ญ ์ด๋ฐฅ์ง์ด ์์์ ๋์ค๋ ๋ฌธ์
๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด bool ์ฟผ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ฌ ๊ฒ์ ์ฟผ๋ฆฌ๋ฅผ ๊ฐ์ ํ๊ธฐ๋ก ๊ฒฐ์ ํ์ต๋๋ค.
-
ํค์๋ ๋ถ์ ํ ํ๋๋ณ๋ก ๊ฐ์ค์น๋ฅผ ๋ค๋ฅด๊ฒ ์ค์
- ๊ฐ์ค์น๋ฅผ ์กฐ์ ํด ์ํ๋ ๊ฒฐ๊ณผ๋ฅผ ๋์ถํ๋ ค ํ์ผ๋, ์ ๋ ฅ๋ ๋์์ ๊ตฌ๊ฐ ๋ฐ๋์ ํฌํจ๋๋ค๋ ๋ณด์ฅ์ด ์์ต๋๋ค.
-
bool ์ฟผ๋ฆฌ๋ฅผ ์ฌ์ฉํด ํ์ ์กฐ๊ฑด ์ ์ฉ
- ํค์๋๋ฅผ ๋ถ์ํ์ฌ ๋์์ ๊ตฌ, ๋ฉ๋ด๋ฅผ ํํฐ๋งํ ํ, ํด๋น ์กฐ๊ฑด์ must๋ก ์ค์ ํด ํ์์ ์ผ๋ก ํฌํจ๋๋๋ก ์ฒ๋ฆฌํฉ๋๋ค.
์ฌ์ฉ์ ๊ธฐ๋์ ๋ถํฉํ๋ ๊ฒ์ ๊ฒฐ๊ณผ๋ฅผ ๋ณด์ฅํ๊ธฐ ์ํด bool ์ฟผ๋ฆฌ๋ฅผ ์ ํํ์ต๋๋ค. ์ด ์ ๊ทผ๋ฒ์ ๋์, ๊ตฌ, ๋ฉ๋ด์ ๊ฐ์ ์ ๋ ฅ ์กฐ๊ฑด์ ๋ฐ๋์ ์ถฉ์กฑ์ํค๋ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํ ์ ์์ต๋๋ค.
ํค์๋๋ฅผ ๋ถ์ํ์ฌ ํํฐ๋งํ ๋ค, ๋์, ๊ตฌ, ๋ฉ๋ด ์ด๋ฆ์ ์ถ์ถํ๊ณ ์ด๋ฅผ ํ์ฉํ์ฌ ๊ฒ์์ ๊ฐ์ ํ์ต๋๋ค.
-
๋์, ๊ตฌ, ๋ฉ๋ด ํํฐ๋ง
- ํค์๋์์ ๋์, ๊ตฌ, ๋ฉ๋ด ์ ๋ณด๋ฅผ ์ถ์ถ.
- ์ถ์ถ๋ ์ ๋ณด๋ฅผ Elasticsearch์ bool ์ฟผ๋ฆฌ์์
must์กฐ๊ฑด์ผ๋ก ์ ์ฉํ์ฌ ๋ฐ๋์ ํฌํจ๋๋๋ก ์ค์ .
-
๊ฒ์ ํ๋ก์ธ์ค
- ์ถ์ถ๋ ์กฐ๊ฑด(๋์, ๊ตฌ, ๋ฉ๋ด)์ ๊ธฐ์ค์ผ๋ก ๋ฌธ์๋ฅผ ํํฐ๋ง.
- ์ด ๋จ๊ณ์์ ์ ๋ ฅ๋ ์์น์ ๋ฉ๋ด๋ฅผ ๋ง์กฑํ๋ ๋ฌธ์๋ง ๋จ๊น.
- ํํฐ๋ง๋ ๊ฒฐ๊ณผ์ ๋ํด ๊ฐ๊ฒ๋ช
๊ณผ ๋ฉ๋ด ํ๋๋ฅผ
match๋ก ๊ฒ์.
- ์ถ์ถ๋ ์กฐ๊ฑด(๋์, ๊ตฌ, ๋ฉ๋ด)์ ๊ธฐ์ค์ผ๋ก ๋ฌธ์๋ฅผ ํํฐ๋ง.
-
์กฐ๊ฑด์ด ์์ ๊ฒฝ์ฐ
- ๋ง์ฝ ์ ๋ ฅ๋ ํค์๋์์ ๋์, ๊ตฌ, ๋ฉ๋ด ์ ๋ณด๊ฐ ์ถ์ถ๋์ง ์๋๋ค๋ฉด, ๊ฐ๊ฒ๋ช ๊ณผ ๋ฉ๋ด ํ๋๋ง์ผ๋ก ๊ฒ์์ ์ํ.
-
๊ฐ๊ฒ๋ช ์ ์ฐ์ ์์ ๋ถ์ฌ
- ๊ฐ๊ฒ๋ช
ํ๋์์ ํ ํฐํ๋์ง ์์
keywordํ๋๋ฅผ ์ฌ์ฉํด ๊ฒ์. - boost ๊ฐ์ ๋ถ์ฌํ์ฌ ๋ฉ๋ด๋ณด๋ค ๊ฐ๊ฒ๋ช ์ด ๋ ๋์ ์ฐ์ ์์๋ฅผ ๊ฐ๋๋ก ์ค์ .
- ๊ฐ๊ฒ๋ช
ํ๋์์ ํ ํฐํ๋์ง ์์
1์ฐจ ๊ฐ์ ์์๋ ์ฌ๋ฌ ํ๋์ ๋ํด ์ฟผ๋ฆฌ๋ฅผ ์์ฒญํ์ต๋๋ค. ๊ทธ๋ฌ๋ ์ด ๋ฐฉ์์ ๊ฒ์ ํ๋๊ฐ ๋ง์์ง์๋ก ์ฑ๋ฅ์ ๋ถ์ ์ ์ธ ์ํฅ์ ๋ฏธ์น ๊ฐ๋ฅ์ฑ์ด ์์์ต๋๋ค. ์ด๋ฅผ ๊ฐ์ ํ๊ธฐ ์ํด Elasticsearch์ copy_to ๊ธฐ๋ฅ์ ํ์ฉํ์ฌ ๊ฒ์ ์ฑ๋ฅ์ ์ต์ ํํ์ต๋๋ค.
- ๊ฒ์ ํ
์คํธ ํตํฉ
- ๊ฒ์์ ํ์ํ ํ
์คํธ ๋ฐ์ดํฐ๋ฅผ ์๋ผ์คํฑ ์์น์
copy_to๋ฅผ ์ฌ์ฉํด์ ํ๋์ ํ๋์ ํตํฉํ์ฌ ์ ์ฅ
- ๊ฒ์์ ํ์ํ ํ
์คํธ ๋ฐ์ดํฐ๋ฅผ ์๋ผ์คํฑ ์์น์
- ์๋ฅผ ๋ค์ด:
- ์ฃผ์:
์์ธ์ ์ํ๊ตฌ - ๊ฐ๊ฒ๋ช
:
๋ง์ง - ๋ฉ๋ด:
ํ๋ฒ๊ฑฐ, ํผ์ - ํตํฉ๋ ํ๋:
์์ธ์ ์ํ๊ตฌ ๋ง์ง ํ๋ฒ๊ฑฐ, ํผ์
- ์ฃผ์:
์ฟผ๋ฆฌ๋ฅผ ์ฌ๋ฌ ์ฐจ๋ก ์์ ํ๋ฉด์ ์ฌ์ฉ์๊ฐ ์ํ๋ ๊ฒฐ๊ณผ๋ฅผ ์ป๊ธฐ ์ํ ๋ฐฉ๋ฒ์ ๊ณ ๋ฏผํ์ต๋๋ค. ๊ทธ๋ฌ๋ ๊ฒ์์ ๋ํ ๊ตฌ์ฒด์ ์ธ ๋น์ฆ๋์ค ์๊ตฌ์ฌํญ์ด ์์ด ์ ์ ํ ๋ฐฉํฅ์ ์ก๊ธฐ ์ด๋ ค์ ์ต๋๋ค. ์ด์ ์บ์นํ ์ด๋ธ๊ณผ ๊ฐ์ ์๋น์ค์ ๊ฒ์ ๋ฐฉ์์ ๋ถ์ํ์ฌ ๊ฐ์ ์์ด๋์ด๋ฅผ ์ป์์ต๋๋ค.
-
์์ค๋ฅผ ๊ฒ์ํ๋ฉด ์ด๋ฆ์์์ค๊ฐ ํฌํจ๋ ๊ฐ๊ฒ๋ค์ด ๊ฒ์๋จ. -
์์ธ ์์ค๋ฅผ ๊ฒ์ํ๋ฉด ์์ธ ์ง์ญ ํํฐ๊ฐ ์ ์ฉ๋์ง๋ง, ๊ฒฐ๊ณผ๋์์ธ ์์ค์ ๊ด๋ จ ์๋ ๊ฐ๊ฒ๋ ํฌํจ๋จ. -
์์ธ ์์น์ธ๋ ๊ฒ์๋์ง ์์ง๋ง,์์ธ ์์น์ธ๋ก์์ค์ ๊ฐ์ด ๋ ๊ตฌ์ฒด์ ์ธ ์ ๋ ฅ์๋ ๊ฒ์ ๊ฒฐ๊ณผ๊ฐ ๋ํ๋จ. -
์์น์ธ๋ก์์ค์ค์ค๋ ๊ฒ์๋์ง๋ง,์์ธ์์ด ์์น์ธ๋ก์์ค์ค์ค๋ ๊ฒฐ๊ณผ๊ฐ ๋์ค์ง ์์. -
์์น์ธ๋ฅด์๋ ๊ฒฐ๊ณผ๊ฐ ์๋์จ๋ค. -
์์ธ ๋์๋ ํํฐ์ ์์ธ์ด ์ฒดํฌ๊ฐ ๋๋ค. -
์ค์ ๋ก ์๋
์์ธ ๋์์ ๊ฒ์ ํด๋ณด๋ฉด ์์ธ์ ํํฐ ์ฒดํฌ๊ฐ ์๋๋ค.
์ด๋ฌํ ๋ถ์์ ํตํด ์๊ฐํ ๊ฒ์ ๊ตฌํ ๋ฐฉ์์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
-
์ ํํ ๋งค์นญ ์ฐ์
- ์ฌ์ฉ์๊ฐ ์ ๋ ฅํ ํค์๋๋ฅผ ๊ธฐ์ค์ผ๋ก term ๋๋ prefix ์ฟผ๋ฆฌ๋ฅผ ์ฌ์ฉํด ์ ํํ ์ผ์นํ๋ ๊ฐ๊ฒ๋ช ์ ๋จผ์ ๊ฒ์.
-
ํตํฉ ๊ฒ์ ์กฐ๊ฑด
- ๋ง์ฝ ์ ํํ ๋งค์นญ ๊ฒฐ๊ณผ๊ฐ ์์ ๊ฒฝ์ฐ, ํตํฉ ๊ฒ์์ผ๋ก ์งํ.
- ํตํฉ ๊ฒ์์์๋ copy_to๋ก ์์ฑํ
full_textํ๋์ ์ฟผ๋ฆฌ๋ฅผ ์คํํ์ฌ ๋ค์ํ ํ๋์์ ํค์๋๋ฅผ ์ฐพ์.
-
์นดํ ๊ณ ๋ฆฌ ์ฒดํฌ์ ํํฐ๋ง
- ๊ฒ์๋ ํค์๋์ ์ผ์นํ๋ ์นดํ ๊ณ ๋ฆฌ๊ฐ ์์ผ๋ฉด ์ด๋ฅผ ํ์ธํด ํ๋ก ํธ์๋์ ์ ๋ฌํ์ฌ, ์น ํ์ด์ง์์ ํด๋น ์นดํ ๊ณ ๋ฆฌ๊ฐ ์ ํ๋ ์ํ๋ก ํ์๋๋๋ก ํจ.
Operator๋ฅผ AND๋ก ์ค์ ํด ๋ชจ๋ ํค์๋๊ฐ ์ผ์นํ๋ ๋ฌธ์๋ง ๋ฐํํ๋๋ก ์ฒ๋ฆฌ.
-
์ต์ ํ ๊ณ ๋ ค
- ๊ฒ์ ์ฑ๋ฅ์ ์ํด ๋ ๋ฒ์ ์ฟผ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ์์ ๋ํด ๊ณ ๋ ค ํ์.
๊ธฐ์กด์๋ ๋ฐฑ์๋์์ ํค์๋๋ฅผ ๋ถ์ํ์ฌ ํ๋ก ํธ์๋์ ํํฐ๋ง๋ ์นดํ ๊ณ ๋ฆฌ๋ฅผ ๋๊ฒจ์ฃผ๋ ๋ฐฉ์์ ๊ณ ๋ คํ์ผ๋, ์ด๋ฅผ ํ๋ก ํธ์๋์์ ํํฐ ์์์ ์ ํ๋ ์นดํ ๊ณ ๋ฆฌ๋ฅผ ๊ธฐ์ค์ผ๋ก ๊ฒ์ํ๋ ๋ฐฉ์์ผ๋ก ๋ณ๊ฒฝํ์ต๋๋ค.
-
๊ฐ๊ฒ ์ด๋ฆ ๊ฒ์
bool์ฟผ๋ฆฌ์์must์prefix์ฟผ๋ฆฌ๋ฅผ ์ฌ์ฉํด ๊ฐ๊ฒ ์ด๋ฆ์ ๋จผ์ ๊ฒ์.
-
์นดํ ๊ณ ๋ฆฌ ํํฐ ์ ์ฉ
- ์ฌ์ฉ์๊ฐ ์์ฒญ์ ์นดํ
๊ณ ๋ฆฌ ํํฐ๋ฅผ ํฌํจํ๋ค๋ฉด,
district_category.keywordํ๋์ ๋ํดterms์ฟผ๋ฆฌ๋ฅผ ์ฌ์ฉํด ์นดํ ๊ณ ๋ฆฌ๊ฐ ํ๋๋ผ๋ ์ผ์นํ๋ ๊ฒฐ๊ณผ๋ง ๋ฐํํ๋๋ก ์ค์ .
- ์ฌ์ฉ์๊ฐ ์์ฒญ์ ์นดํ
๊ณ ๋ฆฌ ํํฐ๋ฅผ ํฌํจํ๋ค๋ฉด,
-
๊ฒ์ ๊ฒฐ๊ณผ ํ์ธ
- ๊ฒ์ ๊ฒฐ๊ณผ๊ฐ ์๋ค๋ฉด ํด๋น ๊ฒฐ๊ณผ๋ฅผ ๊ทธ๋๋ก ๋ฐํ.
-
๊ฒ์ ๊ฒฐ๊ณผ๊ฐ ์์ ๊ฒฝ์ฐ ํตํฉ ๊ฒ์ ์ํ
bool์ฟผ๋ฆฌ๋ฅผ ์ด์ฉํดfull_textํ๋๋ฅผ ๋์์ผ๋ก ๊ฒ์ํ๋ฉฐ,AND์ฐ์ฐ์๋ฅผ ์ฌ์ฉํด ํค์๋๊ฐ ๋ชจ๋ ํฌํจ๋ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํ.filter๋ถ๋ถ์ ๊ธฐ์กด๊ณผ ๋์ผํ๊ฒ ์ ์งํด ์นดํ ๊ณ ๋ฆฌ ์กฐ๊ฑด์ด ์ ์ฉ๋ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํ.
์ฌ๋ฌ ํ๋๋ฅผ ๊ฐ๊ฐ ๋ ๋ฒ์ ์ฟผ๋ฆฌ๋ก ๊ฒ์ํ ํ์๊ฐ ์๋ค๋ ์ ์ ๊ณ ๋ คํ์ฌ, ๊ฐ๊ฒ๋ช ์ผ๋ก๋ง ๋จผ์ ๊ฒ์ํ๋ ๋ถ๋ถ์ ์ ๊ฑฐํ๊ณ ๋ฐ๋ก ํตํฉ ๊ฒ์์ ์ํํ๋ ๋ฐฉ์์ผ๋ก ์ต์ ํํ์ต๋๋ค.
์์ธ๋ณต์ง์ ๊ฒ์ํ๋ฉฐ ํตํฉ ๊ฒ์ ๋ฐฉ์์ผ๋ก์ ์ ํ ํ ๊ฒฐ๊ณผ๋ฅผ ํ์ธํ๊ณ , ๊ฒ์ ์ ํ๋์ ์ฑ๋ฅ์ด ๊ฐ์ ๋๋ ๊ฒ์ ํ์ธํ์ต๋๋ค.
์์ธ๋ณต์ง๊ฒ์ ์ ๊ธฐ๋ํ๋ ๊ฒฐ๊ณผ๋ ์์ธ ์ง์ญ์ ๋ณต์ง๋ค์ด ์ต์์์ ๋ ธ์ถ๋๋ ๊ฒ์ ๋๋ค.๊ฒฝ์๋จ๋ ์์ธ๋ณต์ง๊ฒ์ ์ ๊ธฐ๋ํ๋ ๊ฒฐ๊ณผ๋ ๊ฒฝ์๋จ๋ ์ง์ญ์ ์์ธ๋ณต์ง์ด ์์์ ๋ ธ์ถ๋๋ ๊ฒ์ ๋๋ค.
boolBuilder.must(m -> m.match(x -> x.field("full_text").query(search.keyword()).operator(Operator.And))).boost(4f);-
์์ธ๋ณต์ง๊ฒ์ ๊ฒฐ๊ณผ: ๊ธฐ๋ํ๋ ๊ฒฐ๊ณผ๊ฐ ๋์ค์ง ์์.
-
๊ฒฝ์๋จ๋ ์์ธ๋ณต์ง๊ฒ์ ๊ฒฐ๊ณผ: ๊ธฐ๋ํ๋ ๊ฒฐ๊ณผ๊ฐ ๋์ด.
- ์ฒซ ๋ฒ์งธ ํ
์คํธ์์ ์์ธ๋ณต์ง์ด ์์์ ๋์ค์ง ์๋ ๋ฌธ์ ๊ฐ ์์ด, ๊ฐ๊ฒ ์ด๋ฆ ํ๋์ ๊ฐ์ค์น๋ฅผ ๋ถ์ฌํ์ฌ
should์กฐ๊ฑด์ ์ถ๊ฐํ์ต๋๋ค.
boolBuilder.must(m -> m.match(x -> x.field("full_text").query(search.keyword()).operator(Operator.And))).boost(2f)
.should(m -> m.match(x -> x.field("title").query(search.keyword()).boost(4f)));๋ณ๊ฒ์ ์ ๊ธฐ๋ํ๋ ๊ฒฐ๊ณผ๋ ์ ํํ "๋ณ"์ด๋ผ๋ ๊ฐ๊ฒ๊ฐ ์ต์์์ ํ์๋๋ ๊ฒ์ ๋๋ค.๋๊ตฌ ๋ณ๊ฒ์ ์ ๊ธฐ๋ํ๋ ๊ฒฐ๊ณผ๋ ๋๊ตฌ ์ง์ญ์ ์์นํ "๋ณ"์ด๋ผ๋ ๊ฐ๊ฒ๊ฐ ์์์ ํ์๋๋ ๊ฒ์ ๋๋ค.
boolBuilder.must(m -> m.match(x -> x.field("full_text").query(search.keyword()).operator(Operator.And))).boost(2f)
.should(m -> m.match(x -> x.field("title").query(search.keyword()).boost(4f)));-
๋ณ๊ฒ์ ๊ฒฐ๊ณผ: ๊ธฐ๋ํ ๊ฒฐ๊ณผ์ ๋ฌ๋ฆฌ "๋ณ์ฝ๋ณ"์ด๋ผ๋ ๊ฐ๊ฒ๊ฐ ์ต์์์ ํ์๋จ.
-
๋๊ตฌ ๋ณ๊ฒ์ ๊ฒฐ๊ณผ: ์ด๋ ์ ๋ ์ํ๋ ๊ฒฐ๊ณผ๊ฐ ๋์์ผ๋, ์๋ฒฝํ์ง ์์.
- ๊ธฐ์กด
should์กฐ๊ฑด์match์ฟผ๋ฆฌ๋ฅผterm์ฟผ๋ฆฌ๋ก ๋ณ๊ฒฝํ์ฌ, ๊ฐ๊ฒ ์ด๋ฆ๊ณผ ์ ํํ ์ผ์นํ๋ ๊ฒฝ์ฐ๋ฅผ ์ฐ์ ์ผ๋ก ์ฒ๋ฆฌ
boolBuilder.must(m -> m.match(x -> x.field("full_text").query(search.keyword()).operator(Operator.And))).boost(2f)
.should(m -> m.term(x -> x.field("title").value(search.keyword()).boost(4f)));-
๋ณ๊ฒ์ ๊ฒฐ๊ณผ: ์ด์ ๊ณผ ๋์ผํ๊ฒ ๊ธฐ๋ํ ๊ฒฐ๊ณผ์ ์ผ์นํ์ง ์์.
-
๋๊ตฌ ๋ณ๊ฒ์ ๊ฒฐ๊ณผ: ์ผ๋ถ ๊ฐ์ ์ด ์์์ผ๋ ์ฌ์ ํ ๊ธฐ๋์ ๋ฏธ์น์ง ๋ชปํจ.
๊ธฐ์กด ์ฟผ๋ฆฌ๋ฅผ ๊ฒฐํฉํ์ฌ ๋ค์๊ณผ ๊ฐ์ด ๊ฐ์
- ํค์๋๊ฐ ๊ฐ๊ฒ๋ช ๊ณผ ์ ํํ ์ผ์นํ๋ฉด ๊ฐ์ค์น 2๋ฅผ ๋ถ์ฌ.
- ํค์๋๊ฐ ๊ฐ๊ฒ๋ช ๊ณผ ๋ถ๋ถ ์ผ์นํ๋ฉด ๊ฐ์ค์น 1.5๋ฅผ ๋ถ์ฌ.
boolBuilder = new BoolQuery.Builder()
.must(m -> m.match(t -> t
.field("full_text")
.query(search.keyword())
.operator(Operator.And)))
.should(s -> s.match(t -> t
.field("title")
.query(search.keyword())
.boost(1.5f)))
.should(s -> s.term(t -> t
.field("title.keyword")
.value(search.keyword())
.boost(2.0f)));๊ธฐ์กด ๊ฒ์์์๋ ๊ฐ๊ฒ ์ด๋ฆ๊ณผ ์ฃผ์๋ฅผ ์ค์ฌ์ผ๋ก ๊ฒ์ ๊ฒฐ๊ณผ๋ฅผ ๋์ถํ์ต๋๋ค. ์ด์ ๋ฉ๋ด ๊ฒ์ ๊ธฐ๋ฅ์ ์ถ๊ฐํ๋ฉฐ, ๋ฉ๋ด ๋ฐ์ดํฐ๋ฅผ Elasticsearch์ ์ ์ฅํ๊ณ ๊ฒ์์ด ๊ฐ๋ฅํ๋๋ก ๊ตฌํํ์ต๋๋ค.
-
๊ฐ๊ฒ ๋ฐ ๋ฉ๋ด ๋ณ๊ฒฝ์ฌํญ์ ๋ฐ๋ฅธ ์ ๋ฐ์ดํธ
- ๊ฐ๊ฒ ์์ฑ, ์ญ์ , ์์ , ๋ณ๊ฒฝ ์ Elasticsearch์ ์ฆ์ ๋ฐ์.
- ๋ฉ๋ด ์์ฑ, ์์ , ์ญ์ , ๋ณ๊ฒฝ ์์๋ ๋์ผํ๊ฒ ์ฆ์ ๋ฐ์.
-
ํ์ฌ ๋ฐ์ดํฐ ์ ๋ฐ์ดํธ
- ๋ฐ์ดํฐ๊ฐ ์ ๊ธฐ ๋๋ฌธ์ ๋ณ๊ฒฝ์ฌํญ ๋ฐ์ ์ ๋ฐ๋ก ์ ๋ฐ์ดํธ๋ฅผ ์ํ.
- ์ถํ ๋ฐ์ดํฐ๊ฐ ๋ง์์ง๋ฉด, ๋ณ๊ฒฝ์ฌํญ์ ๋ชจ์ Bulk Update ๋ฐฉ์์ผ๋ก ์ ํํ ์์ .
-
copy_toํ์ฉ- ๋ฉ๋ด ๋ฐ์ดํฐ๋ฅผ
copy_to๋กfull_textํ๋์ ์ ์ฅํ์ฌ, ๊ธฐ์กด ์ฟผ๋ฆฌ๋ฅผ ์์ ํ์ง ์๊ณ ๋ ๊ฒ์์ด ๊ฐ๋ฅํ๋๋ก ์ค์ .
- ๋ฉ๋ด ๋ฐ์ดํฐ๋ฅผ
์๋์ ๊ฐ์ ๋ฐฉ์์ผ๋ก ๊ฐ๊ฒ ์ ๋ณด์ ๋ฉ๋ด ์ ๋ณด๊ฐ Elasticsearch์ ์ ์ฅ๋์ด ์์ต๋๋ค.
-
์๋ฉ๋ฆฌ์นด๋ ธ๊ฒ์ -
์์ด์ค ์๋ฉ๋ฆฌ์นด๋ ธ๊ฒ์
- ๋ฉ๋ด ๋ฐ์ดํฐ๋ฅผ Elasticsearch์ ์ ์ฅํ๋ฉด์ ๊ธฐ์กด ๊ฒ์ ์ฟผ๋ฆฌ๋ฅผ ์์ ํ์ง ์์๋
full_textํ๋์์ ๋ฉ๋ด ๊ฒ์์ด ๊ฐ๋ฅํด์ก์ต๋๋ค. - ๊ฒ์ ๊ฒฐ๊ณผ๊ฐ ์ ํํ๊ฒ ๋ฐํ๋๋ ๊ฒ์ ํ์ธํ์ต๋๋ค.
- ํ์ฌ๋ ๋ฐ์ดํฐ๊ฐ ์ ์ด ๊ฐ๊ฒ ๋ฐ ๋ฉ๋ด์ ๋ํด update๊ฐ ์์ผ๋ฉด ์ฆ์, ์๋ผ์คํฑ ์์น์ crud ์์ฒญ์ ๋ณด๋ด์ง๋ง, ์ถํ์ ์์ธ ๋ฐ์ดํฐ๊ฐ ๋ง์์ง๋ค๋ฉด Bulk Update ๋ฐฉ์์ผ๋ก์ ์ ํ์ ๊ณ ๋ ค ์ค์ ๋๋ค.
| ์ด๋ฆ | ํฌ์ง์ | Github ๋งํฌ |
|---|---|---|
| ํฉํธ์ง | ๋ฆฌ๋ | [๐https://github.com/ballqs] |
| ์ ์ฌํธ | ๋ถ๋ฆฌ๋ | [๐https://github.com/Nameless1004] |
| ์กฐ์ํ | ํ์ | [๐https://github.com/SuHyun-git] |
| ๊น์ค์ | ํ์ | [๐https://github.com/yunseokim119] |
| ๊ธธ์ฉ์ง | ํ์ | [๐https://github.com/pumaclass/] |
-
๋ฌธ์ ๋ฐ์ ์ ์ฆ์ ๊ณต์
- ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ฉด ํ์๋ค์๊ฒ ๋น ๋ฅด๊ฒ ์ํฉ์ ๊ณต์ ํ์ฌ ํ๋ ฅ ํด๊ฒฐ.
-
์ผ์ ๋ฌด์กฐ๊ฑด ์งํค๊ธฐ
- ์ผ์ ๋ณ๋ ์ ์ฌ๋ ๊ณต์ ๋ฐ ์ฃผ๋ง ํ์ฉํ ๊ฒ.
-
์ฌ์ํ ๊ฒ๋ ์ง๋ฌธํ๊ธฐ
- ๊ถ๊ธํ ์ ์ด๋ ๋งํ ๋ถ๋ถ์ ์ฌ์ํ ๊ฒ์ด๋ผ๋ ์ฆ์ ๋ฌผ์ด๋ณด๊ณ ํด๊ฒฐ.
-
์คํฌ๋ผ์์ ํธ๋ฌ๋ธ ์ํ ๋ฐ ๊ตฌํ ์ฌํญ ์ค๋ช
- ๋งค์ผ ์คํฌ๋ผ ์๊ฐ์ ๊ตฌํ ์งํ ์ํฉ๊ณผ ๋ฌธ์ ํด๊ฒฐ ๊ณผ์ ์ ๊ณต์ .
-
1Day, 1Code Review, 1PR ์์น
- ํ๋ฃจ์ ํ๋ ์ด์์ ๊ตฌํํ ์ฝ๋ ๋ฆฌ๋ทฐ ๋ฐ PR ์์ฑ.
-
1PR ๋น 1์ธ ์ด์ ํ์ธ ํ ๋จธ์ง
- ๊ฐ PR์ ๋ํด ์ต์ 1๋ช ์ด์์ ์น์ธ์ ํตํด ์ฝ๋ ํ์ง์ ๊ฐ์ .
-
์ฑ๋ฅ ์ต์ ํ ์ฑ๊ณต
- Redis ์บ์ฑ์ ๋์ ํด 1048.9ms์์ 4.32ms๋ก ์ฝ 24278% ํฅ์์ํด
- Like , ์กฐํ์ ๊ธฐ๋ฅ์ ์ด๋น 1000๋ฒ ์ ๊ทผ์ด ๋์ด๋ ๋ฌธ์ ์์ด ๋์
-
ํจ์จ์ ์ธ ํ์
- ํ์ ๊ฐ ์ญํ ๋ถ๋ด์ด ๋ช ํํ์ผ๋ฉฐ, GitHub Actions , Jenkins์ ํ์ฉํ CI/CD ๊ตฌ์ถ์ผ๋ก ๊ฐ๋ฐ-๋ฐฐํฌ ์ฃผ๊ธฐ๋ฅผ ๋จ์ถ.
- ๋งค์ผ ์คํฌ๋ผ์ ํตํด ๋ฌธ์ ๋ฅผ ๋น ๋ฅด๊ฒ ๊ณต์ ํ๊ณ , ์ ๊ทน์ ์ผ๋ก ํด๊ฒฐ.
- GitHub์ commit์ ๊ตฌ๋ถํ์ฌ ํด๋น commit์ด ๋ฌด์์ ์๋ฏธํ๋์ง ์ฝ๊ฒ ํ์ ๊ฐ๋ฅ
- ์์ฌ์ํต์ด ์๋์์ง๋ง ์ ์ฑ
์ ์ธ ๋ถ๋ถ์ ๋ํด ์ง์๋ถ์กฑ์ผ๋ก ์๊ฒฌ์ถฉ๋์ด ์ฆ์.
- ๋ฐฑ์๋์ ํ๋ก ํธ์๋๊ฐ์ ๊ธฐ๋ฅ ๊ตฌํ ์๊ฒฌ ์ถฉ๋์ ์ํด์ ๋น๊ต์ ์๊ฐ์ ๋ง์ด ์์๋ค.
-
๊ธฐ์ ์ ๊ณ ๋ํ
- ๋ฌด์ค๋จ ๋ฐฐํฌ๋ฅผ ์ํ ์ถ๊ฐ์ ์ธ CI/CD ๊ฐ์ ๊ณํ
- ์๋ผ์คํฑ์์น๋ฅผ ํตํด ํฌ๋กค๋ง์ ์ ์ฑ ํ๊ธฐ ๋ฐ ์ ํ์ง ๊ฒ์ ๊ฒฐ๊ณผ ํํฐ๋ง ์์
-
์ถ๊ฐ ๊ธฐ๋ฅ ๊ฐ๋ฐ
- WebFlux๋ฅผ ๋์ ํด ๋ฆฌ์กํฐ๋ธํ๋ก๊ทธ๋๋ฐ์ผ๋ก I/O๊ธฐ๋ฅ์ ๋ชจ๋๋ก ๋นผ๋ ์์
- MSA๋ฅผ ๊ณต๋ถํ์ฌ ์ฌ๋ฌ ๊ฐ์ ์์ ์๋น์ค๋ก ๋๋ ๋ฐฐํฌํ๊ธฐ
-
ํ ์คํธ ์๋ํ ๊ฐํ
- ๊ธฐ์กด ๋จ์ ํ ์คํธ ์ธ์ ํตํฉ ํ ์คํธ ๋ฐ ๋ถํ ํ ์คํธ๋ฅผ ์ถ๊ฐํ์ฌ ์์ ์ฑ์ ๋์ฑ ๊ฐํ.
https://www.figma.com/design/XC7jH231J14F6BCBdgOsf1/Untitled?node-id=0-1&t=VN6XSThorsDXxCW2-1











































