개인프로젝트/스터디 앱

스터디 앱 04 - CommonResponse, record 클래스

노루동산 2024. 11. 11. 23:32

CommonResponse

@Builder
public record CommonResponseDto<T>(HttpStatusCode code, String message, T data) {

}

@Builder
public record CommonErrorResponseDto(HttpStatusCode code, String message, String path, LocalDateTime timestamp) {
}

정형화된 response를 반환하기 위해 CommonResponseDto를 만들었다.

네트워크 상태 코드, 메시지, 실질적으로 전달할 데이터로 구성되어 있다.

Error response의 경우에는 데이터 대신 path(호출한 api를 나타낸다)와 타임스탬프를 담았다.

 

그런데 이런 DTO 클래스를 더 간편하게 만들어주는 record 클래스라는 게 있다고 한다.

 

 

record 클래스

record는 JDK16부터 등장하는 특별한 클래스이다. (프리뷰로 나온 건 JDK14)

불변 객체를 위한 클래스로 간단하게 데이터를 저장하고 옮기는 데에 사용한다고 한다.

딱 DTO에 어울리는 클래스이다.

 

record 클래스는 아래와 같은 것들은 자동으로 구현해 준다.

  • 필드 캡슐화
  • 생성자 메서드
  • getters 메서드
  • equals 메서드
  • hashcode 메서드
  • toString 메서드

나는 여기에 편의성과 통일성을 위해 Builder 어노테이션만 추가해 주었다.

다른 필드를 구현하는 것도 가능하지만 불변객체를 위한 클래스이기 때문에

내부에 선언되는 모든 필드는 static이어야만 한다.

 

 

도커 데스크탑 이슈

deploying wsl2 distributions provisioning docker wsl distros: ensuring main distro is deployed: checking if main distro is up to date: checking main distro bootstrap version: getting main distro bootstrap version: open \\wsl$\docker-desktop\etc\wsl_bootstrap_version: the network name cannot be found.

도커 데스크탑을 실행하는 데 자꾸 이런 에러가 떠서 시간이 좀 걸렸다.

 

wsl --unregister docker-desktop

PowerShell에 위와 같은 명령어를 입력하니까 해결됐다.

 

 

기타 등등

이 외에도 docker 설정도 하고 properties도 손 보고...

전체적으로 전체적인 틀을 다듬는 작업을 하였다.

거의 반년 전에 짜놨던 코드들이 정말 방해가 됐다.

 

  public void signUp(UserRequestDto requestDto) {
    if (userRepository.existsByEmail(requestDto.getEmail())) {
      throw new BusinessException(ErrorCode.ALREADY_EXISTING_USER);
    }

    User user = User.builder()
        .nickname(requestDto.getNickname())
        .email(requestDto.getEmail())
        .password(passwordEncoder.encode(requestDto.getPassword()))
        .state(State.ACTIVE)
        .role(Role.User)
        .build();

    userRepository.save(user);
  }

  public void withdrawal(User user) {
    user.updateState(State.DELETED);
  }

회원가입, 회원탈퇴도 간단하게 구현해 보았다.

유저를 직접 삭제하지 않고 state를 deleted로 설정해 준다는 것이다.

 

이것을 구현하기 위해 erd도 조금 수정하였다.

state, 겸사겸사 role 칼럼도 추가해 주었다.

 

@Getter
@Entity
@NoArgsConstructor
@Table(name = "users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false)
    private String nickname;

    @Email
    @Column(unique = true, nullable = false)
    private String email;

    @Column(nullable = false)
    private String password;

    @Column(nullable = false)
    @Enumerated(EnumType.STRING)
    private State state;

    @Column(nullable = false)
    @Enumerated(EnumType.STRING)
    private Role role;

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "user", cascade = CascadeType.ALL)
    private List<Post> post = new ArrayList<>();

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "user", cascade = CascadeType.ALL)
    private List<Comment> comment = new ArrayList<>();

    @Builder
    public User(String nickname, String email, String password, State state, Role role) {
        this.nickname = nickname;
        this.email = email;
        this.password = password;
        this.state = state;
        this.role = role;
    }

    public void updateState(State state) {
        this.state = state;
    }

    public enum State {
        ACTIVE,
        DELETED,
        BLOCK;
    }

    public enum Role {
        User,
        Admin
    }
}

그런데 이제 보니 createdAt과 updatedAt 칼럼 추가도 필요해 보인다... 이럴 수가.

이는 타임스탬프용 MappedSuperclass를 만들어서 상속받도록 하겠다.

 

@Getter
public class UserRequestDto {
    @Size(min = 2, max = 20)
    private String nickname;

    @Email
    private String email;

    @Size(min = 8, max = 20)
    private String password;
}

그리고 회원가입 시 사용하는 dto인데 password 제한을 어떻게 둘 지도 좀 생각해야겠다.

 

블로그에 개발한 내용 정리하는 게 정말 귀찮았는데

쓰고 나니 부족한 점이 잘 보이는 것 같다.

아무래도 혼자 개발하는 만큼 이런 점을 캐치하기가 힘든데 기록하는 습관을 들여야겠다.

 

 

에러 하나

org.springframework.http.converter.HttpMessageConversionException: Type definition error: [simple type, class java.time.LocalDateTime]

에러가 하나 발생했는데 오늘은 피곤해서 내일 개선해 봐야겠다.

LocalDateTime 파싱 문제가 생긴 것 같은데 처음 보는 오류다.

record 클래스를 사용하며 발생한 사이드임팩트일지도 모르겠다.

 

 

차회 예고

  1. 회원가입 시 email 인증 - redis 활용
  2. 로그인, 로그아웃
  3. 비밀번호 재설정