DB

[JPA] 엔티티 값을 변환하여 저장, 조회하기(Feat: @Converter)

수수한 인간 2025. 3. 10. 01:22

어떤 값을 저장할 때 데이터베이스에 저장할 때 원하는 값으로 저장하고 조회할 때도 원하는 값이나 타입으로 반환할 때 사용합니다.
예를 들어 개인정보의 암호화하여 저장해야하거나 Boolen 타입일 때 Y, N 값으로 데이터베이스에 저장하는 등 다양한 경우에 사용될 수 있습니다.


AttributeConverter란

AttributeConverter 클래스는 프로퍼티의 값을 저장하거나 읽을 때 사용할 수 있는 인터페이스입니다.

public interface AttributeConverter<X, Y> {
    // 엔티티의 데이터를 데이터베이스 컬럼에 저장할 데이터로 변환한다.
    Y convertToDatabaseColumn(X attribute);
    // 데이터베이스에서 조회한 컬럼 데이터를 엔티티 데이터로 변환한다.
    X convertToEntityAttribute(Y dbData);
}

사용예제

암호화 및 복호화할 때 사용하는 케이스에 대해서 설명하겠습니다.

import jakarta.persistence.AttributeConverter;

public class CryptoConverter implements AttributeConverter<String, String> {
    @Override
    public String convertToDatabaseColumn(String text) {
        // 데이터베이스 저장할 때 호출됩니다.
        return Crypto.encrypt(text);
    }

    @Override
    public String convertToEntityAttribute(String text) {
        // 데이터베이스에서 조회할 때 호출됩니다.
        return Crypto.decrypt(text);
    }
}

Converter는 따로 스프링빈에 등록하지 않아도 사용가능합니다.
해당 Converter를 적용하고 싶은 엔티티의 프로퍼티에 @Convert 어노테이션을 추가해주시면 적용가능합니다.

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "email")
    private String email;

    @Column(name = "name")
    private String name;

    @Column(name = "phone")
    @Convert(converter = CryptoConverter.class)
    private String phone;

    @Column(name = "role")
    private String role;

}

@Convert 어노테이션을 클래스 레벨에도 설정 가능합니다.
이때는 attributeName 속성을 사용하여 어떤 프로퍼티에 적용할지 명시해주셔야합니다.

@Entity
@Convert(converter = CryptoConverter.class, attributeName = "phone")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "email")
    private String email;

    @Column(name = "name")
    private String name;

    @Column(name = "phone")
    private String phone;

    @Column(name = "role")
    private String role;
}

글로벌 설정

@Converter(autoApply = true)로 글로벌 설정이 가능하고 @Convert로 프로퍼티에 사용하지 않더라도 적용됩니다.
AttributeConverter<X, Y>일 때 모든 X타입에 대해서 Converter가 적용됩니다.

import jakarta.persistence.AttributeConverter;

@Converter(autoApply = true)
public class CryptoConverter implements AttributeConverter<String, String> {
    @Override
    public String convertToDatabaseColumn(String text) {
        // 데이터베이스 저장할 때 호출됩니다.
        return Crypto.encrypt(text);
    }

    @Override
    public String convertToEntityAttribute(String text) {
        // 데이터베이스에서 조회할 때 호출됩니다.
        return Crypto.decrypt(text);
    }
}

주의사항

  1. Converter를 구현하실 때 저장및 조회하는 엔티티마다 호출하기 때문에 복잡한 로직이나 외부시스템에 연동할 경우 속도 이슈가 발생할 수 있습니다.
  2. convertToDatabaseColumn과 convertToEntityAttribute 함수를 구현하실 때 null 값에 대한 처리를 해주셔야 잘못된 값이 적용되거나 에러가 발생하지 않습니다.
  3. autoApply = true는 Enum을 변경하는 케이스나 전체적인 엔티티를 수정하는 경우에만 사용해야합니다.