프로젝트 리팩토링 주저리

Muji1412·2025년 4월 22일

프로젝트

목록 보기
1/4

코드가 '개판' 이다.

문제는 이러하다.
1. 엔티티를 두번이나 조회하고 있다.
2. boolean타입으로 조회해서 한번 더 유저를 불러오는 작업을 한다.
3. 컨트롤러에서 try-catch 문 하나만 사용하는게 아니라 if문 + try-catch문 사용중.

AuthController

 @PostMapping("/find-id")
    public ResponseEntity<ApiResponseDto> findIdByEmail(@Valid @RequestBody FindIdRequestDto requestDto) {


        if (!userService.checkUserByNameAndPhoneAndEmail(requestDto)){
            return ResponseEntity.
                    status(HttpStatus.NOT_FOUND).
                    body(ApiResponseDto.fail("일치하는 유저가 존재하지 않습니다."));
        }

        try {
            userService.sendUserIdToEmail(requestDto);
            // UserService 호출이 성공하면 (예외가 발생하지 않으면)
            String successMessage = "아이디 정보가 [" + requestDto.getEmail() + "] 주소로 발송되었습니다. 메일을 확인해주세요.";
            log.info(successMessage);
            return ResponseEntity.ok(ApiResponseDto.success(successMessage));

        } catch (EntityNotFoundException e) {
            // UserService에서 사용자를 찾지 못했을 때
            log.warn("아이디 찾기 실패 (사용자 없음): {}", e.getMessage());
            return ResponseEntity
                    .status(HttpStatus.NOT_FOUND) // 404 Not Found
                    .body(ApiResponseDto.fail(e.getMessage()));

        } catch (RuntimeException e) {
            // EmailService에서 메일 발송 실패 등 기타 런타임 예외 처리
            log.error("아이디 찾기 중 서버 오류 발생: {}", e.getMessage(), e); // 스택 트레이스 포함 로깅
            String errorMessage;
            // 메일 발송 관련 예외인지 확인 (더 구체적인 원인 파악 가능)
            if (e.getCause() instanceof MailException) {
                errorMessage = "이메일 발송 시스템에 오류가 발생했습니다. 잠시 후 다시 시도해주세요.";
            } else {
                errorMessage = "아이디 찾기 처리 중 오류가 발생했습니다.";
            }
            return ResponseEntity
                    .status(HttpStatus.INTERNAL_SERVER_ERROR) // 500 Internal Server Error
                    .body(ApiResponseDto.fail(errorMessage));
        }
   }

UserService

 @Transactional(readOnly = true) // 조회 작업이므로 readOnly
    public void sendUserIdToEmail(FindIdRequestDto requestDto) {
        String email = requestDto.getEmail();

        // 1. 이메일로 사용자 조회
        Users foundUser = usersRepository.findByEmail(email)
                .orElseThrow(() -> new EntityNotFoundException("해당 정보로 가입된 사용자를 찾을 수 없습니다."));

        // 2. 사용자가 존재하면 EmailService를 통해 아이디 발송
        mailService.sendUserIdByEmail(foundUser.getEmail(), foundUser.getId());
    }

갈아엎은 코드

AuthController

@PostMapping("/find-id")
    public ResponseEntity<ApiResponseDto> findIdByEmail(@Valid @RequestBody FindIdRequestDto requestDto) {

        // 이프(이름, 전화번호, 이메일을 받아서 유저가 있는지 조회하는)문 삭제 - service 안에 넣어서 일관성 있게 해결함
        try {
            userService.sendUserIdToEmail(requestDto);
            // UserService 호출이 성공하면 (예외가 발생하지 않으면)
            String successMessage = "아이디 정보가 [" + requestDto.getEmail() + "] 주소로 발송되었습니다. 메일을 확인해주세요.";
            log.info(successMessage);
            return ResponseEntity.ok(ApiResponseDto.success(successMessage));

            // 캐치해야할거,
            // EntityNotFoundException (sendUserIdToEmail 에서 던져줌)
            // MailException - 메일 보낼때 오류
            // RuntimeException - 서버 오류
        } catch (EntityNotFoundException e) {
            // UserService에서 사용자를 찾지 못했을 때
            log.warn("아이디 찾기 실패 (사용자 없음): {}", e.getMessage());
            return ResponseEntity
                    .status(HttpStatus.NOT_FOUND) // 404 Not Found
                    .body(ApiResponseDto.fail(e.getMessage())); // sendUserIdToEmail에서 실어둔 메세지가 실림
        } catch (MailException e) {
            log.error("이메일 전송 중 서버 오류 발생: {}", e.getMessage(), e);
            String errorMessage = "이메일 전송중 오류가 발생했습니다. 다시 시도해주세요";
            return ResponseEntity
                    .status(HttpStatus.INTERNAL_SERVER_ERROR)
                    .body(ApiResponseDto.fail(errorMessage));
        }
        catch (RuntimeException e) {
            // EmailService에서 메일 발송 실패 등 기타 런타임 예외 처리
            log.error("아이디 찾기 중 서버 오류 발생: {}", e.getMessage(), e); // 스택 트레이스 포함 로깅
            String errorMessage = "아이디 찾기 중 오류가 발생했습니다.";
            return ResponseEntity
                    .status(HttpStatus.INTERNAL_SERVER_ERROR) // 500 Internal Server Error
                    .body(ApiResponseDto.fail(errorMessage));
        }
   }

UserService

@Transactional(readOnly = true) // 조회 작업이므로 readOnly
    public void sendUserIdToEmail(FindIdRequestDto requestDto) {

        //사용자 존재 체크 + 유저 불러오기
        Users foundUser = usersRepository.findByNameAndPhoneAndEmail(
                requestDto.getName(),
                requestDto.getPhone(),
                requestDto.getEmail()
        ).orElseThrow(() -> new EntityNotFoundException("입력한 정보와 일치하는 유저가 없습니다22."));

        // 사용자가 존재하면 EmailService를 통해 아이디 발송
        mailService.sendUserIdByEmail(foundUser.getEmail(), foundUser.getId());
    }

개선점

  1. 이제는 DB를 한번만 조회함
  2. 가독성 향상
  3. 책임 분리 - 컨트롤러의 역할(호출 위임, http 상태 출력 등)에 집중시킴
profile
박치기공룡의 개발일지

0개의 댓글