1. 도메인 클래스 컨버터란?
도메인 클래스 컨버터(Domain Class Converter) 는 HTTP 요청에서 전달된 엔티티의 ID 값을 기반으로 자동으로 엔티티 객체로 변환해주는 기능이다.
즉, 컨트롤러에서 객체의 ID를 직접 조회하는 코드 없이(예: findById) Spring이 자동으로 엔티티를 찾아서 주입해 준다.
주요 기능
- @PathVariable 또는 @RequestParam을 사용할 때, ID 값을 자동으로 해당 엔티티 객체로 변환
- Spring Data JPA와 함께 사용할 경우 자동으로 findById(id) 실행
2. 도메인 클래스 컨버터 적용 전
Spring Data JPA를 사용하지 않는 일반적인 방식에서는 컨트롤러에서 직접 엔티티를 조회해야 한다
@RestController
@RequiredArgsConstructor
public class MemberController {
private final MemberRepository memberRepository;
@GetMapping("/members/{id}")
public String findMember(@PathVariable("id") Long id) {
Member member = memberRepository.findById(id)
.orElseThrow(() -> new EntityNotFoundException("Member not found"));
return member.getUsername();
}
}
기존 방식의 단점
- memberRepository.findById(id)를 직접 호출해야 하므로 코드가 반복됨
- 매번 예외 처리를 수행해야 함 (orElseThrow())
3. 도메인 클래스 컨버터 적용 후
Spring Data JPA의 도메인 클래스 컨버터를 적용하면 @PathVariable을 사용해 엔티티 ID를 직접 받지 않고, 엔티티 자체를 파라미터로 받을 수 있다.
@RestController
@RequiredArgsConstructor
public class MemberController {
private final MemberRepository memberRepository;
@GetMapping("/members/{id}")
public String findMember(@PathVariable("id") Member member) {
return member.getUsername();
}
}
변경 후 장점
- findById() 호출이 자동으로 수행됨 (Spring이 내부적으로 처리)
- 코드가 간결해짐 (ID 조회 및 예외 처리를 직접 하지 않아도 됨)
4. 도메인 클래스 컨버터의 동작 방식
도메인 클래스 컨버터는 Spring의 Converter 인터페이스를 기반으로 동작한다.
Spring MVC가 @PathVariable 또는 @RequestParam을 처리할 때, 컨버터를 사용하여 ID 값을 엔티티 객체로 변환한다.
동작 과정
- 클라이언트가 GET /members/1 요청
- Spring이 1을 Member 엔티티의 ID로 간주
- findById(1)을 실행하여 Member 객체 조회
- 조회된 Member 객체를 컨트롤러 메서드에 전달
Spring 내부 처리 과정
Spring 내부적으로 아래와 같은 코드가 실행된다.
Member member = memberRepository.findById(id).orElseThrow(() -> new EntityNotFoundException("Member not found"));
- 즉, 컨트롤러에서 findById()를 직접 호출하지 않지만, Spring이 자동으로 변환을 수행한다.
5. 도메인 클래스 컨버터의 한계 및 주의사항
1) 조회용으로만 사용해야 함
도메인 클래스 컨버터는 조회(Read)용으로만 사용해야 한다.
이유는 컨버터가 영속성 컨텍스트에 의해 관리되지 않기 때문이다.
잘못된 사용 예제 (엔티티 수정)
@PutMapping("/members/{id}")
public ResponseEntity<Void> updateMember(@PathVariable("id") Member member) {
member.setUsername("newUsername"); // 변경이 영속성 컨텍스트에 반영되지 않음!
return ResponseEntity.ok().build();
}
위 코드에서는 setUsername()으로 값을 변경해도 변경 사항이 저장되지 않는다. (Dirty Checking)
도메인 클래스 컨버터로 주입된 객체는 영속성 컨텍스트에서 관리되지 않기 때문이다.
올바른 사용 예제
@PutMapping("/members/{id}")
public ResponseEntity<Void> updateMember(@PathVariable("id") Long id, @RequestBody MemberDto memberDto) {
Member member = memberRepository.findById(id).orElseThrow();
member.setUsername(memberDto.getUsername());
memberRepository.save(member);
return ResponseEntity.ok().build();
}
위와 같이 직접 findById()를 호출한 후 save()를 수행해야 변경 사항이 반영된다.
2) 예외 처리가 부족할 수 있음
컨버터는 findById()를 수행하지만, 엔티티가 없을 경우 예외 처리를 자동으로 하지 않는다.
따라서 엔티티가 존재하지 않는 경우, 컨트롤러 메서드가 실행되지 않고 null이 주입될 가능성이 있다.
이를 방지하려면 전역 예외 처리를 추가하는 것이 좋다.
@ExceptionHandler(EntityNotFoundException.class)
public ResponseEntity<String> handleEntityNotFound(EntityNotFoundException e) {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(e.getMessage());
}
6. 정리
- 도메인 클래스 컨버터는 ID를 자동으로 엔티티 객체로 변환하는 기능
- @PathVariable 또는 @RequestParam을 통해 사용 가능
- 조회(Read) 전용으로만 사용 가능하며, 수정 시에는 findById()를 직접 호출해야 함
- 예외 처리가 부족할 수 있으므로 EntityNotFoundException 핸들링 필요
'Backend > JPA' 카테고리의 다른 글
JPA (Spring Data JPA) - SimpleJpaRepository(JPA Repository 기본 구현체) 파악해보기 (0) | 2025.03.13 |
---|---|
JPA (Spring Data JPA) - JPA 페이징과 정렬 처리 방법 (0) | 2025.03.12 |
JPA (Spring Data JPA)- Auditing을 활용한 엔티티 자동 생성 및 수정 정보 기록 (0) | 2025.03.12 |
JPA (Spring Data JPA) - 사용자 정의 리포지토리 개념과 구현 방법 (0) | 2025.03.12 |
JPA (Spring Data JPA) - 쿼리 메소드 기능 (예제 코드) (0) | 2025.03.11 |