๊ธฐ์กด ํ๋ก์ ํธ์์ Service ๊ฐ ์์กด์ฑ์ด ์๊ธฐ๋ ๋ถ๋ถ์ด ๊ณ ๋ฏผ์ด์๊ณ ,
์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ์คํ๋ง ์ด๋ฒคํธ๋ฅผ ์ ์ฉํด ๋ดค์ต๋๋ค.
โ ํ๋ก์ ํธ ์ํฉ
"๋ด๋ถ ์๋ฆผ ๊ธฐ๋ฅ"์ด ์๋น์ค์ ํ์ํ์ต๋๋ค.
์ฆ, ์ ์ ๊ฐ ์๋น์ค์ ์ ์ํ์ ๋ ์๋ฆผ์ด ์์ฌ ์๊ณ ์ด๋ฅผ ํ์ธํ ์ ์๋ ํ๋ฉด์ด ํ์ํ์ต๋๋ค.
์ฌ์ฉ์์๊ฒ ์๋ฆผ์ด ๋์ฐฉํ๋ ์ํฉ์ ๋ค์ 3๊ฐ์ง ๊ฒฝ์ฐ์์ต๋๋ค.
- ๋ฆฌ๋ทฐ ์์ฒญ
- ํ๋ก์ ํธ ํ์ ์ด๋
- ํ์ ์ด๋ ์๋ฝ
๐ Alarm ํ ์ด๋ธ
ํด๋น ๊ธฐ๋ฅ์ ํ์ํ ์๋ ํ ์ด๋ธ์ ๋ค์๊ณผ ๊ฐ์ด ์ค๊ณํ์ต๋๋ค.
์ฃผ์ ํ๋๋ก๋
- `receiver_id`: ์๋์ ๋ฐ๋ ์ฌ๋ ID
- `sender_id`: ์๋์ ๋ณด๋ธ ์ฌ๋ ID
- `targetId`: ์๋ฆผ์ด ๋ฐ์ํ 3๊ฐ์ง ์ํฉ ๊ฐ๊ฐ์์ ์ฐ๊ด๋ ์ํฐํฐ์ ID
- `message`: ์๋ ๋ฉํธ
- `alarm_type`: ์๋์ด ๋ฐ์ํ ์ํฉ(๋ฆฌ๋ทฐ ์์ฒญ, ํ์ ์ด๋, ์ด๋ ์๋ฝ)
์ด๋ฅผ ์ํฐํฐ๋ก ๊ตฌํํ๋ฉด ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
๐ ๋ฆฌ๋ทฐ ์์ฒญ ์๋ฆผ ์์ฑ ๋ก์ง
์๋ฆผ์ด ์์ฑ๋๋ 3๊ฐ์ง ์ํฉ ์ค, ์ ๊ฐ ๋ด๋นํ "๋ฆฌ๋ทฐ ์์ฒญ" ์๋ฆผ ์์ฑ ๋ก์ง์ ๋ํด ์ค๋ช ๋๋ฆฌ๊ฒ ์ต๋๋ค.
ํ ์ ์ ๊ฐ ๋ค๋ฅธ ์ ์ ์๊ฒ ๋ฆฌ๋ทฐ๋ฅผ ์์ฒญํ๋ฉด, 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์์ ์กฐํํด ์ค๋ ๊ฒ๋ ๋ ๋ค๋ฅธ ์์กด์ฑ ๋ฌธ์ ์ ๋๋ค.
โ ๋ฌธ์ ์
์ ์ํฉ์ ๋์ํํ๋ฉด ์๋์ ๊ฐ์ต๋๋ค.
์ด์ฒ๋ผ Service๊ฐ ๋ค๋ฅธ Service์ ์์กดํ๋ฉด ์ด๋ค ๋ฌธ์ ์ ์ด ์์๊น์?
- ๋๋ฉ์ธ ๊ฐ์ ๊ฐํ ๊ฒฐํฉ๋
- ๋จ์ผ ์ฑ ์ ์์น(SRP) ์๋ฐฐ
- ์ข์ง ์์ ํ์ฅ์ฑ
๐ ๋๋ฉ์ธ ๊ฐ์ ๊ฐํ ๊ฒฐํฉ๋
ํ์ฌ 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` ๋ฉ์๋ ๋ก์ง ์คํ
โ ์คํ๋ง ์ด๋ฒคํธ ์ ์ฉ ํ ๋ฌธ์ ํด๊ฒฐ
์คํ๋ง ์ด๋ฒคํธ๋ฅผ ์ ์ฉํ ํ์ ๋ชจ์ต์ ๋์ํํ๋ฉด ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
์คํ๋ง ์ด๋ฒคํธ๋ฅผ ์ ์ฉํ๋ฉด ๊ณผ์ฐ ์์ ์ธ๊ธํ๋ 3๊ฐ์ง ๋ฌธ์ ๊ฐ ํด๊ฒฐ๋ ๊น์?
ํ๋์ฉ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
๐ ํด๊ฒฐ: ๋๋ฉ์ธ ๊ฐ์ ๊ฐํ ๊ฒฐํฉ๋
์ค๊ฐ์ `EventListener`๊ฐ ์๊ธฐ๋ฉด์ ReviewService์ ProjectService๋ AlarmService์ ์์กดํ์ง ์์๋ ๋ฉ๋๋ค.
์ฆ, Alarm ์์ฑ ๋ก์ง์ด ๋ณ๊ฒฝ๋๋๋ผ๋ ReviewService์ ProjectService์ ์ํฅ์ด ๊ฐ์ง ์๋ ๊ฑฐ์ฃ .
๐ ํด๊ฒฐ: ๋จ์ผ ์ฑ ์ ์์น(SRP) ์๋ฐฐ
๊ธฐ์กด์๋ "์๋์ ์์ฑํด๋ผ!"๋ผ๊ณ ํ๊ณ ์๊ธฐ ๋๋ฌธ์ ReviewService์ ProjectService์ ์๋ ์์ฑ์ ์ฑ ์์ด ์๋ค๊ณ ํ์ต๋๋ค.
ํ์ง๋ง, ์ด๋ฒคํธ ๊ธฐ๋ฐ์ผ๋ก ์์ ํ๋ฉด "๋ฆฌ๋ทฐ ์์ฒญ/ํ์ ์ด๋/ ์ด๋ ์๋ฝ ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ๋ค!"๋ผ๊ณ ๋จ์ํ ์ด๋ฒคํธ๋ฅผ ๋ฐ์์ํค๊ธฐ๋ง ํ๋ฉด ๋ฉ๋๋ค.
์๋ ์์ฑ์ ๋ํ ์ฑ ์์ ๋ ์ด์ ์ง์ง ์์ต๋๋ค.
๐ ํด๊ฒฐ: ์ข์ง ์์ ํ์ฅ์ฑ
์์ ๋งํ๋ฏ์ด ์ด๋ฉ์ผ ์๋ฆผ๊ณผ ๋ฌธ์ ์๋ฆผ์ด ์ถ๊ฐ๋๋ค๋ฉด ์ด๋ป๊ฒ ๋ ๊น์?
๋จ์ํ `EventListener` ๋ก์ง๋ง ์ถ๊ฐํ๋ฉด ๋ฉ๋๋ค!
ReviewService์ ProjectService์ ๋ก์ง์ ์ ํ ์์ ํ์ง ์์๋ ๋ฉ๋๋ค.
์ฌ์ ํ ์ด๋ฒคํธ๋ฅผ ๋ฐ์์ํค๊ธฐ๋ง ํ๋ฉด ๋์ฃ .
โ ์ฝ๋ ์์ - @EventListener ํ์ฉ
์ด์ ์คํ๋ง ์ด๋ฒคํธ๋ฅผ ์ ์ฉํ๊ธฐ ์ํด ๊ธฐ์กด ์ฝ๋๋ฅผ ์์ ํด ๋ณด๊ฒ ์ต๋๋ค.
๐ Event ํด๋์ค ์์ฑ
์๋์ด ํ์ํ ์ธ ๊ฐ์ง ์ํฉ(๋ฆฌ๋ทฐ ์์ฒญ, ํ์ ์ด๋, ์ด๋ ์๋ฝ)์ ๋ํด ์ด๋ฒคํธ ํด๋์ค๋ฅผ ๋ง๋ค์ด์ค๋๋ค.
๐ ReviewService์ EventPublisher ์ฃผ์
ApplicationEventPublisher๋ฅผ ํตํด ReviewService์์ ์ด๋ฒคํธ๋ฅผ ๋ฐํํฉ๋๋ค.
๐ EventListener ํด๋์ค ์์ฑ
๋ง์ง๋ง์ผ๋ก ์ด๋ฒคํธ๋ฅผ ์ฒ๋ฆฌํด ์ฃผ๋ EventListener ํด๋์ค๋ฅผ ์์ฑํฉ๋๋ค.
`@EventListener` ์ด๋ ธํ ์ด์ ์ ๋ฉ์๋์ ๋ฌ์์, ๊ฐ ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ์ ๋ ์ด๋ค ๋ก์ง์ ์คํํ ์ง ์ ์ํด ์ค๋๋ค.
โ @EventListener ๋ฌธ์
์์ ์ฝ๋์์ `@EventListener`๋ผ๋ ์ด๋ ธํ ์ด์ ์ ์ฌ์ฉํ์ต๋๋ค.
ํ์ง๋ง, ์ด ์ด๋ ธํ ์ด์ ์๋ ๋ช ๊ฐ์ง ๋ฌธ์ ๊ฐ ์์ต๋๋ค.
๐ ๊ธฐ๋ณธ์ ์ผ๋ก ๋๊ธฐ๋ก ๋์
๋จ์ํ `@EventListener` ์ด๋ ธํ ์ด์ ๋ง ๋ฌ์์ฃผ๋ฉด ์ด ๋ฉ์๋๋ ๋๊ธฐ๋ก ๋์ํฉ๋๋ค.
ํ์ง๋ง ๋๊ธฐ ๋ฐฉ์์์๋ ๋ค์๊ณผ ๊ฐ์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค.
- ์๋น์ค ๋ด๋ถ ์๋ฆผ + ์ด๋ฉ์ผ ์๋ฆผ ๋ณด๋ธ๋ค๊ณ ๊ฐ์
- ๋๊ธฐ๋ก ๋์ํ๋ฉด ์๋น์ค ๋ด๋ถ ์๋ฆผ ์์ฑ ํ, ์ด๋ฉ์ผ ์๋ฆผ ๋ณด๋
- ์ด๋ฉ์ผ ์๋ฆผ์ด ์ค๋ ๊ฑธ๋ฆฌ๋ฉด ์ฌ์ฉ์๋ ์ด ์๊ฐ์ ๋ชจ๋ ๊ธฐ๋ค๋ ค์ผ ํจ
์ด๋ฐ ๋ฌธ์ ๋ฅผ ๋ฐฉ์งํ๊ธฐ ์ํด, ํด๋น ๋ฆฌ์ค๋ ๋ฉ์๋์ `@Async` ์ด๋
ธํ
์ด์
์ ํจ๊ป ์ฌ์ฉํ์ฌ
๋น๋๊ธฐ๋ก ์ฒ๋ฆฌ๋๋๋ก ๋ช
์ํด ์ฃผ๋ ๊ฒ์ด ์ข์ต๋๋ค.
๐Event๋ฅผ ๋ฐํ์ํจ ๋ก์ง๋ ๊ฐ์ด ๋กค๋ฐฑ
์ด๋ ์๋ฝ ์๋์ด ์์ฑ๋๋ ๊ณผ์ ์์ ๋ง์ฝ ์์ธ๊ฐ ๋ฐ์ํ๋ค๊ณ ํฉ์๋ค.
- ํ๋ก์ ํธ ๋ฉค๋ฒ ์ด๋๋ฅผ ๋ฐ์ ์ ์ ๊ฐ ์ด๋ ์๋ฝ
- ProjectService์์ ํ ๋ฉค๋ฒ๋ฅผ ์๋ก ์์ฑํ์ฌ ์ ์ฅ
- ์ด๋๋ฅผ ์๋ฝํ๋ค๋ ์ด๋ฒคํธ๋ฅผ ๋ฐ์์ํด
- AlarmEventListener์์ ์๋ ์์ฑํ์ฌ ์ ์ฅํ๋ ค ํ๋๋ฐ, Exception ๋ฐ์
- ๊ทธ๋ผ ํ ๋ฉค๋ฒ๋ฅผ ์๋ก ์์ฑํ๋ ๊ณผ์ ๋ ๊ฐ์ด ๋กค๋ฐฑ๋จ
๊ฒฐ๊ตญ, ์ด๋๋ฅผ ์๋ฝํ ์ฌ์ฉ์ ์ ์ฅ์์๋ ์๋ฝํ์์๋ ์๋ฝ๋์ง ์๋ ์ํฉ์ด ๋ฐ์ํ๋ ๊ฒ์ ๋๋ค.
ํต์ฌ ๋น์ฆ๋์ค ๋ก์ง์ ์์ ์ฑ์ ๋ณด์ฅํ๊ธฐ ์ํด์๋ ์ด๋ฅผ ํด๊ฒฐํฉ๋๋ค.
๊ทธ๋ฆฌ๊ณ ํด๊ฒฐ ๋ฐฉ๋ฒ์ ๋ฐ๋ก `@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)`์ผ๋ก ๋ณ๊ฒฝํ๊ณ
๋ค์ ์ด๋ ์๋ฝ ์๋์ด ์์ฑ๋๋ ๊ณผ์ ์์ ๋ง์ฝ ์์ธ๊ฐ ๋ฐ์ํ๋ค๊ณ ํฉ์๋ค.
- ProjectService์์ ํ ๋ฉค๋ฒ๋ฅผ ์๋ก ์์ฑํ์ฌ ์ ์ฅ
- ์ด๋๋ฅผ ์๋ฝํ๋ค๋ ์ด๋ฒคํธ๋ฅผ ๋ฐ์์ํด
- ํธ๋์ญ์ ์ปค๋ฐ
- AlarmEventListener์์ ์๋ ์์ฑํ์ฌ ์ ์ฅํ๋ ค ํ๋๋ฐ, Exception ๋ฐ์
- ํ ๋ฉค๋ฒ๋ ์ด๋ฏธ ์ปค๋ฐ๋์๊ธฐ ๋๋ฌธ์ ์ ์ ์ฅ๋จ
=> `@TransactionalEventListener`์ ์ฌ์ฉํด ํต์ฌ ๋น์ฆ๋์ค ๋ก์ง์ ์์ ์ฑ์ ๋ณด์ฅํ ์ ์์ต๋๋ค.
โ ์ฝ๋ ์์ - @Async & @TransactionalEventListener ํ์ฉ
๐ @Async ์ฌ์ฉ
ํ ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ์ ๋, ๋ ๊ฐ์ง(๋ด๋ถ ์๋, ์ด๋ฉ์ผ ์๋) ์ฒ๋ฆฌ๋ฅผ ํ๊ณ ์ถ๋ค๋ฉด
`@Async`๋ฅผ ๋ถ์ฌ ๋น๋๊ธฐ์ ์ผ๋ก ์ฒ๋ฆฌ๋ ์ ์๋๋ก ํด์ผ ํฉ๋๋ค.
"๋ฆฌ๋ทฐ ์์ฒญ ๋ณด๋ด๊ธฐ" ์ํฉ์์๋ ๋น์ฆ๋์ค ๋ก์ง์์ CUD ์์ ์ ํ์ง ์์ต๋๋ค.
๋ฐ๋ผ์ `@EventListener`๋ฅผ ๊ตณ์ด `@TransactionalEventListener`๋ก ๋ณ๊ฒฝํ์ง ์์๋ ๋ฉ๋๋ค.
๐ @Async & @TransactionalEventListener ์ฌ์ฉ
๋ฐ๋ฉด์ "ํ ์ด๋ ์๋ฝ" ์ํฉ์์๋ `@TransactionalEventListener`๋ก ๋ณ๊ฒฝํด์ค์ผ ํฉ๋๋ค.
๋น์ฆ๋์ค ๋ก์ง์์ `TeamMember`๋ผ๋ ๊ฐ์ฒด๋ฅผ ์๋ก ์์ฑํด ์ ์ฅํ๊ธฐ ๋๋ฌธ์ ๋๋ค.
โ @TransactionalEventListener๋ง ์ฌ์ฉํ๋ฉด ์ ๋จ!
์ ๋ ๊ฒ ํด์ ๋ชจ๋ ์์ ์ด ๋๋ ์ค ์์์ผ๋..
๋ ๋ฌธ์ ๊ฐ ๋ฐ์ํ์ต๋๋ค.
๐๋ฌธ์
ํ ๋ฉค๋ฒ ์์ฑ ํ ํธ๋์ญ์ ์์ ์ด๋ฏธ Commit์ด ๋์๊ธฐ ๋๋ฌธ์ ํด๋น ํธ๋์ญ์ ์์๋ ์กฐํ๋ฐ์ ์ํํ ์ ์๋ค๋ ๊ฒ์ ๋๋ค.
์ฆ, EventListener์์ ๋ฐ์ดํฐ๋ฅผ insert, delete, update ํ๋ฉด ๋ฐ์์ด ์ ๋ฉ๋๋ค.
๐ํด๊ฒฐ
`@TrnasactionalEventListener`๊ณผ ํจ๊ป `@Transactional(propagation=Propagation.REQUIRES_NEW)`๋ฅผ ๋ถ์ฌ์ค์ผ ํฉ๋๋ค.
`REQUIRES_NEW` ์ ํ ์ต์
์ ์ค์ ํ๋ฉด, ์ด๋ฒคํธ ๋ฆฌ์ค๋ ๋ด๋ถ์ ์๋ฆผ ์ฒ๋ฆฌ ๋ก์ง์ด ๋ณ๋์ ์๋ก์ด ํธ๋์ญ์
์์ ์คํ๋ฉ๋๋ค.
์ฆ ๋ฉ์ธ ํธ๋์ญ์
๊ณผ๋ ๋ถ๋ฆฌ๋์ด ๋์ํ๋ฏ๋ก ์๋ฆผ ์์ฑ ๊ณผ์ ์์ ์์ธ๊ฐ ๋ฐ์ํด๋ ๋ณธ๋ ๋น์ฆ๋์ค ๋ก์ง์ ๋กค๋ฐฑ๋์ง ์๊ณ ๊ทธ๋๋ก ์ปค๋ฐ๋ฉ๋๋ค.
โ AOP vs. ์คํ๋ง ์ด๋ฒคํธ
์คํ๋ง ์ด๋ฒคํธ๋ฅผ ๊ณต๋ถํ๋ค ๋ณด๋ AOP๋ ๋ญ๊ฐ ๋ค๋ฅธ ๊ฑธ๊น? ํ๋ ์๋ฌธ์ด ๋ค์์ต๋๋ค.
AOP๋ฅผ ์จ์ "์๋ ์์ฑ"์ด๋ผ๋ ๊ณตํต ๊ด์ฌ์ฌ๋ฅผ ๋ถ๋ฆฌํ๋ฉด ๋์ง ์๋?
๊ฒฐ๋ก ์ ์ผ๋ก ๋์ ๋ชฉ์ ์ด ์กฐ๊ธ ๋ฌ๋์ต๋๋ค.
- AOP: ๊ณตํต๋ ๋ถ๊ฐ์ ์ธ ๊ธฐ๋ฅ์ ํ๋์ Aspect์ผ๋ก ๋ถ๋ฆฌ
- ์คํ๋ง ์ด๋ฒคํธ: ๋ ๋๋ฉ์ธ ๊ฐ์ ์์กด์ฑ ๋ถ๋ฆฌ
AOP์์ ๋ถ๋ฆฌํ๊ณ ์ ํ๋ ๊ฒ์ "๊ณตํต"๋๋ฉด์ "๋ถ๊ฐ์ ์ธ ๊ธฐ๋ฅ"์ ๋๋ค.
์๋ ์์ฑ์ ๋ฆฌ๋ทฐ ์์ฒญ/ ํ๋ก์ ํธ ํ์ ์ด๋ / ์ด๋ ์๋ฝ ์ํฉ์์ "๊ณตํต"๋ ๊ธฐ๋ฅ์ ๋ง์ต๋๋ค.
ํ์ง๋ง, ๋ถ๊ฐ์ ์ธ ๊ธฐ๋ฅ์ด๋ผ๊ณ ๋ ๋ณผ ์ ์์ต๋๋ค.
๋ถ๊ฐ์ ์ธ ๊ธฐ๋ฅ์ด๋ ๋ก๊ทธ, ์ํ ์๊ฐ ์ ์ฅ๊ณผ ๊ฐ์ด ํต์ฌ ๊ธฐ๋ฅ์ ๋ณด์กฐํ๋ ๊ธฐ๋ฅ์ ์๋ฏธํฉ๋๋ค.
์๋ ์์ฑ์ Alarm ๊ฐ์ฒด๋ฅผ ์์ฑํด DB์ ์ ์ฅํ๋ ํต์ฌ ๋ก์ง์ ๋๋ค! Aspect๋ก๋ ๋ถ์ ์ ํฉ๋๋ค.
๋ฐ๋ผ์, ๋ ๋๋ฉ์ธ ๊ฐ์ ์์กด์ฑ์ด ๊ณ ๋ฏผ๋๋ ์ ์ํฉ์์๋ ์คํ๋ง ์ด๋ฒคํธ๋ฅผ ์ ์ฉํ๋ ๊ฒ์ด ์ ์ ํฉ๋๋ค.
'๐ฏ Programming' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[์คํ๋ง] JPA N+1 ๋ฌธ์ ํธ๋ฌ๋ธ ์ํ (1) | 2025.03.27 |
---|---|
[ISSUE] error: connect econnrefused (1) | 2025.02.17 |
[JAVA] ์ค๋ณต ์ ๊ฑฐ ๋ฐฉ๋ฒ(+์ ๋ ฌ) (1) | 2025.01.31 |
[Github Action] build ์ค๋ฅ ์์ธ ๋ ์์ธํ ๋ณด๋ ๋ฒ (0) | 2024.10.08 |