[TypeORM] SubScriber 활용하여 User Role 변경 감지 알림 보내기

어드민이 유저의 등급을 일반 유저에서 Prime 혹은 특별 유저로 변경 시, 해당 유저에게  알림이 가야되는 로직을 TypeORM의 SubScriber를 통해 구현하였다. afterUpdate를 사용하여 유저 테이블에 변경이 생기면 이를 감지하여 알림 테이블에 지정된 알림 데이터를 저장하는 방식으로 하였는데 유저가 유저 정보를 수정해도 해당 afterUpdate가 작동하는 문제가 발생하였다. 

 

이 문제를 해결하기 위해서는 유저 테이블의 변경이 생기기 이전의 정보와 변경 이후의 정보의 특정 칼럼을 활용하여 예외처리를 해야하는데 TypeORM의 공식 Subscriber 문서를 찾아보면 따로 존재하는 것 같지 않았는데 TypeORM 깃헙 이슈에서 event.databaseEntity를 통해 변경이전의 정보를 가져올 수 있다는 것을 발견하였다.

 

Make previous value available in @AfterUpdate function · Issue #4792 · typeorm/typeorm

Issue type: [ ] question [ ] bug report [x] feature request [ ] documentation issue Database system/driver: Any TypeORM version: Any Steps to reproduce or a small repository showing the problem: By...

github.com

event.databaseEntity를 사용하여 변경 이전의 정보를 가져와서 해당 정보의 User Role 칼럼 PRIME 여부와, 변경 이후의 정보를 가져와서 해당 정보의 UserRole 칼럼의 PRIME 여부를 통해 변경 이전에는 COMMON이다가 변경 이후 PRIME인 경우에만 알림을 저장하는 것으로 변경하였다.

@Injectable()
export class UserSubscriber implements EntitySubscriberInterface {
  constructor(@InjectConnection() readonly connection: Connection) {
    connection.subscribers.push(this);
  }

  listenTo() {
    return User;
  }

  async afterUpdate(event: UpdateEvent<User>) {
    const prevData = event.databaseEntity;
    const data = await event.entity;
    if (prevData.role !== 'SPECIAL' && data.role === 'SPECIAL') {
      const notification = this.connection.manager.create(Notification, {
        type: NotificationType.CHANGEDTOSPECIAL,
        targetId: data.id,
        title: '',
        body: '',
        userId: null,
      });
      await this.connection.manager.save(Notification, notification);
    }
  }
}