[๐Ÿ”ฅTroubleShooting - MoodBuddy๐Ÿ”ฅ] ๋„ˆ์˜ ์ฟผ๋””ํ‹ฐ์•„์ด๋Š” ๋ญ๋‹ˆ?!

._mungยท2025๋…„ 3์›” 9์ผ
0

MoodBuddy

๋ชฉ๋ก ๋ณด๊ธฐ
3/8

๐Ÿ“Œ ํ”„๋กœ์ ํŠธ ์†Œ๊ฐœ

ํŒ€์› : PM(1) / Design(1) / Frontend(2) / Backend(3)
๊ธฐ๊ฐ„ : 2024.03 ~ 2025.03
๋งํฌ : https://github.com/M-ung/MoodBuddy_Server
์„œ๋น„์Šค ๋‚ด์šฉ : ์‚ฌ์šฉ์ž๊ฐ€ ์ž‘์„ฑํ•œ ์ผ๊ธฐ๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ๊ฐ์ • ๋ถ„์„ํ•˜๋Š” ์›น ์„œ๋น„์Šค
์†Œํ†ต : GitHub, Slack, Notion, Discord


๐Ÿ”ฅTroubleShooting๐Ÿ”ฅ

Problems

์šฐ๋ฆฌ ์„œ๋น„์Šค 'MoodBuddy" ์—๋Š” ํŠน๋ณ„ํ•œ ๊ธฐ๋Šฅ์ด ์žˆ๋‹ค. ๋ฐ”๋กœ "์ฟผ๋””ํ‹ฐ์•„์ด(QuddyTI)" ์ด๋‹ค.

์ฟผ๋””ํ‹ฐ์•„์ด(QuddyTI)๋ž€?
๋‹จ์ˆœํžˆ MBTI๋ฅผ ์ƒ๊ฐํ•˜๋ฉด ๋œ๋‹ค.
์‚ฌ์šฉ์ž๊ฐ€ ํ•œ ๋‹ฌ ๋™์•ˆ ์ž‘์„ฑํ•œ ์ผ๊ธฐ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ "์ผ๊ธฐ ์ž‘์„ฑ ํšŸ์ˆ˜, ์ผ๊ธฐ ๋ถ„์„์„ ํ†ตํ•ด ๋‚˜์˜จ ๊ฐ์ •, ์ฃผ์ œ" ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์ผ๊ธฐ ์„ฑ๊ฒฉ ์œ ํ˜•์„ ํŒ๋ณ„ํ•ด์ฃผ๋Š” ์„œ๋น„์Šค์ด๋‹ค.
์ด๋Š” ํ•œ ๋‹ฌ ๊ธฐ๋ฐ˜์œผ๋กœ ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์™€์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋งค๋‹ฌ 00์‹œ์— ์ฟผ๋””ํ‹ฐ์•„์ด(QuddyTI) ์ƒ์„ฑ(ํ˜„์žฌ ๋‹ฌ) ๋ฐ ์ˆ˜์ •(์ง€๋‚œ ๋‹ฌ)์ด ๋ฐœ์ƒํ•œ๋‹ค.

์ฒ˜์Œ 1์ฐจ ๋ฐฐํฌ ๋•Œ๋Š” ๋‹จ์ˆœํžˆ ์Šค์ผ€์ค„๋Ÿฌ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์•„๋ž˜์™€ ๊ฐ™์ด ๊ตฌํ˜„ํ–ˆ๋‹ค.

@Component
@RequiredArgsConstructor
public class QuddyTIScheduler {
    private final QuddyTIFacade quddyTIFacade;

    @Scheduled(cron = "0 0 0 1 * ?")
    @Transactional
    public void aggregateAndSaveDiaryData() {
        quddyTIFacade.createAndUpadteQuddyTI();
    }
}

์Šค์ผ€์ค„๋Ÿฌ๋ฅผ ๋Œ๋ ค ๋งค๋‹ฌ 00์‹œ์— ๋™์ž‘ํ•˜๋„๋ก ๊ตฌํ˜„ํ–ˆ๋‹ค.

ํ•˜์ง€๋งŒ ์•„๋ž˜์™€ ๊ฐ™์€ ๋ฌธ์ œ์ ๋“ค์ด ๋ฐœ์ƒํ–ˆ๋‹ค.

1. ํ•œ ๋ฒˆ์— ๋ชจ๋“  ์‚ฌ์šฉ์ž์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋ ค๋‹ค ๋ณด๋‹ˆ ๋ฐ์ดํ„ฐ๊ฐ€ ๋งŽ์•„์งˆ์ˆ˜๋ก ์ฟผ๋ฆฌ ๋ถ€ํ•˜ ์ฆ๊ฐ€
2. ํŠธ๋žœ์žญ์…˜์ด ๊ธธ์–ด์ง€๊ณ , ์ „์ฒด ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„์ด ๋Š˜์–ด๋‚˜๋ฉด์„œ ์„œ๋ฒ„ ๋ถ€ํ•˜ ๋ฐœ์ƒ
3. ์‚ฌ์šฉ์ž๊ฐ€ ๋งŽ์•„์งˆ์ˆ˜๋ก ๋ฐ์ดํ„ฐ ์ฆ๊ฐ€๋กœ ์ธํ•ด ํ•˜๋‚˜์˜ ์Šค์ผ€์ค„๋Ÿฌ์—์„œ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ์‹์ด ์ ์  ๋ถ€๋‹ด์Šค๋Ÿฌ์›Œ์ง


