[์Šคํ”„๋ง] ์Šคํ”„๋ง ์ด๋ฒคํŠธ๋Š” ์–ธ์ œ ์จ์•ผํ• ๊นŒ?

2025. 4. 2. 13:51ยท๐ŸŽฏ Programming
๋ฐ˜์‘ํ˜•
๊ธฐ์กด ํ”„๋กœ์ ํŠธ์—์„œ Service ๊ฐ„ ์˜์กด์„ฑ์ด ์ƒ๊ธฐ๋Š” ๋ถ€๋ถ„์ด ๊ณ ๋ฏผ์ด์—ˆ๊ณ ,
์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ์Šคํ”„๋ง ์ด๋ฒคํŠธ๋ฅผ ์ ์šฉํ•ด ๋ดค์Šต๋‹ˆ๋‹ค.

 

โœ… ํ”„๋กœ์ ํŠธ ์ƒํ™ฉ

"๋‚ด๋ถ€ ์•Œ๋ฆผ ๊ธฐ๋Šฅ"์ด ์„œ๋น„์Šค์— ํ•„์š”ํ–ˆ์Šต๋‹ˆ๋‹ค.

์ฆ‰, ์œ ์ €๊ฐ€ ์„œ๋น„์Šค์— ์ ‘์†ํ–ˆ์„ ๋•Œ ์•Œ๋ฆผ์ด ์Œ“์—ฌ ์žˆ๊ณ  ์ด๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋Š” ํ™”๋ฉด์ด ํ•„์š”ํ–ˆ์Šต๋‹ˆ๋‹ค.

 

Alarm ํ™”๋ฉด
์•Œ๋ฆผ ํ™”๋ฉด

 

์‚ฌ์šฉ์ž์—๊ฒŒ ์•Œ๋ฆผ์ด ๋„์ฐฉํ•˜๋Š” ์ƒํ™ฉ์€ ๋‹ค์Œ 3๊ฐ€์ง€ ๊ฒฝ์šฐ์˜€์Šต๋‹ˆ๋‹ค.

  1. ๋ฆฌ๋ทฐ ์š”์ฒญ
  2. ํ”„๋กœ์ ํŠธ ํŒ€์› ์ดˆ๋Œ€
  3. ํŒ€์› ์ดˆ๋Œ€ ์ˆ˜๋ฝ

๐Ÿ“ Alarm ํ…Œ์ด๋ธ”

ํ•ด๋‹น ๊ธฐ๋Šฅ์— ํ•„์š”ํ•œ ์•Œ๋žŒ ํ…Œ์ด๋ธ”์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์„ค๊ณ„ํ–ˆ์Šต๋‹ˆ๋‹ค.

 

Alarm table
Alarm ํ…Œ์ด๋ธ”

 

์ฃผ์š” ํ•„๋“œ๋กœ๋Š” 

  • `receiver_id`: ์•Œ๋žŒ์€ ๋ฐ›๋Š” ์‚ฌ๋žŒ ID
  • `sender_id`: ์•Œ๋žŒ์„ ๋ณด๋‚ธ ์‚ฌ๋žŒ ID
  • `targetId`: ์•Œ๋ฆผ์ด ๋ฐœ์ƒํ•œ 3๊ฐ€์ง€ ์ƒํ™ฉ ๊ฐ๊ฐ์—์„œ ์—ฐ๊ด€๋œ ์—”ํ‹ฐํ‹ฐ์˜ ID
  • `message`: ์•Œ๋žŒ ๋ฉ˜ํŠธ
  • `alarm_type`: ์•Œ๋žŒ์ด ๋ฐœ์ƒํ•œ ์ƒํ™ฉ(๋ฆฌ๋ทฐ ์š”์ฒญ, ํŒ€์› ์ดˆ๋Œ€, ์ดˆ๋Œ€ ์ˆ˜๋ฝ)

 

์ด๋ฅผ ์—”ํ‹ฐํ‹ฐ๋กœ ๊ตฌํ˜„ํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

 

Alarm Entity
Alarm ์—”ํ‹ฐํ‹ฐ


๐Ÿ“ ๋ฆฌ๋ทฐ ์š”์ฒญ ์•Œ๋ฆผ ์ƒ์„ฑ ๋กœ์ง

์•Œ๋ฆผ์ด ์ƒ์„ฑ๋˜๋Š” 3๊ฐ€์ง€ ์ƒํ™ฉ ์ค‘, ์ œ๊ฐ€ ๋‹ด๋‹นํ•œ "๋ฆฌ๋ทฐ ์š”์ฒญ" ์•Œ๋ฆผ ์ƒ์„ฑ ๋กœ์ง์— ๋Œ€ํ•ด ์„ค๋ช…๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค.

Service logic
ReviewService์™€ AlarmService

 

ํ•œ ์œ ์ €๊ฐ€ ๋‹ค๋ฅธ ์œ ์ €์—๊ฒŒ ๋ฆฌ๋ทฐ๋ฅผ ์š”์ฒญํ•˜๋ฉด, ReviewService์˜ requestReview ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ๊ทธ ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ, AlarmService์˜ createAlarm ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค.

 

์ฆ‰, ReviewService ๋‚ด๋ถ€์—์„œ AlarmService์˜ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๊ธฐ ์œ„ํ•ด, AlarmService ๊ฐ์ฒด๋ฅผ ํ•„๋“œ๋กœ ๊ฐ€์ง€๊ณ  ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

 

