@Embedded, @Embeddable 을 활용하여 단위 테스트에서 생성자 파라미터 개수를 줄이자!!!~~

반응형

개요

오늘도 평화롭게 코드를 작성하고 있었어요..
저희 팀은 organazation으로 같이 코드를 관리하고 있기에 팀원들의 코드를 염탐해 봤습니다.

그런데!!
처음보는 코드를 발견하였습니다. 그건 바로 Embedded 요건 멀까?
찾아보니 JPA에서 임베디드 타입을 제공하는 방법이었습니다.~~~~~
이걸 활용하면 단위 테스트를 사용할때, 생성자 파라미터의 갯수를 줄일 수 있을꺼 같다!!!

생각해보니...

기존에 사용했었던 빌더 패턴도 생성자 파라미터 갯수를 줄일 수 있지 않나??
갑자기 궁금해졌다. 뭐가 좋은걸까???

그래서 뭘 테스트 했는데.

초반에 다음처럼 단위 테스트를 작성하고 싶었습니다.

String userId = "userI123456";
CoreException result = assertThrows(CoreException.class, () -> new UserModel(userId));
assertThat(result.getErrorType()).isEqualTo(ErrorType.BAD_REQUEST);

그런데 이메일도 단위 테스트가 추가 되었죠..

String email = "email";
CoreException result = assertThrows(CoreException.class, () -> new UserModel(email));
assertThat(result.getErrorType()).isEqualTo(ErrorType.BAD_REQUEST);

 

그러면 내가 선택할 수 있는 방법은 총 2가지 (알고있는)..
생성자 파라미터를 여러개 만들어서 제공하는 방식!!!
두번째는 빌더 패턴을 활용하는 방식!!!!

전자 같은 경우 왠지 모르겠지만 생성자 파라미터를 하나만 추가했으니 2,3,4개짜리도 추가해야할것 같은 느낌이 들었어요..
이렇게 폭팔적으로 생성자 파라미터의 갯수를 줄이는 방법으로 빌더 패턴으로 알고 있었죠.

빌더 패턴

빌더 패턴을 사용하기 위해서는 사전작업이 필요했어요.
저는 직접 만드는 방법을 선택하였고 다음 처럼 만들 수 있었죠.

public class UserModel {
...

  public static UserBuilder builder() {
    return new UserBuilder();
  }

  public static class UserBuilder {
    private String userId;
    private String email;

    public UserBuilder userId(String userId) {
        this.userId = userId;
        return this;
    }

    public UserBuilder email(String email) {
        this.email = email;
        return this;
    }


    public UserModel build() {
        return new UserModel(userId, email);
    }
  }

}

그러면 테스트코드에서는 다음 처럼 작성 할 수 있었어요...

String userId = "userI123456";
CoreException result = assertThrows(CoreException.class, () -> new UserModel.UserBuilder()
						     	                    .userId(userId)
							                    .build());
assertThat(result.getErrorType()).isEqualTo(ErrorType.BAD_REQUEST);

음...
이렇게 만들면 생성자 파라미터의 폭팔은 막을 수 있더라구요.
근데 문제는 빌더 배턴으로 사용해도 null관리는 생성자로 사용했을때랑 별 다를게 없었어요.

if (email == null) {
      throw new CoreException(ErrorType.BAD_REQUEST);
}

이걸 테코로 만들게 되면
null처리에 대한 벨리데이션을 빼지 않는 이상 일반 사용자와 다른게 생긴거 말고는 없는거 같아요..

그러면 임베디드 타입은 뭐가 다를까??

@Embeddable,@Embedded (임베디드 타입)

이 방식도 사전작업이 필요하더라구요.
다음은 Embedeable과 Embedded타입에 대해 적어봤어요.

  • @Embeddable : 값 타입을 정의하는 곳에 표시 (임베디드 타입을 사용하기 위해 생성한 Class에 표시) 
  • @Embedded : 값 타입을 사용하는 곳에 표시 (임베디드 타입을 사용하는 Entity에 표시)
@Embeddable
public class UserId {

  private String userId;

  public UserId() {}

  public UserId(String userId) {
    if (userId == null || userId.trim().isEmpty()) {
      throw new CoreException(ErrorType.BAD_REQUEST, "아이디는 공백으로 생성할 수 없습니다.");
    }
    
    this.userId = userId;
  }

  public String getUserId() {
    return userId;
  }
}

요렇게 사용하고

@Entity
@Table(name = "user")
public class UserModel extends BaseEntity {

@Embedded
private UserId userId;
 ...
}

요렇게 값을 등록하면 되더라구요.
이제 제일 중요한 테스트 코드에서는 어떻게 사용할까요???

String userId = "userI123456";
CoreException result = assertThrows(CoreException.class, () -> new UserId(userId));
assertThat(result.getErrorType()).isEqualTo(ErrorType.BAD_REQUEST);

요로코롬 사용할수 있는데 사용해보니 왠지 UserId에 다른 값들은 넣지 않아도 될거 같았어요..
그러면 일단 생성자 파라미터 갯수를 줄이는건 성공한듯합니다.~~

필요한 만큼 클래스로 만들어야 하기때문에
값들이

String a;
String b;
String c;

요렇게 되어있고 얘네를 임베디드로 관리를 하게 되면 생성자가 3개를 만들어야 하더라구요.

현재

String userId = "userI12345";
String email = "email@email.com";
String birthday = "2020-01-01";
String gender = "M";

UserModel userModel = new UserModel(userId, email, birthday, gender);

assertThat(userModel.getUserId().length()).isLessThanOrEqualTo(10);

요렇게 개발했기때문에 임베디드 타입으로 수정하려면 시간이 조금마니 걸리지 않을까 싶네요...

(참고로 시간은 아무런 의미가 없었다. 파라미터 갯수가 엄청나게 많은건 아니라서 요걸 테스트하지는 못했네요 ㅜㅜ)

결론

임베디드 방식이 독립적으로 userId를 사용할 수 있기때문에 더 좋다고 생각합니다.
빌더도 값을 독립적으로 사용할수도 있지만...
값을 필수로 지정이 되어있다면 빌더에 반드시 넣어줘야 하더라구요..
결국, 빌더는 기존 생성자에서 만든거이기때문에 어쩔 수 없는걸까요??

찾아보니
임베디드 타입은 여러 엔티티에서 공유하면 사이드 이펙트로 인해 부작용이 발생할 수 있다고 하더라구요..

근데 곰곰히 생각해보니 이거 초면아닌거 같은데... 어디서 봤더라....

레퍼런스

- https://inpa.tistory.com/entry/GOF-%F0%9F%92%A0-%EB%B9%8C%EB%8D%94Builder-%ED%8C%A8%ED%84%B4-%EB%81%9D%ED%8C%90%EC%99%95-%EC%A0%95%EB%A6%AC   
- https://tall-developer.tistory.com/16      

'루퍼스 > 1주차' 카테고리의 다른 글

WIL  (0) 2025.07.20

댓글

Designed by JB FACTORY