[Project] email ์ „์†ก EventPublisher ํ™œ์šฉ

Updated:

Categories:

Tags: ,

๐Ÿ“Œ ๊ฐœ์ธ์ ์ธ ๊ณต๊ฐ„์œผ๋กœ ๊ณต๋ถ€๋ฅผ ๊ธฐ๋กํ•˜๊ณ  ๋ณต์Šตํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•˜๋Š” ๋ธ”๋กœ๊ทธ์ž…๋‹ˆ๋‹ค.
์ •ํ™•ํ•˜์ง€ ์•Š์€ ์ •๋ณด๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ์œผ๋‹ˆ ์ฐธ๊ณ ๋ฐ”๋ž๋‹ˆ๋‹ค :๐Ÿ˜ธ
[ํ‹€๋ฆฐ ๋‚ด์šฉ์€ ๋Œ“๊ธ€๋กœ ๋‚จ๊ฒจ์ฃผ์‹œ๋ฉด ๋ณต๋ฐ›์œผ์‹ค๊ฑฐ์—์š”]


EmailController์˜ ์—ญํ• ์„ Event๋กœ ์˜ฎ๊ธด ์ด์œ ์™€ ๊ตฌํ˜„ ๊ณผ์ •

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

๊ธฐ์กด ๋กœ์ง์˜ ๋ฌธ์ œ์ 

๋จผ์ €, ๊ธฐ์กด ๋กœ์ง์„ ๊ฐ„๋‹จํžˆ ์„ค๋ช…ํ•˜์ž๋ฉด ์ด๋ ‡๋‹ค:

  1. ์‚ฌ์šฉ์ž๊ฐ€ ํšŒ์› ๊ฐ€์ž…์„ ํ•˜๋ฉด, ์ž„์‹œ๋กœ ๋ ˆ๋””์Šค(Redis)์— ์ •๋ณด๋ฅผ ์ €์žฅํ•˜๊ณ ,
  2. ๊ทธ ํ›„ EmailController๋ฅผ ํ†ตํ•ด ์ธ์ฆ ๋ฉ”์ผ์„ ๋ฐœ์†กํ•˜๊ณ ,
  3. ์‚ฌ์šฉ์ž๊ฐ€ ์ธ์ฆ ์ฝ”๋“œ๋ฅผ ์ž…๋ ฅํ•˜๋ฉด ๊ทธ์ œ์•ผ ํšŒ์› ์ •๋ณด๋ฅผ DB์— ์ €์žฅํ•˜๋Š” ๊ตฌ์กฐ๋‹ค.

์ด ๊ณผ์ •์—์„œ Post ์š”์ฒญ์„ ์„ธ ๋ฒˆ์ด๋‚˜ ๋ณด๋‚ด์•ผ ํ–ˆ๋‹ค:

  • ํšŒ์› ๋“ฑ๋ก ์‹œ /members๋กœ ์š”์ฒญ
  • ์ด๋ฉ”์ผ ์ „์†ก ์‹œ /send-mail๋กœ ์š”์ฒญ
  • ์ธ์ฆ ์ฝ”๋“œ ์ž…๋ ฅ ์‹œ /verify๋กœ ์š”์ฒญ

๋ฌผ๋ก  ์ด ๊ตฌ์กฐ๋„ ์ž˜ ์ž‘๋™ํ•˜๊ธด ํ•˜์ง€๋งŒ, ๋งค๋ฒˆ ์š”์ฒญ์„ ๋ณด๋‚ด์•ผ ํ•˜๋‹ค ๋ณด๋‹ˆ ๋ฒˆ๊ฑฐ๋กญ๊ณ , ์ฝ”๋“œ๋„ ๋ณต์žกํ•ด์กŒ๋‹ค. ๊ทธ๋ž˜์„œ ์ด ๊ณผ์ •์„ Event๋กœ ์ฒ˜๋ฆฌํ•˜๋ฉด ๋” ํšจ์œจ์ ์ด์ง€ ์•Š์„๊นŒ ์ƒ๊ฐํ•˜๊ฒŒ ๋๋‹ค.

