SubScriber afterRemove( )에서 removeEvent의 Entity가 notFound인 이유

LikeCount와 같은 테이블의 number 칼럼에 +1 혹은 -1을 할 일이 생기는 경우, +1을 하는 API를 새로 구성하는 것 보다 Like 테이블에 row가 추가될 때마다 SubScriber에서 트랜잭션을 열고, +1을 추가하는 것이 프론트의 api 호출 빈도를 줄일 수 있다는 점에서 장점이 있다고 생각하였다.

 

+1의 경우, TypeORM afterInsert( )를 사용하여 insertEvent가 해당 테이블에서 발생시 number +=1을 하는 방식으로 작성하여, 정상적으로 likeCount 칼럼의 값에 +1이 되는 것을 확인하였는데, -1의 경우, 테이블에서 해당 정보가 삭제되더라도 removeEvent가 row가 삭제된 것을 체크하지않아 -=1이 되지않는 문제가 발생하였다.

원인

Delete 메소드를 활용하는 REST api는 Service단에서 repository.delete({id})를 사용하여 id 값을 통해 해당 row를 삭제하는 경우가 많았다. 관련 TypeORM Issue를 살펴보면 repository.delete()를 사용하지 말고, repository.remove()를 사용하면 removeEvent가 작동한다고 되어있다.

 

Undefined entity on RemoveEvent · Issue #6876 · typeorm/typeorm

Issue type: [x] bug report [ ] feature request [ ] documentation issue Database system/driver: [ ] cordova [ ] mongodb [ ] mssql [x] mysql / mariadb [ ] oracle [ ] postgres [ ] cockroachdb [ ] sqli...

github.com

해결방법

해당 removeEvent가 작동해야되는 Delete 메소드 API의 Service 부분을 repository.delete({id})에서 repository.remove(repository)의 방식으로 변경하였다.

.delete()를 사용할 때는 아래와 같이 테이블에서 검색하지않고, 바로 id값만을 통해 삭제하였다.

deleteLikeById(id: number) {
    return this.repository.delete({ id });
  }

.remove의 경우, 아래와 같이 테이블에서 id값을 통해 find를 해와서 불러온 해당 엔티티 자체를 삭제하는 방식으로 하였다.

async deleteLike(id: number) {
    const like = await this.repository.findOne({ id });
    this.repository.remove(like);
  }

 

해결된 이유

평소라면 "해결했다~"하고 끝내겠지만, .remove와 .delete 어떻게 보면 '삭제'라는 동일한 기능을 하는 함수를 굳이? typeorm에서 두 가지로 나눠서 구현해놓은 이유와 .remove와 .delete의 차이점, 왜 removeEvent는 delete() 사용시 작동하지않는지 모르겠어서 이에 대해 알아보았다. TypeORM 깃헙의 repository API 문서를 확인해보면 아래와 같이 설명되어있다.

repository.remove( ) 

한 트랜잭션안에 주어진 Entity나 Entitiy Array를 삭제한다. 삭제된 Entity 혹은 Entities를 리턴합니다.

repository.delete( )

주어진 id, ids 또는 조건으로 Entitiy를 삭제합니다.

위의 두 설명만 봐도 왜 removeEvent의 Entiity가 undefined였는지 이해가 되었다. .remove의 경우, 삭제하고 나서 해당 삭제된 Entity를 리턴하지만, .delete의 경우, 리턴하는 값 없이 삭제해버린다.

결론은 "공식 깃헙에서 문서를 잘 읽어보자" 였다.

 

참고) https://github.com/typeorm/typeorm/blob/master/docs/repository-api.md