문제 상황

요구 사항 및 분석

팀 빌딩 서비스를 만들면서 다음과 같은 요구 사항이 있었다.

사용자는 여러 팀에 속할 수 있다. 팀에는 여러 명의 사용자가 속할 수 있다.

이 간단한 요구 사항을 개발하기 위해 다음과 같이 진행했다. 참고로 JPA를 사용했다.

  1. 사용자는 User, 팀은 Team이라 한다.
  2. UserTeam은 다대다 관계이다. 일대다—다대일 관계로 분리하기 위해 중간 테이블을 사용한다.
  3. 사용자가 팀에 속하면 그 사용자는 그 팀의 팀원이다. 이때 팀원을 Member라고 한다.
  4. Member는 중간 테이블에 대응된다. Member는 고유한 속성을 갖기 때문에 엔티티로 사용한다.
  5. 따라서 UserMember는 일대다 관계이고 MemberTeam은 다대일 관계이다.
  6. 이때 member 테이블에 user_id와 team_id를 외래키로 갖게 된다.

새로운 팀원을 등록할 때의 코드는 다음과 같다.

// userId와 teamId를 알고 있는 상황

User user = userRepository.findById(userId)
			.orElseThrow(RuntimeException::new); // todo: create exception

Team team = teamRepository.findById(teamId)
			.orElseThrow(RuntimeException::new); // todo: create exception

Member member = Member.builder()
			.user(user)
			.team(team)
			.role(MEMBER) // 추가로 갖는 속성 값 예시
			.build();

memberRepository.save(member);

어떤게 아쉬웠을까?

Member를 저장, 조회, 수정, 삭제(CRUD)할 때 매번 UserTeam을 찾아야 했다. 따라서 매번 2번씩 select 쿼리가 나갔다. UserTeam에 관련된 도메인 로직이 있다면 상관 없지만, Member를 CRUD 하기 위한 용도로 매번 조회하는 것이 아쉬웠다. 그래서 방법이 없을까 고민을 해보았다.

조회 쿼리 줄이기

우선 어떤 상황인지 살펴보자.