ํ”„๋กœ์ ํŠธ ํŒ€์› ์ดˆ๋Œ€์™€ ์ดˆ๋Œ€ ์ˆ˜๋ฝ ์ƒํ™ฉ์—์„œ๋„ ๋งˆ์ฐฌ๊ฐ€์ง€์ž…๋‹ˆ๋‹ค.

 

ProjectService์˜ ๊ฐ ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋˜๊ณ , ๊ทธ ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ AlarmService์˜ createAlarm ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค.

ProjectService๋„ AlarmService ๊ฐ์ฒด๋ฅผ ํ•„๋“œ๋กœ ๊ฐ€์ง€๊ณ  ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

 


๊ทธ๋Ÿผ ๊ฐ ๋„๋ฉ”์ธ(Review, Project)์˜ ์„œ๋น„์Šค ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ฒŒ ์•„๋‹ˆ๋ผ,
๋ฐ”๋กœ AlarmService์˜ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ์•ˆ ๋˜๋Š” ๊ฑธ๊นŒ์š”?

 

๊ทธ๋ ‡๊ฒŒ ํ•˜๊ฒŒ ๋˜๋ฉด ๋˜ ๋‹ค๋ฅธ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. 

  • ์˜ˆ๋ฅผ ๋“ค์–ด 'ํ”„๋กœ์ ํŠธ ํŒ€์› ์ดˆ๋Œ€' ์ƒํ™ฉ์—์„œ๋Š” ๋‹จ์ˆœํžˆ ์•Œ๋ฆผ๋งŒ ๋ณด๋‚ด๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ, ProjectMember ๊ฐ์ฒด๋„ ์ƒˆ๋กœ ์ƒ์„ฑํ•ด์„œ DB์— ์ €์žฅํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ์ด ์ž‘์—…์„ AlarmService์—์„œ ์ฒ˜๋ฆฌํ•˜๊ฒŒ ๋˜๋ฉด, ProjectMember ์ƒ์„ฑ๊ณผ ์ €์žฅ ๋กœ์ง์ด AlarmService๋กœ ๋“ค์–ด๊ฐ€๊ฒŒ ๋˜๊ณ , ์ด๋Š” ๋˜ ๋‹ค๋ฅธ ์˜์กด์„ฑ ๋ฌธ์ œ๋กœ ์ด์–ด์ง‘๋‹ˆ๋‹ค.
  • ์•Œ๋žŒ ์ƒ์„ฑ์„ ํ•˜๊ธฐ ์ „์— targetId๊ฐ€ ์œ ํšจํ•œ์ง€ ๊ฒ€์ฆํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. targetId์—๋Š” proejct, reviewForm, reviewRecord์˜ ID๊ฐ€ ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋งŒ์•ฝ ์ด ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๋ฅผ AlarmService์—์„œ ์ฒ˜๋ฆฌํ•œ๋‹ค๋ฉด AlarmService๊ฐ€ proejctRepository, reviewFormRepository, reviewRecordReposistory๋ฅผ ๋ชจ๋‘ ์˜์กดํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ๋„๋ฉ”์ธ์˜ ๋ ˆํฌ์ง€ํ† ๋ฆฌ์— ์ง์ ‘ ์ฐธ์กฐํ•˜์—ฌ์•ผ DB์—์„œ ์กฐํšŒํ•ด ์˜ค๋Š” ๊ฒƒ๋„ ๋˜ ๋‹ค๋ฅธ ์˜์กด์„ฑ ๋ฌธ์ œ์ž…๋‹ˆ๋‹ค.

 


โœ… ๋ฌธ์ œ์ 

์œ„ ์ƒํ™ฉ์„ ๋„์‹ํ™”ํ•˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

 

Before Event Flow
์ด๋ฒคํŠธ ์ ์šฉ ์ „ ๋ชจ์Šต

 

 

์ด์ฒ˜๋Ÿผ Service๊ฐ€ ๋‹ค๋ฅธ Service์— ์˜์กดํ•˜๋ฉด ์–ด๋–ค ๋ฌธ์ œ์ ์ด ์žˆ์„๊นŒ์š”?

 

  1. ๋„๋ฉ”์ธ ๊ฐ„์˜ ๊ฐ•ํ•œ ๊ฒฐํ•ฉ๋„
  2. ๋‹จ์ผ ์ฑ…์ž„ ์›์น™(SRP) ์œ„๋ฐฐ
  3. ์ข‹์ง€ ์•Š์€ ํ™•์žฅ์„ฑ

 


๐Ÿ“ ๋„๋ฉ”์ธ ๊ฐ„์˜ ๊ฐ•ํ•œ ๊ฒฐํ•ฉ๋„

ํ˜„์žฌ Review-Alarm๊ณผ Project-Alarm ๋„๋ฉ”์ธ ์‚ฌ์ด์— ๊ฒฐํ•ฉ๋„๊ฐ€ ๊ฐ•ํ•˜๋‹ค๊ณ  ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋งŒ์•ฝ Alarm ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋กœ์ง์„ ๋ณ€๊ฒฝํ•˜๋ฉด, ์ด๋Š” ReviewService์™€ ProjectService์—๋„ ์˜ํ–ฅ์„ ์ค๋‹ˆ๋‹ค.

 


๐Ÿ“ ๋‹จ์ผ ์ฑ…์ž„ ์›์น™(SRP) ์œ„๋ฐฐ

