[Spring] @Transient어노테이션

@Transient Annotation의 사용법과 주의사항을 알아보자.
Hi's avatar
Apr 21, 2024
[Spring] @Transient어노테이션
 

✅ Transient 어노테이션

notion image
📋
Spring에서 @Transient 주석은 엔터티 클래스의 필드를 임시로 표시하는 데 사용된다. 즉, 해당 필드가 데이터베이스에 지속되어서는 안되는 경우 사용한다. 이 주석은 Java 코드에 포함하고 싶지만 데이터베이스에 저장하고 싶지 않은 필드가 엔터티 클래스에 있는 경우 특히 유용하다.
 

✅ 정의와 적용 예시

그렇다면, @Transient 작동 방식과 이를 언제 사용할 수 있는지 알아보자
  • 정의: 필드를 @Transient로 표시하면 Spring이 엔터티 저장, 업데이트 또는 쿼리와 같은 데이터베이스 작업을 수행할 때 해당 필드를 무시한다. 이는 Hibernate와 같은 지속성 공급자에게 SQL 작업에 이 필드를 포함하지 말라고 지시하는 것이다!
  • 적용 예시:
    • 임시로 계산된 필드: 때로는 다른 지속형 필드를 기반으로 계산된 필드가 있다. 이 필드는 임시적으로 사용하는 필드이므로 데이터베이스에 저장할 필요가 없는 경우가 있다.
    • 비영구적 정보: 애플리케이션 내 내부 처리에 필요하지만 데이터베이스 저장과 관련이 없는 필드는 임시로 표시될 수 있다.
    • 보안 관련 정보: 비밀번호나 임시 토큰과 같이 유지하고 싶지 않은 민감한 정보가 포함된 필드는 임시로 표시될 수 있다.
 
 

✅ 사용 예시

id, username, password라는 세 가지 필드가 있는 User 엔터티 클래스가 있다고 가정해보자. 또한 사용자 인증 중에 생성되지만 데이터베이스에 유지되어서는 안 되는 temporaryToken이라는 필드를 포함하고 있다.
 
@Transient 주석을 사용하여 User 엔터티 클래스를 정의하는 방법은 다음과 같습니다.
import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Transient; import lombok.Data; import lombok.NoArgsConstructor; import lombok.AllArgsConstructor; @Entity @Data @AllArgsConstructor @NoArgsConstructor public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String username; private String password; @Transient private String temporaryToken; }
 
temporaryToken 필드를 @Transient로 표시했다. 이는 이 필드가 데이터베이스에 유지되어서는 안 된다는 것을 Spring에 알려준다.
 
이제 Spring 저장소 또는 EntityManager를 사용하여 User 엔터티를 저장하거나 업데이트하면 temporaryToken 필드가 무시되고 해당 값이 데이터베이스에 저장되지 않는다.
 
다음은 Spring Boot 애플리케이션에서 이 엔터티를 사용하는 방법에 대한 예입니다.
javaCopy code import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class DemoApplication implements CommandLineRunner { @Autowired private UserRepository userRepository; // Assuming UserRepository is your JPA repository interface public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } @Override public void run(String... args) throws Exception { // Creating a new user User user = new User("john.doe", "password123"); user.setTemporaryToken("temporaryToken123"); // Saving the user userRepository.save(user); // Retrieving the user from the database User retrievedUser = userRepository.findById(user.getId()).orElse(null); if (retrievedUser != null) { // Print user details (temporaryToken won't be persisted) System.out.println("Retrieved User:"); System.out.println("ID: " + retrievedUser.getId()); System.out.println("Username: " + retrievedUser.getUsername()); System.out.println("Password: " + retrievedUser.getPassword()); System.out.println("Temporary Token: " + retrievedUser.getTemporaryToken()); // null을 리턴할 것이다!! } } }
이 예에서는 User 객체를 저장하기 전에 temporaryToken 값을 설정하더라도 @Transient 주석으로 인해 데이터베이스에는 저장되지 않는다.
 
데이터베이스에서 사용자를 꺼내, 사용자 정보를 출력하면 temporaryToken 필드가 null을 출력할 것이다. null은 데이터베이스에 저장되지 않았음을 나타낸다.
 

✅ 주의사항

  • @Transient 어노테이션을 사용하면 특정 필드를 지속성에서 제외하는 데 유용하게 사용할 수 있지만, 과도하게 사용하면 시스템 디자인에 문제가 발생할 수 있다.
  • 스키마 생성 중에는 임시 필드가 고려되지 않는다. 자동 스키마 생성을 사용하는 경우 임시 필드가 데이터베이스 스키마에 반영되지 않는다는 점을 기억해야 한다.
 

✅ 대체 방안

  • 특정 속성을 DB 지속성에서 제외하려면 해당 속성이 없는 DTO(Data Transfer Object)를 새로 만드는 것이 좋다.
  • 필드가 유지되는 방식을 맞춤설정해야 하는 경우 insertableupdatable과 같은 속성이 포함된 JPA의 @Column 주석을 사용하는 것이 좋다.
 
 
Share article

soultree