Event๋กœ ๋กœ์ง์„ ์˜ฎ๊ธด ์ด์œ 

Event๋กœ ๋กœ์ง์„ ์˜ฎ๊ธฐ๋ฉด, ํšŒ์› ๋“ฑ๋ก ์‹œ ํ•œ ๋ฒˆ์˜ ์š”์ฒญ์œผ๋กœ ์ธ์ฆ ๋ฉ”์ผ ๋ฐœ์†ก๊นŒ์ง€ ์ฒ˜๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅํ•ด์ง„๋‹ค. ์ด๋กœ์จ ์š”์ฒญ ํšŸ์ˆ˜๋„ ์ค„๊ณ , ์ฝ”๋“œ๋„ ๊น”๋”ํ•ด์ง„๋‹ค.

๊ธฐ์กด์— EmailController์—์„œ ์ฒ˜๋ฆฌํ•˜๋˜ ๋ฉ”์ผ ๋ฐœ์†ก ๋กœ์ง์„ Event๋กœ ์˜ฎ๊ธฐ๋ฉด, ํšŒ์›(member)์„ ๋“ฑ๋กํ•  ๋•Œ ์ž๋™์œผ๋กœ ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜๊ณ , ๊ทธ ์ด๋ฒคํŠธ๋ฅผ ํ†ตํ•ด ๋ฉ”์ผ์ด ์ „์†ก๋˜๋Š” ๊ตฌ์กฐ๋กœ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ํšŒ์› ๋“ฑ๋ก๊ณผ ๋™์‹œ์— ์ด๋ฉ”์ผ์ด ๋ฐœ์†ก๋˜๋ฏ€๋กœ ๋ณ„๋„์˜ ๋ฉ”์ผ ๋ฐœ์†ก ์š”์ฒญ์„ ํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค.

Event ๊ตฌํ˜„: ๊ฐ„๋‹จํ•˜๊ณ  ํšจ๊ณผ์ ์ธ ๋ฐฉ๋ฒ•

๋ณดํ†ต Spring์—์„œ ์ด๋ฒคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•  ๋•Œ ApplicationEvent๋ฅผ ์ƒ์†๋ฐ›์•„ ์‚ฌ์šฉํ•˜๊ณค ํ•œ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ์ตœ๊ทผ ์Šคํ”„๋ง ๋ฒ„์ „์—์„œ๋Š” ๊ตณ์ด ApplicationEvent๋ฅผ ์ƒ์†๋ฐ›์ง€ ์•Š์•„๋„ ๋œ๋‹ค๊ณ  ํ•ด์„œ, ์ด๋ฒˆ์—๋Š” ์ƒ์†๋ฐ›์ง€ ์•Š๊ณ  ๊ฐ„๋‹จํ•˜๊ฒŒ ๊ตฌํ˜„ํ•ด๋ดค๋‹ค.

๋‚ด๊ฐ€ ์„ ํƒํ•œ ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค:

  1. ํšŒ์› ๋“ฑ๋ก ์‹œ ์ด๋ฒคํŠธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ค๊ณ ,
  2. ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ์ด ์ด๋ฒคํŠธ๋ฅผ ๋ฐ›์•„์„œ ์ด๋ฉ”์ผ์„ ๋ฐœ์†กํ•˜๋Š” ๋กœ์ง์„ ์‹คํ–‰ํ•œ๋‹ค.