๋‹จ์ผ ์ฑ…์ž„ ์›์น™์ด๋ž€, ํด๋ž˜์Šค๊ฐ€ ๋‹จ ํ•˜๋‚˜์˜ ์ฑ…์ž„๋งŒ ๋งก์•„์•ผ ํ•œ๋‹ค๋Š” ์›์น™์ž…๋‹ˆ๋‹ค.

์ฆ‰, "์–ด๋–ค ํด๋ž˜์Šค๋ฅผ ๋ณ€๊ฒฝํ•ด์•ผ ํ•˜๋Š” ์ด์œ ๋Š” ์˜ค์ง ํ•˜๋‚˜"๋ผ๋Š” ์˜๋ฏธ์ž…๋‹ˆ๋‹ค.

 

ํ˜„์žฌ ReviewService์—๋Š” 2๊ฐ€์ง€์˜ ์ฑ…์ž„์ด ์žˆ์Šต๋‹ˆ๋‹ค.

Review ๊ด€๋ จ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ์ฒ˜๋ฆฌํ•˜๋Š” ์ฑ…์ž„ + Alarm์„ ์ƒ์„ฑํ•˜๋Š” ์ฑ…์ž„

 

createAlarm ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ํ–‰์œ„๋Š” ๊ฒฐ๊ตญ "๋ฆฌ๋ทฐ ์š”์ฒญ ์•Œ๋ฆผ์„ ์ƒ์„ฑํ•˜๋ผ!"๋Š” ๋ช…๋ น์„ ๋‚ด๋ฆฌ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
์ฆ‰, ์•Œ๋žŒ ์ƒ์„ฑ์ด๋ผ๋Š” ํ–‰์œ„๊ฐ€ ReviewService ๋‚ด๋ถ€์—์„œ ์ผ์–ด๋‚˜๊ณ  ์žˆ๋‹ค๋Š” ์‚ฌ์‹ค๋งŒ์œผ๋กœ๋„, ์•Œ๋ฆผ ์ƒ์„ฑ์— ๋Œ€ํ•œ ์ฑ…์ž„์ด ReviewService์— ์กด์žฌํ•œ๋‹ค๊ณ  ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 


๐Ÿ“ ์ข‹์ง€ ์•Š์€ ํ™•์žฅ์„ฑ

ํ˜„์žฌ๋Š” ํŠน์ • ์ƒํ™ฉ์ด ๋ฐœ์ƒํ–ˆ์„ ๋•Œ ์„œ๋น„์Šค ๋‚ด๋ถ€ ์•Œ๋žŒ๋งŒ ์ƒ์„ฑํ•˜๋Š” ๊ตฌ์กฐ์ž…๋‹ˆ๋‹ค.

 

ํ•˜์ง€๋งŒ ๋งŒ์•ฝ ์„œ๋น„์Šค ๋‚ด๋ถ€ ์•Œ๋žŒ๊ณผ ํ•จ๊ป˜ ์ด๋ฉ”์ผ ์•Œ๋ฆผ๋„ ํ•จ๊ป˜ ๋ณด๋‚ด๊ณ  ์‹ถ๋‹ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผ ํ• ๊นŒ์š”?


๊ฒฐ๊ตญ EmailService๋ฅผ ์ƒˆ๋กœ ๋งŒ๋“ค๊ณ , ReviewService์™€ ProjectService ์•ˆ์—์„œ emailService.createEmailAlarm() ๊ฐ™์€ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๊ฒŒ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

 

์ดํ›„์— SMS ์•Œ๋ฆผ๊นŒ์ง€ ์ถ”๊ฐ€ํ•˜๊ณ  ์‹ถ์–ด ์ง„๋‹ค๋ฉด, ๋˜๋‹ค์‹œ SmsService๋ฅผ ๋งŒ๋“ค๊ณ , ReviewService์™€ ProjectService๊ฐ€ ์ด ์„œ๋น„์Šค์—๋„ ์˜์กดํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

์ด๋Ÿฐ ์‹์œผ๋กœ ์•Œ๋ฆผ ์ˆ˜๋‹จ์ด ๋Š˜์–ด๋‚  ๋•Œ๋งˆ๋‹ค ์„œ๋น„์Šค๋Š” ์ ์  ๋” ๋งŽ์€ ์ฑ…์ž„์„ ๊ฐ€์ง€๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

 


โœ… ์Šคํ”„๋ง ์ด๋ฒคํŠธ

์ด๋ ‡๊ฒŒ ์˜์กด์„ฑ ๋ฌธ์ œ๊ฐ€ ์žˆ์„ ๋•Œ, ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด ๋ฐ”๋กœ ์Šคํ”„๋ง ์ด๋ฒคํŠธ์ž…๋‹ˆ๋‹ค!

 

๐Ÿ“ ๋ชฉ์ 

์˜์กด์„ฑ ๋ถ„๋ฆฌ๋ฅผ ์œ„ํ•ด

 

๐Ÿ“ ๊ตฌ์„ฑ์š”์†Œ

  • ์ด๋ฒคํŠธ(event): ํŠน์ • ์กฐ๊ฑด์ด ์ถฉ์กฑ๋˜์—ˆ์„ ๋•Œ ๋ฐœ์ƒํ•˜๋Š” ์‚ฌ๊ฑด
  • ๋ฐœํ–‰์ž(publisher): ์ด๋ฒคํŠธ๋ฅผ ๋ฐœํ–‰์‹œํ‚ด
  • ๊ตฌ๋…์ž(subscriber): ์ด๋ฒคํŠธ๋ฅผ ๊ฐ์ง€ํ•˜๊ณ  ํŠน์ • ๋™์ž‘ ์ˆ˜ํ–‰