How

๊ทธ๋ž˜์„œ ์œ„ ๋ฌธ์ œ๋“ค์„ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด "Spring Batch" ๋ฅผ ์šฐ๋ฆฌ ์„œ๋น„์Šค์— ๋„์ž…ํ•˜๊ธฐ๋กœ ํ–ˆ๋‹ค.

Spring Batch๋ž€?
Spring Batch๋Š” ๋Œ€๋Ÿ‰์˜ ๋ฐ์ดํ„ฐ๋ฅผ ํšจ๊ณผ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋„๋ก ์„ค๊ณ„๋œ ๋ฐฐ์น˜ ์ฒ˜๋ฆฌ ํ”„๋ ˆ์ž„์›Œํฌ๋‹ค.
์Šค์ผ€์ค„๋Ÿฌ๊ฐ€ ๋‹จ์ˆœ ๋ฐ˜๋ณต ์‹คํ–‰์„ ํ•˜๋Š” ๊ฒƒ๊ณผ ๋‹ฌ๋ฆฌ, ๋Œ€๋Ÿ‰ ๋ฐ์ดํ„ฐ๋ฅผ ํšจ์œจ์ ์œผ๋กœ ๋‚˜๋ˆ„์–ด ์ฒ˜๋ฆฌํ•˜๊ณ , ์žฌ์‹œ๋„ ๋ฐ ์‹คํŒจ ๋ณต๊ตฌ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•œ๋‹ค.

Spring Batch์˜ ํ•ต์‹ฌ ๊ฐœ๋…
1. Job: ํ•˜๋‚˜์˜ ๋ฐฐ์น˜ ์ž‘์—… ๋‹จ์œ„
2. Step: Job์„ ๊ตฌ์„ฑํ•˜๋Š” ๊ฐœ๋ณ„ ๋‹จ๊ณ„
3. ItemReader: ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ๋Š” ์—ญํ• 
4. ItemProcessor: ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€๊ณตํ•˜๋Š” ์—ญํ• 
5. ItemWriter: ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๋Š” ์—ญํ• 

์œ„ "Spring Batch" ๋ฅผ ์ ์šฉํ•˜๊ฒŒ ๋˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™์€ ๊ธฐ๋Œ€ ํšจ๊ณผ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค.

1. ์„ฑ๋Šฅ ๊ฐœ์„ : ์ž‘์€ ๋‹จ์œ„๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜์—ฌ DB ๋ถ€ํ•˜ ๊ฐ์†Œ
2. ์•ˆ์ •์„ฑ ํ–ฅ์ƒ: ์‹คํŒจํ•œ ์ž‘์—…์„ ์ž๋™์œผ๋กœ ์žฌ์‹œ๋„ ๊ฐ€๋Šฅ


Process

๋จผ์ € ๊ธฐ์กด ์Šค์ผ€์ค„๋Ÿฌ๋Š” Spring Batch์˜ ํŠธ๋ฆฌ๊ฑฐ ์—ญํ• ์„ ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋ณ€๊ฒฝํ•œ ํ›„ ์•„๋ž˜์™€ ๊ฐ™์ด ์„ค๊ณ„ํ–ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  Spring Data JPA๋ฅผ ํ™œ์šฉํ•ด์„œ ์ƒ์„ฑ, ์ˆ˜์ •, ์กฐํšŒ๋ฅผ ํ•ด๊ฒฐํ•˜๋ ค๊ณ  ํ–ˆ๋‹ค.

ํ•˜์ง€๋งŒ Spring Data JPA๋ฅผ ํ™œ์šฉํ•œ ๋ฐฉ์‹์—๋Š” ์•„๋ž˜์™€ ๊ฐ™์€ ๋ฌธ์ œ์ ๋“ค์ด ์žˆ์—ˆ๋‹ค.

1. ๋Œ€๋Ÿ‰ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ์‹œ ์„ฑ๋Šฅ ์ €ํ•˜
2. JPA์˜ ๊ธฐ๋ณธ์ ์ธ Bulk Update/Insert์˜ ํ•œ๊ณ„

๊ทธ๋ž˜์„œ Spring Data JPA ๋ณด๋‹ค JDBC ๋ฐฉ์‹์œผ๋กœ ์ƒ์„ฑ, ์ˆ˜์ •, ์กฐํšŒ๋ฅผ ๊ตฌํ˜„ํ•˜์˜€๋‹ค.
์ฝ”๋“œ๋Š” ์•„๋ž˜์™€ ๊ฐ™๋‹ค.
๋˜ํ•œ, ์ฟผ๋””ํ‹ฐ์•„์ด ์ž‘์—…์„ ํ•˜๋‚˜๋กœ ํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹Œ, ์ƒ์„ฑ๊ณผ ์ˆ˜์ • ์ž‘์—…์„ ๋‘ ๊ฐœ๋กœ ๋ถ„๋ฆฌํ•˜์—ฌ DB ๋ถ€ํ•˜๋ฅผ ๋ถ„์‚ฐํ•˜๊ธฐ๋กœ ํ–ˆ๋‹ค.