์ด ๊ณผ์ •์—์„œ member ๊ฐ์ฒด์—์„œ ํ•„์š”ํ•œ email ์ •๋ณด๋งŒ ๊ฐ€์ ธ์™€์„œ ๋ฉ”์ผ์„ ๋ณด๋‚ด๋Š” ๋ฐฉ์‹์œผ๋กœ ๊ตฌํ˜„ํ–ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ๊ตฌํ˜„ํ•˜๋ฉด ๊ธฐ์กด์˜ ๋กœ์ง๊ณผ ํฌ๊ฒŒ ๋‹ฌ๋ผ์ง€์ง€ ์•Š์œผ๋ฉด์„œ๋„, ์ด๋ฉ”์ผ ๋ฐœ์†ก ๊ณผ์ •์„ ๋” ํšจ์œจ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.

๊ตฌํ˜„ ๊ณผ์ •

  1. ์ด๋ฒคํŠธ ํด๋ž˜์Šค ์ƒ์„ฑ
    • ์ด๋ฉ”์ผ ๋ฐœ์†ก์„ ์œ„ํ•œ ์ด๋ฒคํŠธ ํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑํ–ˆ๋‹ค. ์ด ํด๋ž˜์Šค๋Š” ํšŒ์› ๋“ฑ๋ก ์‹œ ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ด๊ณ  ์žˆ๋‹ค.

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      
        package com.springboot.helper.event;
              
        import com.springboot.member.entity.Member;
        import lombok.Getter;
        import org.springframework.context.ApplicationEvent;
              
        @Getter
        public class RegistrationEvent {
            private final Member member;
              
            public RegistrationEvent(Member member) {
                this.member = member;
            }
        }
              
      
  2. ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ
    • 1 ์—์„œ ๋งŒ๋“  ์ด๋ฒคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฆฌ์Šค๋„ˆ(listener)๋ฅผ ๋งŒ๋“ค์–ด, ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•  ๋•Œ๋งˆ๋‹ค ์ด๋ฉ”์ผ์„ ๋ฐœ์†กํ•˜๋„๋ก ์„ค์ •ํ–ˆ๋‹ค.

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      
        package com.springboot.helper.event;
              
        import com.springboot.helper.email.EmailMessage;
        import com.springboot.helper.email.EmailService;
        import com.springboot.member.service.MemberService;
        import lombok.extern.slf4j.Slf4j;
        import org.springframework.context.event.EventListener;
        import org.springframework.mail.MailSendException;
        import org.springframework.scheduling.annotation.EnableAsync;
        import org.springframework.stereotype.Component;
              
        @Component
        @EnableAsync
        @Slf4j
        public class MemberRegisterEventHandler {
            private final EmailService emailService;
            private final MemberService memberService;
              
            public MemberRegisterEventHandler(EmailService emailService, MemberService memberService) {
                this.emailService = emailService;
                this.memberService = memberService;
            }
            @EventListener
            public void listen(RegistrationEvent event) {
                try{
                    EmailMessage emailMessage = EmailMessage.builder()
                            .to(event.getMember().getEmail())
                            .subject("[MeetBTI] ํšŒ์›๊ฐ€์ž…์„ ์œ„ํ•œ ์ธ์ฆ์ฝ”๋“œ ๋ฐœ์†ก")
                            .build();
                    emailService.sendMail(emailMessage,"email");
              
                } catch (MailSendException e) {
                     log.error("MailSendException");
                } catch (RuntimeException e) {
                    log.error("RuntimeException : while sending");
                }
            }
        }
              
      
    • ์ด๋ฉ”์ผ ์ปจํŠธ๋กค๋Ÿฌ์—์„œ ์‚ฌ์šฉ๋˜๋Š” ๊ฒƒ๋“ค์„ listen ๋ฉ”์„œ๋“œ์— ์ ์šฉํ–ˆ๋‹ค.

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      
        package com.springboot.helper.email;
              
        import org.springframework.http.HttpStatus;
        import org.springframework.http.ResponseEntity;
        import org.springframework.web.bind.annotation.PostMapping;
        import org.springframework.web.bind.annotation.RequestBody;
        import org.springframework.web.bind.annotation.RequestMapping;
        import org.springframework.web.bind.annotation.RestController;
              
        @RequestMapping("/send-mail")
        @RestController
        public class EmailController {
            private final EmailService emailService;
              
            public EmailController(EmailService emailService) {
                this.emailService = emailService;
            }
              
            //ํšŒ์›๊ฐ€์ž… ์ด๋ฉ”์ผ ์ธ์ฆ์ฝ”๋“œ ๋ฐœ์†ก
            @PostMapping("/email")
            public ResponseEntity sendJoinMail(@RequestBody EmailPostDto emailPostDto) {
                EmailMessage emailMessage = EmailMessage.builder()
                        .to(emailPostDto.getEmail())
                        .subject("[MeetBTI] ํšŒ์›๊ฐ€์ž…์„ ์œ„ํ•œ ์ธ์ฆ์ฝ”๋“œ ๋ฐœ์†ก")
                        .build();
              
                emailService.sendMail(emailMessage,"email");
                String message = "์ธ์ฆ์ฝ”๋“œ๊ฐ€ ์ด๋ฉ”์ผ๋กœ ๋ฐœ์†ก๋˜์—ˆ์Šต๋‹ˆ๋‹ค.";
                return new ResponseEntity<>(message, HttpStatus.OK);
            }
        }
              
      
  3. ์ด๋ฒคํŠธ ๋ฐœํ–‰
    • ํšŒ์› ๋“ฑ๋ก์ด ์™„๋ฃŒ๋˜๋ฉด ์ด ์ด๋ฒคํŠธ๋ฅผ ๋ฐœํ–‰(publish)ํ•˜๋„๋ก ํ–ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์ด๋ฉ”์ผ ๋ฐœ์†ก ์š”์ฒญ์ด ์ž๋™์œผ๋กœ ์ด๋ฃจ์–ด์ง„๋‹ค.

      1
      2
      3
      4
      5
      6
      7
      8
      
         public void createMember(Member member) {
                verifiedExistNickname(member.getNickname());
                verifiedExistEmail(member.getEmail());
              
                String key = member.getEmail() + ":email";
                redisUtil.setHashValueWithExpire(key, "memberInfo", member, 600);
                publisher.publishEvent(new RegistrationEvent(member));
            }
      