๐Ÿ“ ํ๋ฆ„

  • `ApplicationEventPublisher`๊ฐ€ `publishEvent()`๋กœ ์ด๋ฒคํŠธ ๋ฐœํ–‰
  • `ApplicationContext`๊ฐ€ ๋ฐœํ–‰๋œ ์ด๋ฒคํŠธ๋ฅผ `@EventListener`๊ฐ€ ๋ถ™์–ด์žˆ๋Š” ๋ฉ”์„œ๋“œ์— ์ „๋‹ฌ
  • `@EventListener` ๋ฉ”์„œ๋“œ ๋กœ์ง ์‹คํ–‰

Event Flow


โœ… ์Šคํ”„๋ง ์ด๋ฒคํŠธ ์ ์šฉ ํ›„ ๋ฌธ์ œ ํ•ด๊ฒฐ

์Šคํ”„๋ง ์ด๋ฒคํŠธ๋ฅผ ์ ์šฉํ•œ ํ›„์˜ ๋ชจ์Šต์„ ๋„์‹ํ™”ํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

After Event Flow
์ด๋ฒคํŠธ ์ ์šฉ ํ›„ ๋ชจ์Šต

 

์Šคํ”„๋ง ์ด๋ฒคํŠธ๋ฅผ ์ ์šฉํ•˜๋ฉด ๊ณผ์—ฐ ์•ž์„œ ์–ธ๊ธ‰ํ–ˆ๋˜ 3๊ฐ€์ง€ ๋ฌธ์ œ๊ฐ€ ํ•ด๊ฒฐ๋ ๊นŒ์š”?

 

ํ•˜๋‚˜์”ฉ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.


๐Ÿ“ ํ•ด๊ฒฐ: ๋„๋ฉ”์ธ ๊ฐ„์˜ ๊ฐ•ํ•œ ๊ฒฐํ•ฉ๋„

์ค‘๊ฐ„์— `EventListener`๊ฐ€ ์ƒ๊ธฐ๋ฉด์„œ ReviewService์™€ ProjectService๋Š” AlarmService์— ์˜์กดํ•˜์ง€ ์•Š์•„๋„ ๋ฉ๋‹ˆ๋‹ค.

์ฆ‰, Alarm ์ƒ์„ฑ ๋กœ์ง์ด ๋ณ€๊ฒฝ๋˜๋”๋ผ๋„ ReviewService์™€ ProjectService์— ์˜ํ–ฅ์ด ๊ฐ€์ง€ ์•Š๋Š” ๊ฑฐ์ฃ .

 


๐Ÿ“ ํ•ด๊ฒฐ: ๋‹จ์ผ ์ฑ…์ž„ ์›์น™(SRP) ์œ„๋ฐฐ

๊ธฐ์กด์—๋Š” "์•Œ๋žŒ์„ ์ƒ์„ฑํ•ด๋ผ!"๋ผ๊ณ  ํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ReviewService์™€ ProjectService์— ์•Œ๋žŒ ์ƒ์„ฑ์˜ ์ฑ…์ž„์ด ์žˆ๋‹ค๊ณ  ํ–ˆ์Šต๋‹ˆ๋‹ค.

 

ํ•˜์ง€๋งŒ, ์ด๋ฒคํŠธ ๊ธฐ๋ฐ˜์œผ๋กœ ์ˆ˜์ •ํ•˜๋ฉด "๋ฆฌ๋ทฐ ์š”์ฒญ/ํŒ€์› ์ดˆ๋Œ€/ ์ดˆ๋Œ€ ์ˆ˜๋ฝ ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ–ˆ๋‹ค!"๋ผ๊ณ  ๋‹จ์ˆœํžˆ ์ด๋ฒคํŠธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ค๊ธฐ๋งŒ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

์•Œ๋žŒ ์ƒ์„ฑ์— ๋Œ€ํ•œ ์ฑ…์ž„์€ ๋” ์ด์ƒ ์ง€์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

 


 

๐Ÿ“ ํ•ด๊ฒฐ: ์ข‹์ง€ ์•Š์€ ํ™•์žฅ์„ฑ

์ข‹์ง€ ์•Š์€ ํ™•์žฅ์„ฑ

 

์•ž์„œ ๋งํ–ˆ๋“ฏ์ด ์ด๋ฉ”์ผ ์•Œ๋ฆผ๊ณผ ๋ฌธ์ž ์•Œ๋ฆผ์ด ์ถ”๊ฐ€๋œ๋‹ค๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ์š”?

 

๋‹จ์ˆœํžˆ `EventListener` ๋กœ์ง๋งŒ ์ถ”๊ฐ€ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค!

 

ReviewService์™€ ProjectService์˜ ๋กœ์ง์€ ์ „ํ˜€ ์ˆ˜์ •ํ•˜์ง€ ์•Š์•„๋„ ๋ฉ๋‹ˆ๋‹ค.

์—ฌ์ „ํžˆ ์ด๋ฒคํŠธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ค๊ธฐ๋งŒ ํ•˜๋ฉด ๋˜์ฃ .

 