์Šค์ผ€์ค„๋Ÿฌ๋Š” ๋‘ ๊ฐœ๋กœ ๋‚˜๋ˆด๋”๋ผ๋„ ๊ฐ™์€ ์‹œ๊ฐ„์— ์‹คํ–‰ํ•˜๋ฉด ์œ„์™€ ๊ฐ™์€ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ƒ์„ฑ๊ณผ ์ˆ˜์ • ์Šค์ผ€์ค„๋Ÿฌ๋ฅผ ๊ฐ๊ฐ ๋‹ค๋ฅธ ๋งค๋‹ฌ ๋ง์ผ๊ณผ 1์ผ๋กœ ๋ถ„๋ฆฌํ•ด์„œ ์‹คํ–‰ํ•˜๋„๋ก ์„ค๊ณ„ํ–ˆ๋‹ค.


Result

๋ฌธ์ œ ํ•ด๊ฒฐ๋กœ ์•„๋ž˜์™€ ๊ฐ™์€ ๊ฒฐ๊ณผ๋ฅผ ์–ป์—ˆ๋‹ค.
1. ์‚ฌ์šฉ์ž 10,000๋ช… ๊ธฐ์ค€, ์ฟผ๋””ํ‹ฐ์•„์ด ์ƒ์„ฑ ํ‰๊ท  ์•ฝ 919ms, ์ˆ˜์ • ํ‰๊ท  ์•ฝ 14,528ms๋กœ ์„ฑ๋Šฅ ๊ฐœ์„ .
2. ์Šค์ผ€์ค„๋Ÿฌ โ†’ Spring Batch ํŠธ๋ฆฌ๊ฑฐ ๋ฐฉ์‹์œผ๋กœ ์ „ํ™˜ํ•˜์—ฌ ์œ ์ง€๋ณด์ˆ˜์„ฑ์„ ํ–ฅ์ƒ.
3. JPA ๋Œ€์‹  JDBC ์‚ฌ์šฉ์œผ๋กœ ๋”ํ‹ฐ ์ฒดํ‚น ์˜ค๋ฒ„ํ—ค๋“œ๋ฅผ ์ œ๊ฑฐํ•˜๊ณ  batch ์„ฑ๋Šฅ ์ตœ์ ํ™”.
4. ์ฟผ๋””ํ‹ฐ์•„์ด ์ƒ์„ฑ๊ณผ ์ˆ˜์ • ์ž‘์—…์„ ๋ถ„๋ฆฌํ•˜์—ฌ DB ๋ถ€ํ•˜๋ฅผ ๋ถ„์‚ฐ


Thoughts

์ด๋ฒˆ Spring Batch ๋„์ž…์„ ํ†ตํ•ด ์Šค์ผ€์ค„๋Ÿฌ ๊ธฐ๋ฐ˜์˜ ๋Œ€๋Ÿ‰ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ๋ฅผ ๊ฐœ์„ ํ•˜๋Š” ๊ฒฝํ—˜์„ ํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค.

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

์œ„ ๊ฒฝํ—˜๋“ค์„ ํ†ตํ•ด ๋Œ€๋Ÿ‰ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ๋Š” ๋‹จ์ˆœํžˆ ์Šค์ผ€์ค„๋Ÿฌ๋กœ ์ ์šฉํ•ด์•ผ๊ฒ ๋‹ค๋Š” ์ƒ๊ฐ๋ณด๋‹จ Spring Batch์™€ ๊ฐ™์€ ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์ ์šฉํ•˜๋Š” ๊ฒƒ์ด ํ•„์ˆ˜์ ์ด๋ผ๋Š” ์ƒ๊ฐ์„ ํ–ˆ๋‹ค.

๋˜ Spring Data JPA์˜ ํŽธ๋ฆฌ์„ฑ์œผ๋กœ ์ธํ•ด ์ด์— ์˜์กดํ•˜๊ธฐ๋ณด๋‹จ ์•Œ๊ณ  ์“ฐ๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•˜๋‹ค๋Š” ๊ฒƒ์„ ๊นจ๋‹ฌ์•˜๋‹ค. ๋ถˆํŽธํ•˜๋”๋ผ๋„ ์„ฑ๋Šฅ์ ์œผ๋กœ ๋–จ์–ด์ง€๋ฉด JDBC์™€ ๊ฐ™์€ ๊ธฐ์ˆ ์„ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์„ค๊ณ„ ๋Šฅ๋ ฅ์„ ๊ฐ–์ถ˜ ๊ฐœ๋ฐœ์ž๊ฐ€ ๋˜์–ด์•ผ๊ฒ ๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ๋‹ค.


profile
๐Ÿ’ป ๐Ÿ’ป ๐Ÿ’ป

0๊ฐœ์˜ ๋Œ“๊ธ€

๊ด€๋ จ ์ฑ„์šฉ ์ •๋ณด