🟢

Spring에서 알림 기능 구현(이벤트 비동기 처리)

작성일자
May 18, 2023
태그
SPRING
프로젝트
BeachCombine
책 종류
 
비치컴바인 프로젝트에서 Top 10을 준비하는 과정에서 리팩토링을 거치며 알림 기능을 추가하기로 결정했다.
 
주어진 기한이 매우 짧아 푸시알림까진 넣지 않고 페이지를 리프레쉬했을 때만 보이게 처리해주는 선까지만 구현하기로 했다. 이를 위해선 sse나 소켓같은건 사용할 필요 없고, db처리만 해주면 된다.
 
notification이란 테이블을 만들고 알림 메시지들을 저장하는 것이다.
notion image
우리는 알림 읽음 처리나 알림 삭제 같은 세부 기능들은 제외하고 가장 중요한 알림 목록 보여주는 기능만 만들기로 해서 db가 저 형태지만, 혹시 알림 읽음 처리도 추가하고 싶다면, 별 다를 거 없이 notification 테이블에 boolean 값을 저장하는 읽음 여부 필드도 추가해주면 된다.
 
물론 단순 db처리만 해주진 않았고, 어쨌든 알림은 특정 이벤트이기에 이벤트 등록을 해주고, 비동기 처리를 해주었다. 해당 과정을 아래 정리하겠다.
 
예시는 사용자가 청소 완료 후 포인트를 받으면 포인트를 받았단 알림을 띄어주는 이벤트다. 전체 코드는 아래 링크에서 확인할 수 있다.
Feature/102 clean notification

Spring에서 알림 기능 구현(비동기 처리)

1. 비동기 설정

  • backend/common/config/AsyncConfig.java

2. 알림 메시지 enum 생성

  • backend/event/NotificationCode.java

    3. 알림 인프라 구축 및 테스트

    (1) 이벤트 생성

    Member 클래스와 관련한 이벤트라 MemberEvent라 이름붙였다.
    • backend/event/MemberEvent.java
      • backend/event/MemberEventListener.java

        (2) 테스트

        • backend/event/MemberEventListener.java
          • backend/service/MemberService.java
            • 핵심은 알림 생성 코드를 method의 끝부분에 써주는 것이다. return문이 있다면 그 바로 위에 써준다.
          • 포인트 받는 api를 실행해보면 아래와 같은 로그가 뜨는 걸 확인할 수 있다.
            • notion image

          4. DB에 알림 저장

          • 알림 이벤트가 잘 동작하는 걸 확인했으니, 이제 이벤트가 동작할 때 로그를 찍어주는 대신, notification 테이블에 알림 메시지를 저장하게만 해주면 된다.

          (1) 도메인 추가

          • backend/domain/Notification.java
            • 중간에 extends BaseEntity 부분은 우리 플젝이 base entity를 사용해 수정 시간이랑 생성 시간을 저장해서 그렇다. 없는 플젝은 안써도 좋다.
          • backend/repository/NotificationRepository.java

            (2) 알림 메시지 DB에 저장

            • backend/event/MemberEventListener.java
              • 결과
                • 포인트를 받는 api를 실행했을 때, db에 알림 메시지가 제대로 저장된다.
                • notion image
              • 에러) 혹시 아래 에러가 뜬다면! 아마 높은 확률로 당신의 application.yml의 ddl-auto 값이 none으로 되어 있을 것이다. 즉, notification db가 생성되지 않았거나 db와 entity가 맞지 않아서 뜨는 에러다.
                • Caused by: org.hibernate.exception.SQLGrammarException: could not execute statement
                • 해결 1) 만일 토이프로젝트라면, 그냥 ddl-auto 값을 create이나 update로 바꿔준 후 재실행하면 notification db가 자동으로 생성되어 에러가 뜨지 않게 된다. 대신 db에 이전에 저장해둔 값들이 전부 날라가니 매우매우매우매우매우 매우 주의하자.
                • 해결 2) 토이프로젝트가 아니거나 db의 이전 값들이 날라가면 안되는 상황이면, 직접 sql문을 날려 테이블을 추가해주자! 필자는 notification db를 아래 sql문을 날려 생성했다.
                  • 성공한 SQL문
                    • 실패했던 SQL문
                      • 실패 원인) db와 entity가 맞지 않았음. member_id는 not null인데 null 값을 insert하려 했고, pk에 auto_increment 설정이 안되어 있어 null값이 계속 들어갔음
                    • 이를 작성할 땐, 이전에 ddl-auto가 create일 때 자동으로 생성됐던 sql문을 참고했다. 해당 내용에 대해선 아래 필자가 이전에 정리해둔 포스팅에서 확인할 수 있다.

                다른 알림 추가하기 (재사용성이 좋은 코드다)

                자, 이제 멤버 엔티티와 관련된 다른 알림 이벤트를 추가해보자.
                굉장히 간단한다. 코드 재사용성이 높게 설계됐단 걸 여기서 확인할 수 있다.
                열거형 NotificationCode에 새로운 메시지 내용을 추가해주고, service단에 이벤트를 호출해주는 코드 한 줄만 추가해주면 된다.
                • backend/event/Notification.code
                  • backend/service/TrashcanService.java