Java Spring Boot(9)

제이 용·2025년 11월 19일
  • 여태 짠 코드들을 다시 리뷰해보면서 리팩터링하는 시간을 가질려고 하였다.

  • 기본적으로 비밀번호 암호화를 하면서 유저의 U/D 기능에만 적용을 시켰는데, 일정과 댓글에도 적용을 시키기로 하였다.

1. 암호화 시킬 인코드 클래스 생성

@Component
public class PasswordEncoder {

    public String encode(String rawPassword) {
        return BCrypt.withDefaults().hashToString(BCrypt.MIN_COST, rawPassword.toCharArray());
    }

    public boolean matches(String rawPassword, String encodedPassword) {
        BCrypt.Result result = BCrypt.verifyer().verify(rawPassword.toCharArray(), encodedPassword);
        return result.verified;
    }
}
  • 기존에 생성되어 있기에 서비스와 컨트롤러에 수정만 해주면 될 것 같다.

2. DTO생성

  • 삭제 코드는 비밀번호를 받아야하기 때문에 해당 서비스에 관련된 요청 DTO에 password를 꼭 포함 시킨다.

3. Controller 수정

  • 각 기능별 파라미터에 @RequestBody를 통해 비밀번호를 입력하도록 수정한다.
public ResponseEntity<Void> delete(@SessionAttribute(name = "loginUser", required = false) SessionUser sessionUser,
                                       @PathVariable Long scheduleId,
                                       @RequestBody DeleteScheduleRequest request)
  • 다만 여기서 궁금했던 점이 삭제만 하면 되는 요소인데 굳이 DTO를 통해 변환을 시켜줘야하나? 라는 생각이 들었다. 그냥 String password를 요청하면 안되나? 라는..
  • 결론: DTO를 만드는 게 더 좋고, 이 방식을 권장한다.

  • 왜냐하면 @RequestBody String password 받으면 JSON 요청 형태가 이상해지기 때문이다.

"password" : "1234" 가 아니라 "1234"만 보내야되기 때문에 JSON 규격에 맞지 않는다.

  • 또한 가장 중요한 협업을 함에 있어서 프론트에게 비밀번호만 보내야한다면 저 방식이 맞겠지만, 추후 유지보수가 구리고, 확장성이 좋지 못해질 것이다.

  • 깔끔한 클린 코딩을 위해 데이터를 하나만 전달해줘도 DTO로 변환해주는게 맞다는 결론이다!

4. Service 수정

  • 서비스에 코드가 유저에 비해 한 줄이 더 추가되어야한다. 이걸 깨닫는게 초보자 입장에서는 어려울 수도 있을 것 같은 접근이었다.
User user = schedule.getUser();

        if (!passwordEncoder.matches(password, user.getPassword())) {
            throw new CustomException(ErrorCode.INVALID_PASSWORD);
        }
  • 일단 비밀번호와 암호화라는 것이 유저에서 진행되고 유저에 저장되는 비밀번호기 때문에 유저라는 변수를 꺼내와야만한다.

  • 따라서 스캐줄로부터 유저를 뽑아와 User 타입의 user에 넣어줌으로써 유저로부터의 비밀번호를 꺼내올 수 있게 된다.

KeyPointCode

스캐줄 서비스
User user = schedule.getUser();
코멘트 서비스
User user = comment.getUser();
  • 연관관계 매핑이 되어있는 엔터티를 다룰 수록 서비스나, 레퍼지토리, 컨트롤러에 비교적 영향을 코드적으로 끼칠 수 있다는 점이 주의해야한다.

커밋 및 줄 간격 컨벤션

  • 기본적으로 DTO들을 나열해봤을 때 어떤것은 기능 엔터티 응답/요청 어떤 것은 엔터티 기능 응답/요청 순으로 네이밍이 되어있길래 첫글자만 보고서 어떤 기능의 DTO인지 알기 위해 기능 엔터티 응답/요청 으로 통일을 해 주었다.

기존 - ScheduleCreateRequest, UpdateScheduleRequest
변경 - CreateScheduleRequest, UpdateScheduleRequest

  • 그리고 내가 작성한 프로젝트의 컨벤션들을 작성해보았고, 지속 리팩토링하면서 어긋난 곳이 있으면 수정할 예정이다.

코드 컨벤션

  • 패키지 구조는 domain / web / config / exception 으로 나눈다.

  • DTO는 Request/Response 로 명확히 분리한다.

  • 컨트롤러는 유효성 검증 + 서비스 호출만 담당한다.

  • 서비스는 비즈니스 로직의 중심이며, 인증/권한/비밀번호 검증을 포함한다.

  • 엔티티는 setter 를 두지 않고, 변경 메서드를 명확히 만든다.

  • 예외는 CustomException + ErrorCode Enum + ControllerAdvice 로 통일한다.

  • Response DTO는 불변 객체(final 필드)로 만든다.


커밋 컨벤션

커밋 메시지 타입: feat / fix / refactor / docs / chore / test / style / perf / hotfix

  • 기능 추가 시
feat: 일정 비밀번호 검증 추가

- 일정 수정/삭제 시 비밀번호 검증 로직 추가
- PasswordEncoder 적용
- CustomException ErrorCode 활용
  • 오류 수정 시
fix: 댓글 수정 시 댓글 작성자 검증이 동작하지 않던 문제 수정

- Comment.user ID 검증 로직 추가
  • 리팩토링 시
refactor: ScheduleService 권한 검증 코드 서비스 계층으로 이동

- 인증/인가 로직 통일
- 중복 로직 제거

처음부터 사소한 컨벤션들을 몸에 올바르게 습관들여놔야 나중에 현업에서도 지장이 없을 것 같아 정리해본다.

0개의 댓글