โœ… ์ฝ”๋“œ ์ˆ˜์ • - @EventListener ํ™œ์šฉ

์ด์ œ ์Šคํ”„๋ง ์ด๋ฒคํŠธ๋ฅผ ์ ์šฉํ•˜๊ธฐ ์œ„ํ•ด ๊ธฐ์กด ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

 


๐Ÿ“ Event ํด๋ž˜์Šค ์ƒ์„ฑ

Event class

 

์•Œ๋žŒ์ด ํ•„์š”ํ•œ ์„ธ ๊ฐ€์ง€ ์ƒํ™ฉ(๋ฆฌ๋ทฐ ์š”์ฒญ, ํŒ€์› ์ดˆ๋Œ€, ์ดˆ๋Œ€ ์ˆ˜๋ฝ)์— ๋Œ€ํ•ด ์ด๋ฒคํŠธ ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค์–ด์ค๋‹ˆ๋‹ค.

 


๐Ÿ“ ReviewService์— EventPublisher ์ฃผ์ž…

Event Publisher

 

ApplicationEventPublisher๋ฅผ ํ†ตํ•ด ReviewService์—์„œ ์ด๋ฒคํŠธ๋ฅผ ๋ฐœํ–‰ํ•ฉ๋‹ˆ๋‹ค. 

 


๐Ÿ“ EventListener ํด๋ž˜์Šค ์ƒ์„ฑ

EventListener class

 

๋งˆ์ง€๋ง‰์œผ๋กœ ์ด๋ฒคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•ด ์ฃผ๋Š” EventListener ํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

`@EventListener` ์–ด๋…ธํ…Œ์ด์…˜์„ ๋ฉ”์„œ๋“œ์— ๋‹ฌ์•„์„œ, ๊ฐ ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ ์–ด๋–ค ๋กœ์ง์„ ์‹คํ–‰ํ• ์ง€ ์ •์˜ํ•ด ์ค๋‹ˆ๋‹ค.


โœ…  @EventListener ๋ฌธ์ œ

์•ž์„  ์ฝ”๋“œ์—์„œ `@EventListener`๋ผ๋Š” ์–ด๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ, ์ด ์–ด๋…ธํ…Œ์ด์…˜์—๋Š” ๋ช‡ ๊ฐ€์ง€ ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

 


๐Ÿ“ ๊ธฐ๋ณธ์ ์œผ๋กœ ๋™๊ธฐ๋กœ ๋™์ž‘

๋‹จ์ˆœํžˆ `@EventListener` ์–ด๋…ธํ…Œ์ด์…˜๋งŒ ๋‹ฌ์•„์ฃผ๋ฉด ์ด ๋ฉ”์„œ๋“œ๋Š” ๋™๊ธฐ๋กœ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.

 

ํ•˜์ง€๋งŒ ๋™๊ธฐ ๋ฐฉ์‹์—์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  1. ์„œ๋น„์Šค ๋‚ด๋ถ€ ์•Œ๋ฆผ + ์ด๋ฉ”์ผ ์•Œ๋ฆผ ๋ณด๋‚ธ๋‹ค๊ณ  ๊ฐ€์ •
  2. ๋™๊ธฐ๋กœ ๋™์ž‘ํ•˜๋ฉด ์„œ๋น„์Šค ๋‚ด๋ถ€ ์•Œ๋ฆผ ์ƒ์„ฑ ํ›„, ์ด๋ฉ”์ผ ์•Œ๋ฆผ ๋ณด๋ƒ„
  3. ์ด๋ฉ”์ผ ์•Œ๋ฆผ์ด ์˜ค๋ž˜ ๊ฑธ๋ฆฌ๋ฉด ์‚ฌ์šฉ์ž๋Š” ์ด ์‹œ๊ฐ„์„ ๋ชจ๋‘ ๊ธฐ๋‹ค๋ ค์•ผ ํ•จ

 

์ด๋Ÿฐ ๋ฌธ์ œ๋ฅผ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด, ํ•ด๋‹น ๋ฆฌ์Šค๋„ˆ ๋ฉ”์„œ๋“œ์— `@Async` ์–ด๋…ธํ…Œ์ด์…˜์„ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜์—ฌ
๋น„๋™๊ธฐ๋กœ ์ฒ˜๋ฆฌ๋˜๋„๋ก ๋ช…์‹œํ•ด ์ฃผ๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

 


๐Ÿ“Event๋ฅผ ๋ฐœํ–‰์‹œํ‚จ ๋กœ์ง๋„ ๊ฐ™์ด ๋กค๋ฐฑ 

์ดˆ๋Œ€ ์ˆ˜๋ฝ ์•Œ๋žŒ์ด ์ƒ์„ฑ๋˜๋Š” ๊ณผ์ •์—์„œ ๋งŒ์•ฝ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ–ˆ๋‹ค๊ณ  ํ•ฉ์‹œ๋‹ค. 

 

  1. ํ”„๋กœ์ ํŠธ ๋ฉค๋ฒ„ ์ดˆ๋Œ€๋ฅผ ๋ฐ›์€ ์œ ์ €๊ฐ€ ์ดˆ๋Œ€ ์ˆ˜๋ฝ
  2. ProjectService์—์„œ ํŒ€ ๋ฉค๋ฒ„๋ฅผ ์ƒˆ๋กœ ์ƒ์„ฑํ•˜์—ฌ ์ €์žฅ
  3. ์ดˆ๋Œ€๋ฅผ ์ˆ˜๋ฝํ–ˆ๋‹ค๋Š” ์ด๋ฒคํŠธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ด
  4. AlarmEventListener์—์„œ ์•Œ๋žŒ ์ƒ์„ฑํ•˜์—ฌ ์ €์žฅํ•˜๋ ค ํ–ˆ๋Š”๋ฐ, Exception ๋ฐœ์ƒ
  5. ๊ทธ๋Ÿผ ํŒ€ ๋ฉค๋ฒ„๋ฅผ ์ƒˆ๋กœ ์ƒ์„ฑํ•˜๋Š” ๊ณผ์ •๋„ ๊ฐ™์ด ๋กค๋ฐฑ๋จ

 

