카테고리 없음

[Spring]_심화 개인 과제 트러블슈팅

cork-7 2025. 2. 27. 14:02

레벨 1

1. 코드 개선 퀴즈 - Early Return

@Transactional
    public SignupResponse signup(SignupRequest signupRequest) {


        String encodedPassword = passwordEncoder.encode(signupRequest.getPassword());

        UserRole userRole = UserRole.of(signupRequest.getUserRole());

        if (userRepository.existsByEmail(signupRequest.getEmail())) {
            throw new InvalidRequestException("이미 존재하는 이메일입니다.");
        }

        User newUser = new User(
                signupRequest.getEmail(),
                encodedPassword,
                userRole
        );
        User savedUser = userRepository.save(newUser);

        String bearerToken = jwtUtil.createToken(savedUser.getId(), savedUser.getEmail(), userRole);

        return new SignupResponse(bearerToken);
    }

기본 코드에서 이메일 확인 로직이 passwordEncoder 뒤쪽에 위치해 이미 존재하는 이메일을 사용시 위 로직이 불필요하게 동작

if (userRepository.existsByEmail(signupRequest.getEmail())) {
    throw new InvalidRequestException("이미 존재하는 이메일입니다.");
}

String encodedPassword = passwordEncoder.encode(signupRequest.getPassword());

UserRole userRole = UserRole.of(signupRequest.getUserRole());

User newUser = new User(
        signupRequest.getEmail(),
        encodedPassword,
        userRole
);

이메일 확인로직이 위로 가게 작성

 

2. 리팩토링 퀴즈 - 불필요한 if-else 피하기

 

WeatherDto[] weatherArray = responseEntity.getBody();
if (!HttpStatus.OK.equals(responseEntity.getStatusCode())) {
    throw new ServerException("날씨 데이터를 가져오는데 실패했습니다. 상태 코드: " + responseEntity.getStatusCode());
} else {
    if (weatherArray == null || weatherArray.length == 0) {
        throw new ServerException("날씨 데이터가 없습니다.");
    }
}

if else-if문은 첫 if문과 반대되고 다른 조건을 걸어야할 때 사용한다 다만 현재 로직에서 굳이 else로 묶지 않고 if문으로 작성해도 이상이 없고 가독성에 좋다

WeatherDto[] weatherArray = responseEntity.getBody();
if (!HttpStatus.OK.equals(responseEntity.getStatusCode())) {
    throw new ServerException("날씨 데이터를 가져오는데 실패했습니다. 상태 코드: " + responseEntity.getStatusCode());
}

if (weatherArray == null || weatherArray.length == 0) {
    throw new ServerException("날씨 데이터가 없습니다.");
}

 

 

3. 코드 개선 퀴즈 - Validation

 

비밀번호 변경시 검증로직을 DTO로 옮기자

 

@NotBlank
private String oldPassword;
@NotBlank
@Pattern(regexp = "(?=.*\\d.*)(?=.*[A-Z].*).{8,}", message = "새 비밀번호는 8자 이상이어야 하고, 숫자와 대문자를 포함해야 합니다.")
private String newPassword;

 

 

레벨 2

N+1 문제

 

@Query("SELECT t FROM Todo t LEFT JOIN FETCH t.user u ORDER BY t.modifiedAt DESC")
Page<Todo> findAllByOrderByModifiedAtDesc(Pageable pageable);

todoController와 todoService에서 발생하는 N+1문제를 해결하기 위해 작성된 todoRepository로직이다.

이와 같은 동작을 하는 EntityGraph로 작성해보자

 

@EntityGraph(attributePaths = {"user"})
Page<Todo> findAllByOrderByModifiedAtDesc(Pageable pageable);

 

 

레벨 3

테스트 코드 연습 - 1

encode를 하는 encodedPassword가 앞에 있어 에러발생

@Test
void matches_메서드가_정상적으로_동작한다() {
    // given
    String rawPassword = "testPassword";
    String encodedPassword = passwordEncoder.encode(rawPassword);

    // when
    boolean matches = passwordEncoder.matches(rawPassword, encodedPassword);

    // then
    assertTrue(matches);
}

 

테스트 코드 연습 - 2-1

 

 

expected의 메세지와 메소드명이 틀리다

@Test
public void manager_목록_조회_시_Todo가_없다면_IRE_에러를_던진다() {
    // given
    long todoId = 1L;
    given(todoRepository.findById(todoId)).willReturn(Optional.empty());

    // when & then
    InvalidRequestException exception = assertThrows(InvalidRequestException.class, () -> managerService.getManagers(todoId));
    assertEquals("Todo not found", exception.getMessage());
}

 

테스트 코드 연습 - 2-2

exception이 잘못 적혀있다

 

@Test
public void comment_등록_중_할일을_찾지_못해_에러가_발생한다() {
    // given
    long todoId = 1;
    CommentSaveRequest request = new CommentSaveRequest("contents");
    AuthUser authUser = new AuthUser(1L, "email", UserRole.USER);

    given(todoRepository.findById(anyLong())).willReturn(Optional.empty());

    // when
    InvalidRequestException exception = assertThrows(InvalidRequestException.class, () -> {
        commentService.saveComment(authUser, todoId, request);
    });

    // then
    assertEquals("Todo not found", exception.getMessage());
}

 

테스트 코드 연습 - 2-3

유저가 null인 상황이 서비스 로직에 들어가 있지 않아 메세지가 안뜨고 에러가 발생

 

Transactional
public ManagerSaveResponse saveManager(AuthUser authUser, long todoId, ManagerSaveRequest managerSaveRequest) {
    // 일정을 만든 유저
    User user = User.fromAuthUser(authUser);
    Todo todo = todoRepository.findById(todoId)
            .orElseThrow(() -> new InvalidRequestException("Todo not found"));

    if (todo.getUser() == null || !ObjectUtils.nullSafeEquals(user.getId(), todo.getUser().getId())) {
        throw new InvalidRequestException("담당자를 등록하려고 하는 유저가 일정을 만든 유저가 유효하지 않습니다.");
    }

if문에 null 추가