예외 처리 때문에 Optional?

Code_Angler·2021년 8월 10일
0

JAVA

목록 보기
1/1

null의 대한 처리를 어떻게 할수있을까를 한번이라도 고민해 보았다면 Optional을 쓰는것을 고민해 보셨을것이다.

  • 먼저 Optional을 쓴 예시를 살펴보자
// Project 수정
    @Transactional
    public ProjectResponseDto updateProject(Long projectId, ProjectRequestDto requestDto, SessionUser sessionUser) {

        Optional<UserProjectMapping> userProjectMapping = userProjectMappingRepository.findByUserIdAndProjectIdJoin(sessionUser.getUserId(),projectId);

        if(!userProjectMapping.isPresent()){
            throw new ApiRequestException("프로젝트에 참가한 사용자가 아닙니다.");
        }else if(!userProjectMapping.get().getRole().equals(UserProjectRole.OWNER)){
            throw new ApiRequestException("프로젝트 소유주가 아닙니다.");
        }
        Project project = userProjectMapping.get().getProject();
        project.update(requestDto);

        return ProjectResponseDto.fromEntity(project);
    }

여기서는 예외와 조건을 따로 구분하지 않고 처리하였다는 것이다, 코드만 본다면 if 와 else if 모두 조건에 대한 처리로 보일수도있지 않을까 하는 생각이 들었다.

예외는 예외 답게, 조건은 조건 답게 처리 할 수 있는 방법을 생각해 보기로 하자!

먼저 Optional을 빼보자

// Project 수정
    @Transactional
    public ProjectResponseDto updateProject(Long projectId, ProjectRequestDto requestDto, SessionUser sessionUser) {

        UserProjectMapping userProjectMapping = userProjectMappingRepository.findByUserIdAndProjectIdJoin(sessionUser.getUserId(), projectId);
				
				// 예외처리
        if(Objects.isNull(userProjectMapping)) {
            throw new ApiRequestException("프로젝트에 참가한 사용자가 아닙니다.");
        }
				// 조건 처리(오너가 아니면 수정 불가) 
        if (!userProjectMapping.getRole().equals(UserProjectRole.OWNER)) {
            throw new ApiRequestException("프로젝트 소유주가 아닙니다.");
        }
        Project project = userProjectMapping.getProject();
        project.update(requestDto);

        return ProjectResponseDto.fromEntity(project);
    }

Optional을 쓰지 않고도 예외와 조건이 처리됨을 확인할수있다.


또 하나의 방법인 현재 여기서 findByUserIdAndProjectIdJoin 메소드는 Querydsl로 형성 되었다.

@Override
public UserProjectMapping findByUserIdAndProjectIdJoin(Long userId, Long projectId) {
    return queryFactory
            .select(userProjectMapping)
            .from(userProjectMapping)
            .join(userProjectMapping.project).fetchJoin()
            .where(userProjectMapping.user.userId.eq(userId), userProjectMapping.project.projectId.eq(projectId))
            .fetchFirst();
}

현재 userProjectMapping은 N-M 관계을 이어주는 하나의 Entity로서 , user 한 명이 project하나를 가지는 결과 값을 가지게 설정되었다.

이번엔 findByUserIdAndProjectIdJoin 메소드에서 null 에 대한

예외처리를 해보도록하자

@Override
public UserProjectMapping findByUserIdAndProjectIdJoin(Long userId, Long projectId) {
    return Optional.ofNullable(queryFactory
            .select(userProjectMapping)
            .from(userProjectMapping)
            .join(userProjectMapping.project).fetchJoin()
            .where(userProjectMapping.user.userId.eq(userId), userProjectMapping.project.projectId.eq(projectId))
            .fetchFirst())
            .orElseThrow(() -> new ApiRequestException("프로젝트에 참가한 사용자가 아닙니다."));
}
// Project수정
@Transactional
public ProjectResponseDto updateProject(Long projectId, ProjectRequestDto requestDto, SessionUser sessionUser) {

    UserProjectMapping userProjectMapping = userProjectMappingRepository.findByUserIdAndProjectIdJoin(sessionUser.getUserId(), projectId);

    if (!userProjectMapping.getRole().equals(UserProjectRole.OWNER)) {
        throw new ApiRequestException("프로젝트 소유주가 아닙니다.");
    }
    Project project = userProjectMapping.getProject();
    project.update(requestDto);

    return ProjectResponseDto.fromEntity(project);
}

모든 것이 정상적으로 작동한다.

그렇다면 무엇이 좋은 선택일까?

스타일의 차이라고 볼 수 있을 것 같다.

하지만 굳이 고르라고 한다면 예외처리는 query method 을 이용해 찾아올 때 부터 처리해서 가져와서 이후 불필요한 작업을 서비스단에서 하기 전에 예외가 발생하는 것이 낫다고 생각한다.

무엇보다. 예외는 예외 답게 조건은 조건 답게 라는 것에서 예외는 query method 에서 조건은 서비스단에서 처리하는 것이 개인적으로는 좋은 것 같다.

profile
CodeAngler

0개의 댓글