[TypeORM] Repository API save와 insert 메서드의 차이점

cabbage·2023년 4월 17일
0

ORM

목록 보기
4/7
post-thumbnail
post-custom-banner

프로젝트 개발 중 만나게 된 문제가 있었는데, insert 메서드의 사용법에 문제가 있었다.

문제 상황

insert 메서드를 사용했을 때 발생한 문제는 다대다 관계에 있는 게시글 엔티티와 해시태그 엔티티의 중간 테이블에 게시글id와 해시태그id가 저장되지 않는다는 문제였다. 게시글 엔티티와 해시태그 엔티티가 정상적으로 저장되는 것은 확인했지만, 중간 테이블에 게시글id와 해시태그id가 저장되지 않았다.

프로젝트 개발 중 게시글 엔티티를 생성하기 위해 typeorm의 create 메서드를, 생성한 게시글 엔티티를 저장하기 위해 typeorm의 insert 메서드를 사용하였다. 엔티티들의 관계를 설정하지 않았을 때는 create 메서드로 생성한 엔티티를 insert 메서드를 사용해 문제 없이 엔티티가 저장되었다.

create 메서드와 insert 메서드를 사용한 서비스 로직은 아래와 같았다.

async createBoard({ createBoardDTO }: IBoardsServiceCreateBoard): Promise<Board> {
  const { title, contents } = createBoardDTO;
  const board = this.boardsRepository.create({
    title,
    contents,
  });
  await this.boardsRepository.insert(board);
  return board;
}

여기서 save 메서드가 아니라 insert 메서드를 사용한 이유는 save 메서드는 테이블에 이미 생성한 엔티티가 존재하는지를 확인하는 단계를 거치기 때문에 insert 메서드 보다 비효율적이라고 생각했기 때문이다.

어쨌든 게시글 엔티티를 생성하고 테이블에 저장하는 것은 문제가 없었는데, 게시글 엔티티와 해시태그 엔티티의 관계를 다대다 관계로 설정한 이후 insert 메서드에 문제가 발생했다.

// board.entity.ts
@ManyToMany(
  () => Hashtag, //
  (hashtags) => hashtags.boards,
  { nullable: true },
)
@JoinTable()
hashtags: Hashtag[];

// hashtag.entity.ts
@ManyToMany(
  () => Board, //
  (boards) => boards.hashtags,
)
boards: Board[];

createBoard 서비스 로직은 아래와 같이 변경하였다.

async createBoard({ createBoardDTO }: IBoardsServiceCreateBoard): Promise<Board> {
  const { title, contents, hashtags } = createBoardDTO;
  const _hashtags = await this.hashtagsService.createHashtags({ hashtags });
  const board = this.boardsRepository.create({
    title,
    contents,
    hashtags: _hashtags,
  });
  await this.boardsRepository.insert(board);
  return board;
}

createBoardDTO에 hashtags라는 문자열 배열을 추가했고, hashtagsService의 createHashtags라는 서비스 로직을 사용해 해시태그 엔티티들을 배열 형태로 반환하게 하였다. 그리고 해시태그 엔티티와 다대다 관계를 설정한 게시글 엔티티를 create 메서드로 생성할 때, 해시태그 엔티티 배열을 hashtags에 할당하였다. 그리고 생성한 게시글 엔티티를 insert 메서드를 사용해 저장하였다.

insert 메서드를 사용했을 때 발생한 문제는 다대다 관계에 있는 게시글 엔티티와 해시태그 엔티티의 중간 테이블에 게시글id와 해시태그id가 저장되지 않는다는 문제였다.

게시글 엔티티와 해시태그 엔티티가 정상적으로 저장되는 것은 확인했지만, 중간 테이블에 게시글id와 해시태그id가 저장되지 않았다.

save 메서드와 insert 메서드

typeorm의 insert 메서드에 대해 구글링한 결과, insert 메서드는 단순히 엔티티를 저장하는 기능만 수행한다고 한다. 또한 다대다 관계의 경우 두 엔티티의 관계를 이어주는 중간 테이블에 대한 작업은 처리하지 않는다고 한다.

결과적으로 이 문제를 해결하기 위해 엔티티를 저장할 때 save 메서드를 사용하였다. save 메서드에 대해 구글링한 결과, save 메서드는 엔티티와 연결된 데이터들, 즉 관련 엔티티들과 중간 테이블 데이터를 모두 저장하므로 다대다 관계의 중간 테이블에도 데이터가 추가된다고 한다.

async createBoard({ createBoardDTO }: IBoardsServiceCreateBoard): Promise<Board> {
  const { title, contents, hashtags } = createBoardDTO;
  const _hashtags = await this.hashtagsService.createHashtags({ hashtags });
  const board = this.boardsRepository.create({
    title,
    contents,
    hashtags: _hashtags,
  });
  await this.boardsRepository.save(board); // save 메서드로 변경
  return board;
}

중간 테이블에 게시글id와 해시태그id가 저장되는 것을 확인할 수 있다.

정리

  • typeorm의 insert 메서드는 단순히 엔티티를 저장하는 기능만 수행한다. 다대다 관계가 설정된 두 엔티티의 중간 테이블에 대한 작업은 처리하지 않는다.
  • typeorm의 save 메서드는 엔티티와 연결된 데이터들, 즉 관련 엔티티들과 중간 테이블 데이터를 모두 저장하므로 다대다 관계의 중간 테이블에도 데이터가 추가된다.
profile
캐비지 개발 블로그입니다. :)
post-custom-banner

0개의 댓글