๊ฒฐ๊ตญ, ์ดˆ๋Œ€๋ฅผ ์ˆ˜๋ฝํ•œ ์‚ฌ์šฉ์ž ์ž…์žฅ์—์„œ๋Š” ์ˆ˜๋ฝํ–ˆ์Œ์—๋„ ์ˆ˜๋ฝ๋˜์ง€ ์•Š๋Š” ์ƒํ™ฉ์ด ๋ฐœ์ƒํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

 

ํ•ต์‹ฌ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์˜ ์•ˆ์ •์„ฑ์„ ๋ณด์žฅํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์ด๋ฅผ ํ•ด๊ฒฐํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์€ ๋ฐ”๋กœ `@EventListener` ๋Œ€์‹  `@TransactionalEventListener`๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค!


โœ…  @EventListener vs. @TransactionalEventListener

`@EventListener` : ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœํ–‰๋˜๋Š” ์‹œ์ ์— ๋ฐ”๋กœ EventListener์˜ ๋กœ์ง ์‹คํ–‰

 

`@TransactionalEventListener` : ํŠธ๋žœ์žญ์…˜์˜ ์–ด๋–ค ํƒ€์ด๋ฐ์— ์ด๋ฒคํŠธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ฌ์ง€ ์ •ํ•  ์ˆ˜ ์žˆ์Œ

  • AFTER_COMMIT (๊ธฐ๋ณธ๊ฐ’) - ํŠธ๋žœ์žญ์…˜์ด ์„ฑ๊ณต์ ์œผ๋กœ ๋งˆ๋ฌด๋ฆฌ(commit)๋์„ ๋•Œ ์ด๋ฒคํŠธ ์‹คํ–‰
  • AFTER_ROLLBACK – ํŠธ๋žœ์žญ์…˜์ด rollback ๋์„ ๋•Œ ์ด๋ฒคํŠธ ์‹คํ–‰
  • AFTER_COMPLETION – ํŠธ๋žœ์žญ์…˜์ด ๋งˆ๋ฌด๋ฆฌ ๋์„ ๋•Œ(commit or rollback) ์ด๋ฒคํŠธ ์‹คํ–‰
  • BEFORE_COMMIT - ํŠธ๋žœ์žญ์…˜์˜ ์ปค๋ฐ‹ ์ „์— ์ด๋ฒคํŠธ ์‹คํ–‰

์œ„์™€ ๊ฐ™์ด ์˜ต์…˜์„ ์„ค์ •ํ•˜์—ฌ ์–ด๋А ์‹œ์ ์— ์ด๋ฒคํŠธ๋ฅผ ์‹คํ–‰ํ• ์ง€ ๊ฒฐ์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

์ด์ œ `@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)`์œผ๋กœ ๋ณ€๊ฒฝํ•˜๊ณ 

๋‹ค์‹œ ์ดˆ๋Œ€ ์ˆ˜๋ฝ ์•Œ๋žŒ์ด ์ƒ์„ฑ๋˜๋Š” ๊ณผ์ •์—์„œ ๋งŒ์•ฝ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ–ˆ๋‹ค๊ณ  ํ•ฉ์‹œ๋‹ค. 

  1. ProjectService์—์„œ ํŒ€ ๋ฉค๋ฒ„๋ฅผ ์ƒˆ๋กœ ์ƒ์„ฑํ•˜์—ฌ ์ €์žฅ
  2. ์ดˆ๋Œ€๋ฅผ ์ˆ˜๋ฝํ–ˆ๋‹ค๋Š” ์ด๋ฒคํŠธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ด
  3. ํŠธ๋žœ์žญ์…˜ ์ปค๋ฐ‹
  4. AlarmEventListener์—์„œ ์•Œ๋žŒ ์ƒ์„ฑํ•˜์—ฌ ์ €์žฅํ•˜๋ ค ํ–ˆ๋Š”๋ฐ, Exception ๋ฐœ์ƒ
  5. ํŒ€ ๋ฉค๋ฒ„๋Š” ์ด๋ฏธ ์ปค๋ฐ‹๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ž˜ ์ €์žฅ๋จ

=> `@TransactionalEventListener`์„ ์‚ฌ์šฉํ•ด ํ•ต์‹ฌ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์˜ ์•ˆ์ •์„ฑ์„ ๋ณด์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 


โœ… ์ฝ”๋“œ ์ˆ˜์ • - @Async & @TransactionalEventListener ํ™œ์šฉ

๐Ÿ“ @Async ์‚ฌ์šฉ

Async Annotation

 

