간혹가다 개발 시 객체의 타입과 DB의 타입을 다르게해야 하는 경우가 발생한다.
필자는 아래와 상황에 봉착했었다.
고객의 생년월일을 암호화 X -> 암호화 O 로 변경해야 하는 상황
객체의 타입을 수정해야 되나라는 생각이었지만, 좀 더 좋은 방법이 없을까 하다가 전에 사용했던 Convert 방식이 생각이 났다.
따라서 Convert 방식 하나로 손쉽게 Entity <-> DB 를 변환할 수 있다.
다만 형변환 리소스가 증가하는 부분이니 꼭 필요한 경우에만 사용하길 권장한다.
기존 Entity는 다음과 같이 심플하게 진행을 했었다.
@Getter
@MappedSuperclass
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@SuperBuilder
@EntityListeners(AuditingEntityListener.class)
public abstract class BaseUser extends BaseDomainWithId {
...
/**
* 고객 생년월일
*/
@Comment("고객 생년월일")
private LocalDate birth;
}
2024-03-28 14:01:59.129 DEBUG 25620 --- [nio-8080-exec-5] org.hibernate.SQL :
insert
into
USERS
(BIRTH, ...)
values
(?, ...)
2024-03-28 14:01:59.129 TRACE 25620 --- [nio-8080-exec-5] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [DATE] - [2024-03-28]
...
Entity에 @Convert를 이용하기 위해서 AttributeConverter Interface를 상속받은 Converter Class를 생성한다.
@Converter
@Component // 암호화 컴포넌트 사용을 위한 Bean 처리
@RequiredArgsConstructor
public class LocalDateSecurityAttributeConverter implements AttributeConverter<LocalDate, String> {
private final DamoComponent damoComponent;
@Override
public String convertToDatabaseColumn(LocalDate attribute) {
if (attribute == null) {
return null;
} else {
// 암호화 처리
return damoComponent.encrypt(attribute.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
}
}
@Override
public LocalDate convertToEntityAttribute(String dbData) {
if (dbData == null) {
return null;
} else {
// 복호화 처리
return LocalDate.parse(damoComponent.decrypt(dbData), DateTimeFormatter.ofPattern("yyyy-MM-dd"));
}
}
}
위 Converter는 DB 삽입 시 암호화 컴포넌트로 암호화를 하여 String으로 형변환되어 삽입되며, DB 조회 시 암호화 컴포넌트로 복호화를 하여 LocalDate로 형변환 되는 컨버터이다.
이제 Entity에 컨버터를 적용하도록 변경한다.
@Getter
@MappedSuperclass
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@SuperBuilder
@EntityListeners(AuditingEntityListener.class)
public abstract class BaseUser extends BaseDomainWithId {
...
/**
* 고객 생년월일
*/
@Comment("고객 생년월일")
@Convert(converter = LocalDateSecurityAttributeConverter.class)
@Column(columnDefinition = "CHAR(24)")
private LocalDate birth;
}
2024-03-28 14:22:43.271 DEBUG 2036 --- [nio-8080-exec-6] org.hibernate.SQL :
insert
into
USER_CI
(BIRTH, ...)
values
(?, ...)
2024-03-28 14:22:43.272 TRACE 2036 --- [nio-8080-exec-6] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [VARCHAR] - [gwKRRTXS9DOsUPiEsaYQdA==]
...
이제 DB는 암호화가 잘 되어서 들어가고 조회 시 컨버터를 통하여 복호화를 하여 암/복호화가 지저분한 소스 없이 어노테이션으로 깔끔하게 진행되는 것을 볼 수 있다.
해당 부분은 권장사항이 아니며, 무조건 Entity<->DB 간 형변환이 일어나야하는 경우만 추천한다.