[COGO] 커피챗 신청 로직 수정

hwee·2024년 7월 7일
0

COGO개발과정

목록 보기
6/12
post-thumbnail
post-custom-banner

요약

  1. 영속성 컨텍스트에 연관된 엔티티들을 올리고 작업이 필요할 때는 Fetch Join이 유리하다.

수정할 API

현재 커피챗(Application 이하 app)이 성사되어도 해당 커피챗 시간대(PossibleDate 이하 pd)가 조회되는 문제가 존재한다.
따라서 pd의 엔티티에 isAble 필드(default=true)를 추가하여 true인 pd만 조회되도록 쿼리를 수정하고, app이 생성되면(즉, 커피챗이 성사되면) 해당 pd의 isAble을 false로 수정하고자 한다.

pd 조회 쿼리 수정

수정 전

public List<PossibleDateRequestDto> getPossibleDatesByUsername(String username) {
        return queryFactory.
                select(new QPossibleDateRequestDto(
                        possibleDate.date,
                        possibleDate.startTime,
                        possibleDate.endTime
                ))
                .from(user)
                .join(user.mentor, mentor)
                .join(mentor.possibleDates, possibleDate)
                .where(user.username.eq(username)
                .fetch();
    }

수정 후

public List<PossibleDateRequestDto> getPossibleDatesByUsername(String username) {
        return queryFactory.
                select(new QPossibleDateRequestDto(
                        possibleDate.date,
                        possibleDate.startTime,
                        possibleDate.endTime
                ))
                .from(user)
                .join(user.mentor, mentor)
                .join(mentor.possibleDates, possibleDate)
                .where(user.username.eq(username).and(
                        possibleDate.isActive.isTrue()
                ))
                .fetch();
    }

수정사항은 간단하다.
where절에 isActive.isTrue()만 and로 추가해주었다.
하지만 이제 커피챗이 성사되었을 때 pd를 찾아 isActive값을 변경하는 로직 수정이 필요하다.

커피챗 성사 로직 변경

Mentor findMentor = mentorRepository.findById(request.getMentorId())
			.orElseThrow(Exception::new);
		// User findMentorUser = userRepository.findByMentorId(findMentor.getId());
		User findMentorUser = userRepository.findByMentor(findMentor);
		User findMenteeUser = userRepository.findByUsername(userName);
		Mentee findMentee = menteeRepository.findById(findMenteeUser.getId())
			.orElseThrow(Exception::new);
		Application savedApplication = applicationRepository.save(request.toEntity(findMentor, findMentee));
		emailUtil.sendApplicationMatchedEmail(findMenteeUser.getEmail(), findMentorUser.getName(),
			findMenteeUser.getName(), savedApplication.getDate(), savedApplication.getStartTime(),
			savedApplication.getEndTime());
		return ApplicationCreateResponse.from(
			savedApplication

이 로직은 친구가 담당한 레거시라 건드리기 애매하지만, 쿼리가 여러개 발생하는 코드이다.
mentorId로 Mentor로 활동할 User과 Mentor 엔티티를 찾고, username으로 커피챗을 신청한 Mentee를 찾은 후, 받은 DTO를 사용하여 Application을 생성하는 구조이다.
여기서 pd까지 찾으려면 pd.findByMentor까지 추가해야 하므로 조회쿼리만 4개 발생한다.
여기에 수정된 pd를 저장하고, app을 생성하여 저장하는 쿼리까지 생각하면 한 기능에 쿼리만 6개가 발생한다.
따라서 user-mentor-pd를 fetch join으로 묶어서 한번에 영속성 컨텍스트에 올리고, Mentee는 어쩔수 없이 따로 조회쿼리를 보내야 할 것같다.
일반Join을 사용하지 않는 이유는 3개의 엔티티에서 계속하여 정보를 긁어오기 때문에 차라리 모두 영속성 컨텍스트에 올리는 것이 나을 것 같기 때문이다.

수정된 로직

		//필요한 엔티티들 영속성 컨텍스트에 모두 올리기
		User findMentorUser=userRepository.findByMentorIdWithFetch(request.getMentorId());
		Mentor findMentor=findMentorUser.getMentor();
		User findMenteeUser=userRepository.findByUsername(userName);
		Mentee findMentee=findMenteeUser.getMentee();
		//사용자가 신청한 시간대에 해당하는 PossibleDate의 Active 변경로직
		LocalTime startTime = request.getStartTime();
		// 영속성 컨텍스트에서 PossibleDate 엔티티를 모두 가져옴
		List<PossibleDate> possibleDates = em
				.createQuery("SELECT p FROM PossibleDate p", PossibleDate.class)
				.getResultList();
		// startTime이 지정된 시간인 엔티티를 필터링
		Optional<PossibleDate> possibleDateOpt= possibleDates.stream()
				.filter(p -> startTime.equals(p.getStartTime())).findFirst();
		//찾은 PossibleDate의 Active상태 변경
		if(possibleDateOpt.isPresent()) {
            PossibleDate possibleDate=possibleDateOpt.get();
			possibleDate.setActive(false);
			possibleDateRepository.save(possibleDate);
        }
		else throw new Exception("NOT FOUND"); //500에러
		//성사된 커피챗 생성후 반환
		Application savedApplication = applicationRepository.save(request.toEntity(findMentor, findMentee));
		emailUtil.sendApplicationMatchedEmail(findMenteeUser.getEmail(), findMentorUser.getName(),
			findMenteeUser.getName(), savedApplication.getDate(), savedApplication.getStartTime(),
			savedApplication.getEndTime());
		return ApplicationCreateResponse.from(
			savedApplication
		);

코드가 매우 장황하고 더럽다.
2개의 조회쿼리로 커피챗을 신청한 멘티와 담당할 멘토를 찾고, 이 과정에서 영속성 컨텍스트에 fetch join되어 올라온 pd들중 멘티가 신청한 시간대의 pd를 찾아 Active를 전환하고 저장한다.
최종적으로 app을 생성하여 저장하며 로직이 마무리된다.
총 4개의 쿼리가 발생하는데, 2개가 줄어들었어도 응답속도 차원에서 성능이 매우 안좋게 측정되었다.
이를 개선할 방법을 천천히 생각해 보아야 한다.

결과


일단 app이 생성되는 것은 확인되었고,

제일 위에 있는 pd의 Active가 0(false)로 잘 수정된 것을 확인할 수 있다.

profile
https://fuzzy-hose-356.notion.site/1ee34212ee2d42bdbb3c4a258a672612
post-custom-banner

0개의 댓글