ํ•œ ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ, ๋‘ ๊ฐ€์ง€(๋‚ด๋ถ€ ์•Œ๋žŒ, ์ด๋ฉ”์ผ ์•Œ๋žŒ) ์ฒ˜๋ฆฌ๋ฅผ ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด

`@Async`๋ฅผ ๋ถ™์—ฌ ๋น„๋™๊ธฐ์ ์œผ๋กœ ์ฒ˜๋ฆฌ๋  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

"๋ฆฌ๋ทฐ ์š”์ฒญ ๋ณด๋‚ด๊ธฐ" ์ƒํ™ฉ์—์„œ๋Š” ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์—์„œ CUD ์ž‘์—…์„ ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ `@EventListener`๋ฅผ ๊ตณ์ด `@TransactionalEventListener`๋กœ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š์•„๋„ ๋ฉ๋‹ˆ๋‹ค.

 

๐Ÿ“ @Async & @TransactionalEventListener ์‚ฌ์šฉ

TransacionalEventListener annotation

 

๋ฐ˜๋ฉด์— "ํŒ€ ์ดˆ๋Œ€ ์ˆ˜๋ฝ" ์ƒํ™ฉ์—์„œ๋Š” `@TransactionalEventListener`๋กœ ๋ณ€๊ฒฝํ•ด์ค˜์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์—์„œ `TeamMember`๋ผ๋Š” ๊ฐ์ฒด๋ฅผ ์ƒˆ๋กœ ์ƒ์„ฑํ•ด ์ €์žฅํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

 


โœ…  @TransactionalEventListener๋งŒ ์‚ฌ์šฉํ•˜๋ฉด ์•ˆ ๋จ!

์ €๋ ‡๊ฒŒ ํ•ด์„œ ๋ชจ๋“  ์ž‘์—…์ด ๋๋‚œ ์ค„ ์•Œ์•˜์œผ๋‚˜..

๋˜ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.

 

๐Ÿ“๋ฌธ์ œ

ํŒ€ ๋ฉค๋ฒ„ ์ƒ์„ฑ ํ›„ ํŠธ๋žœ์žญ์…˜์—์„œ ์ด๋ฏธ Commit์ด ๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ํ•ด๋‹น ํŠธ๋žœ์žญ์…˜์—์„œ๋Š” ์กฐํšŒ๋ฐ–์— ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์—†๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ฆ‰, EventListener์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ insert, delete, update ํ•˜๋ฉด ๋ฐ˜์˜์ด ์•ˆ ๋ฉ๋‹ˆ๋‹ค.

 

๐Ÿ“ํ•ด๊ฒฐ

`@TrnasactionalEventListener`๊ณผ ํ•จ๊ป˜ `@Transactional(propagation=Propagation.REQUIRES_NEW)`๋ฅผ ๋ถ™์—ฌ์ค˜์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

`REQUIRES_NEW` ์ „ํŒŒ ์˜ต์…˜์„ ์„ค์ •ํ•˜๋ฉด, ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ ๋‚ด๋ถ€์˜ ์•Œ๋ฆผ ์ฒ˜๋ฆฌ ๋กœ์ง์ด ๋ณ„๋„์˜ ์ƒˆ๋กœ์šด ํŠธ๋žœ์žญ์…˜์—์„œ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.
์ฆ‰ ๋ฉ”์ธ ํŠธ๋žœ์žญ์…˜๊ณผ๋Š” ๋ถ„๋ฆฌ๋˜์–ด ๋™์ž‘ํ•˜๋ฏ€๋กœ ์•Œ๋ฆผ ์ƒ์„ฑ ๊ณผ์ •์—์„œ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•ด๋„ ๋ณธ๋ž˜ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์€ ๋กค๋ฐฑ๋˜์ง€ ์•Š๊ณ  ๊ทธ๋Œ€๋กœ ์ปค๋ฐ‹๋ฉ๋‹ˆ๋‹ค.

Requires new transaction

 


โœ…  AOP vs. ์Šคํ”„๋ง ์ด๋ฒคํŠธ

์Šคํ”„๋ง ์ด๋ฒคํŠธ๋ฅผ ๊ณต๋ถ€ํ•˜๋‹ค ๋ณด๋‹ˆ AOP๋ž‘ ๋ญ๊ฐ€ ๋‹ค๋ฅธ ๊ฑธ๊นŒ? ํ•˜๋Š” ์˜๋ฌธ์ด ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค.

 

AOP๋ฅผ ์จ์„œ "์•Œ๋žŒ ์ƒ์„ฑ"์ด๋ผ๋Š” ๊ณตํ†ต ๊ด€์‹ฌ์‚ฌ๋ฅผ ๋ถ„๋ฆฌํ•˜๋ฉด ๋˜์ง€ ์•Š๋‚˜?

 

 

๊ฒฐ๋ก ์ ์œผ๋กœ ๋‘˜์€ ๋ชฉ์ ์ด ์กฐ๊ธˆ ๋‹ฌ๋ž์Šต๋‹ˆ๋‹ค.

  • AOP: ๊ณตํ†ต๋œ ๋ถ€๊ฐ€์ ์ธ ๊ธฐ๋Šฅ์„ ํ•˜๋‚˜์˜ Aspect์œผ๋กœ ๋ถ„๋ฆฌ
  • ์Šคํ”„๋ง ์ด๋ฒคํŠธ: ๋‘ ๋„๋ฉ”์ธ ๊ฐ„์˜ ์˜์กด์„ฑ ๋ถ„๋ฆฌ

 

