make it simple
article thumbnail

개요

  • 간단하게 채용에 관련된 도메인을 설계를 했다. 보통 채용 공고를 작성할 때 경력직의 년차를 설정한다. 하지만 해당값을 Enum으로 관리하고 싶다. Enum값으로 관리하려는 이유는 여러가지가 있다.
    1. 해당 필드값을 사용할 때 컴파일러가 Enum값 타입을 검사해줘서 코드의 대한 안정성이 높아진다. 
    2. 유지보수하기가 쉬워진다. 공통으로 사용하는 Enum은 수정사항이 있을 경우 그 부분만 수정하면된다.
    3. 가독성이 좋아진다. 상수값으로 되어있어서 보기가 편하다. 
  • 보통은 Enum값이 String으로 하나인경우 @Enumerated(EnumType.STRING) 을 사용하면 된다. 하지만 나의 경우에는 경력직의 년차의 Enum값 같은 경우에는 년도를 나타내는 Year이라는 int값과 해당 데이터를 텍스트로 나타내는 String값 두개의 인스턴스 필드값이 필요하다.
  • DB에 저장할 때는 int값으로 해야 공고를 년차로 필터링해서 조회할 때 조건을 걸기 편하다. 굳이 text값이 왜 필요한지 의문이을 가질 수 있다. 필자 생각으론 클라이언트한테 응답을 내려줄 때 text값(ex: 1년차 이상)을 내려주면 나중에 서버 쪽에서만 수정을 해도 관리하기 편하고 유지보수가 용이할 거 같아서 밑과 같이 설계했다.  
@Getter
@RequiredArgsConstructor
public enum RequiredCareerStatus {
    YR_1(1, "1년차 이상"),
    YR_2(2, "2년차 이상"),
    YR_3(3, "3년차 이상"),
    YR_4(4, "4년차 이상"),
    YR_5(5, "5년차 이상"),
    NONE(100, "경력 무관");

    private final int year;
    private final String text;

}

 

내가 사용한 방법

  • 내가 원하던건 DB에 저장할때는 Int값 Entity로 변환할경우에는 해당 Enum값을 부르고싶었다. 그래서 찾아보니 보편적으로 많이 쓰는 방법이 JPA에서 지원하는 @Converter를 활용해서 많이 사용한다.
@Converter
public class CareerStatusConverter implements AttributeConverter<RequiredCareerStatus, Integer> {

    @Override
    public Integer convertToDatabaseColumn(RequiredCareerStatus status) {
        return status.getYear();
    }

    @Override
    public RequiredCareerStatus convertToEntityAttribute(Integer dbData) {
        for(RequiredCareerStatus status : RequiredCareerStatus.values()){
            if(status.getYear() == dbData){
                return status;
            }
        }
        throw new IllegalArgumentException("없는 경력 년수 입니다." + dbData);
    }

}
  1. AttributerConverter 인터페이스를 구현한다. 필드값엔 Wrapping class 밖에 안되서 int말고 Integer를 사용했다.
  2. convertToDatabaseColumnn 을 상속받아 구현한다. 이름 그대로 DB에 저장될때의 값이다. int값으로 저장하고싶어 리턴값을 year로 리턴했다. 
  3. convertToEntityAttribute을 상속받아 구현한다. DB에서 데이터를 받아 엔티티로 변환될떄의 값이다. dbData라는 값을 DB에서 받아 그 값에 맞는 RequiredCareerStatus Enum값을 리턴했다.
@Getter
@Entity
@Table(name = "recruitments")
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Recruitment extends BaseEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @Convert(converter = CareerStatusConverter.class)
    private RequiredCareerStatus requiredCareerStatus;
    
 }
@Getter
public class RecruitmentResponse {
    private Long id;
    private String title;
    private String requiredCareerYear;

    @Builder
    public RecruitmentResponse(Long id, String title, String requiredCareerYear) {
        this.id = id;
        this.title = title;
        this.requiredCareerYear = requiredCareerYear;
    }

    public static RecruitmentResponse of(Recruitment recruitment) {
        return RecruitmentResponse.builder()
                .id(recruitment.getId())
                .title(recruitment.getTitle())
                .requiredCareerYear(recruitment.getRequiredCareerStatus().getText())
                .build();
    }
}

 

위처럼 도메인에 @Converter(converter = 생성한 컨버터 클래스)를 붙혀주면 DB로 들어갈 때는 convertToDatabaseColumnn() 에 작성한 것처럼 인서트 되고 Entity로 변환될 때는 convertToEntityAttribute()에 작성한대로 Entity로 변환된다. 위에RecruritmentResponse처럼 클라이언트에 내려줄 떄는 String값으로 필자가 원하는 의도대로 사용이 가능하다.

profile

make it simple

@keep it simple

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!