์ด๋ ‡๊ฒŒ ๋กœ์ง์„ Event๋กœ ์˜ฎ๊ธฐ๊ณ  ๋‚˜๋‹ˆ, ์ „์ฒด์ ์ธ ์ฝ”๋“œ๊ฐ€ ํ›จ์”ฌ ๊น”๋”ํ•ด์กŒ๋‹ค. ์ด์ œ ํ•œ ๋ฒˆ์˜ ํšŒ์› ๊ฐ€์ž… ์š”์ฒญ์œผ๋กœ ์ด๋ฉ”์ผ ๋ฐœ์†ก๊นŒ์ง€ ์ž๋™์œผ๋กœ ์ฒ˜๋ฆฌ๋˜๋‹ˆ, ์‚ฌ์šฉ์ž๋Š” ๋” ๊ฐ„ํŽธํ•˜๊ฒŒ ๊ฐ€์ž…ํ•  ์ˆ˜ ์žˆ๊ณ  ๋‚˜๋„ ์š”์ฒญ์ด ์ค„์–ด์„œ ํŽธํ•ด์กŒ๋‹ค!!!

ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ ๋ฉ”์ผ๋„ ์ž˜ ์˜จ๋‹ค ๊ตฟ. (๊ทผ๋ฐ ๋ฉ”์ผ ๋ฐœ์†ก์ด 5์ดˆ๋‚˜ ๊ฑธ๋ฆฌ๋Š”๊ฑด ์–ด๋–ป๊ฒŒ ํ•˜์ง€.)

Project ์นดํ…Œ๊ณ ๋ฆฌ ๋‚ด ๋‹ค๋ฅธ ๊ธ€ ๋ณด๋Ÿฌ๊ฐ€๊ธฐ

Leave a comment