AOP์—์„œ ๋ถ„๋ฆฌํ•˜๊ณ ์ž ํ•˜๋Š” ๊ฒƒ์€ "๊ณตํ†ต"๋˜๋ฉด์„œ "๋ถ€๊ฐ€์ ์ธ ๊ธฐ๋Šฅ"์ž…๋‹ˆ๋‹ค.

์•Œ๋žŒ ์ƒ์„ฑ์€ ๋ฆฌ๋ทฐ ์š”์ฒญ/ ํ”„๋กœ์ ํŠธ ํŒ€์› ์ดˆ๋Œ€ / ์ดˆ๋Œ€ ์ˆ˜๋ฝ ์ƒํ™ฉ์—์„œ "๊ณตํ†ต"๋œ ๊ธฐ๋Šฅ์€ ๋งž์Šต๋‹ˆ๋‹ค.

 

ํ•˜์ง€๋งŒ, ๋ถ€๊ฐ€์ ์ธ ๊ธฐ๋Šฅ์ด๋ผ๊ณ ๋Š” ๋ณผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

๋ถ€๊ฐ€์ ์ธ ๊ธฐ๋Šฅ์ด๋ž€ ๋กœ๊ทธ, ์ˆ˜ํ–‰ ์‹œ๊ฐ„ ์ €์žฅ๊ณผ ๊ฐ™์ด ํ•ต์‹ฌ ๊ธฐ๋Šฅ์„ ๋ณด์กฐํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

์•Œ๋žŒ ์ƒ์„ฑ์€ Alarm ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•ด DB์— ์ €์žฅํ•˜๋Š” ํ•ต์‹ฌ ๋กœ์ง์ž…๋‹ˆ๋‹ค! Aspect๋กœ๋Š” ๋ถ€์ ์ ˆํ•ฉ๋‹ˆ๋‹ค.

 

๋”ฐ๋ผ์„œ, ๋‘ ๋„๋ฉ”์ธ ๊ฐ„์˜ ์˜์กด์„ฑ์ด ๊ณ ๋ฏผ๋๋˜ ์ œ ์ƒํ™ฉ์—์„œ๋Š” ์Šคํ”„๋ง ์ด๋ฒคํŠธ๋ฅผ ์ ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ ์ ˆํ•ฉ๋‹ˆ๋‹ค.

 

 

 

๋ฐ˜์‘ํ˜•

'๐ŸŽฏ Programming' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

[์Šคํ”„๋ง] JPA N+1 ๋ฌธ์ œ ํŠธ๋Ÿฌ๋ธ” ์ŠˆํŒ…  (2) 2025.03.27
[ISSUE] error: connect econnrefused  (1) 2025.02.17
[JAVA] ์ค‘๋ณต ์ œ๊ฑฐ ๋ฐฉ๋ฒ•(+์ •๋ ฌ)  (1) 2025.01.31
[Github Action] build ์˜ค๋ฅ˜ ์›์ธ ๋” ์ž์„ธํžˆ ๋ณด๋Š” ๋ฒ•  (0) 2024.10.08
'๐ŸŽฏ Programming' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€
  • [์Šคํ”„๋ง] JPA N+1 ๋ฌธ์ œ ํŠธ๋Ÿฌ๋ธ” ์ŠˆํŒ…
  • [ISSUE] error: connect econnrefused
  • [JAVA] ์ค‘๋ณต ์ œ๊ฑฐ ๋ฐฉ๋ฒ•(+์ •๋ ฌ)
  • [Github Action] build ์˜ค๋ฅ˜ ์›์ธ ๋” ์ž์„ธํžˆ ๋ณด๋Š” ๋ฒ•
dev-heyjin
dev-heyjin
  • dev-heyjin
    ๊ฐœ๋ฐœ ๊ธฐ๋ก
    dev-heyjin
  • ์ „์ฒด
    ์˜ค๋Š˜
    ์–ด์ œ
    • ๋ถ„๋ฅ˜ ์ „์ฒด๋ณด๊ธฐ (56)
      • ๐ŸŽฏ Programming (8)
      • ๐Ÿ’ช Algorithm (16)
      • โš™๏ธ CS (31)
        • ๋„คํŠธ์›Œํฌ (15)
        • ์šด์˜์ฒด์ œ (15)
        • ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค (0)
  • ๋ธ”๋กœ๊ทธ ๋ฉ”๋‰ด

    • ํ™ˆ
    • ํƒœ๊ทธ
    • ๋ฐฉ๋ช…๋ก
  • ๋งํฌ

  • ๊ณต์ง€์‚ฌํ•ญ

  • ์ธ๊ธฐ ๊ธ€

  • ํƒœ๊ทธ

    DB
    ํ•ดํ‚น
    RDS
    ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค
  • ์ตœ๊ทผ ๋Œ“๊ธ€

  • ์ตœ๊ทผ ๊ธ€

  • hELLOยท Designed By์ •์ƒ์šฐ.v4.10.3
dev-heyjin
[์Šคํ”„๋ง] ์Šคํ”„๋ง ์ด๋ฒคํŠธ๋Š” ์–ธ์ œ ์จ์•ผํ• ๊นŒ?
์ƒ๋‹จ์œผ๋กœ

ํ‹ฐ์Šคํ† ๋ฆฌํˆด๋ฐ”