인프런 커뮤니티 질문&답변

jungjin1.kim님의 프로필 이미지

작성한 질문수

실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발

엔티티에 의존성 주입이 필요한 경우?

해결된 질문

20.02.21 14:49 작성

·

1.5K

0

안녕하세요.

영한님 교육을 듣고 실무에 적용해보려다가 막히는 부분이 있어서 문의드립니다.

JPA없이 사용할 때는 Spring 에서 의존성 관리를 잘 해주고 있어서

@Autowired 애노테이션을 쓰든 명시적으로 정의를 하든

인터페이스로 정의되어 있는 필드에 구상체를 주입받을 수가 있는데

Entity 클래스가 가지고 있는 인터페이스에 대한 구상체 주입은 어떤방식으로 하는지 궁금합니다.

또 기존에 개발되어 있는 도메인 클래스가 Map 타입 필드를 가지고 있는데 Key가 Class<T> 타입인 경우는 어떤 식으로 해야할지 감이 안오는데 어떻게 해야 할까요? ㅠㅠ

답변 3

2

김영한님의 프로필 이미지
김영한
지식공유자

2020. 02. 23. 00:29

네 좋은 질문입니다.

우선 엔티티 클래스는 스프링 컨테이너가 관리하는 빈이 아니기 때문에 기본적인 방법으로는 스프링의 의존성 주입을 받을 수 없습니다. 단 스프링을 사용할 때 엔티티에 의존성 주입을 받게 할 수 있는 방법이 있는데, 스프링 load time weaving 으로 검색해보시면 방법이 있습니다.

그런데 사실 이런 방식을 저도 과거에 시도해본적이 있는데, 결국 이게 유지보수성을 많이 떨어뜨리고, 테스트를 어렵게한 다는 것을 경험으로 알게 되었습니다.

그래서 저는 엔티티가 필드를 통에 외부 의존성을 강하게 가지는 것은 권장하지 않습니다. 

대신에 다음과 같이 파라미터로 넘겨서 외부 의존성을 좀 약하게 가지는 방법이 더 나은 방법이라 생각합니다. 

class EntityX {

  public void changeGo(Calculator calculator) { calcuclator.call() }

}

이러한 방법이 목 객체를 주입하기도 더 쉽게 테스트나 운영시에도 더 유연한 결과를 가져옵니다.

그런데 저는 사실 실무에서 이 방법도 거의 사용하지 않습니다. 엔티티의 비즈니스 로직은 해당 엔티티의 데이터만 순수하게 다루는 경우에 한해서 사용하는 편입니다.(상황에 따라서 항상 그런 것은 아닙니다.)

이런 로직 호출은 서비스계층에서 대부분 처리를 하고 그 결과 데이터만 엔티티에 넘기는 방식을 선호합니다.

추가로 질문해주신 부분은 도메인 클래스가 Map 타입 필드를 가지고 있는데 Key가 Class<T> 타입인 경우는 어떤 식으로 해야할지에 대해서는 자세한 코드를 적어주시면 추가로 답변을 드리겠습니다.

감사합니다

0

김영한님의 프로필 이미지
김영한
지식공유자

2020. 02. 23. 16:19

안녕하세요. jungjin1.kim님

비즈니스 로직 객체를 엔티티에서 호출 하는 것 자체가 자칫하면 운영하기 어려운 코드를 생산합니다.

사실 질문해주신 BaseJob과 엔티티가 어떻게 섞여 들어가는지 설명해주신 내용만으로는 이해가 잘 안됩니다.

비즈니스 로직 객체를 엔티티로 바꾸려고 하는 이유도 잘 이해가 안되구요. (너무 어렵게 풀어가는 느낌을 받습니다.)

서비스, 엔티티와 함께 해당 코드가 어떻게 사용되는지 설명해주시면 더 도움을 드릴 수 있을 것 같아요^^

0

jungjin1.kim님의 프로필 이미지
jungjin1.kim
질문자

2020. 02. 23. 08:14

답변주셔서 감사합니다.

저도 현재는 비즈니스 로직을 가지고 있는 클래스와 비즈니스를 저장할 수 있는 형태로 재정의된 엔티티 타입 클래스으로 나눠서 엔티티에서 비즈니스 객체를 생성하고, 저장하는 기능을 인자로 받아 처리하고 있습니다. 그런데 이 방법도 여간 까다로운게 아니고 비즈니스 객체마다 엔티티 클래스를 만든다는 것 자체가 상당한 노력과 시간이 들어서 이건 아니다 싶은 생각이 많이 듭니다.

그래서 있던 비즈니스 로직 객체를 어떻게든 엔티티로 바꾸려고 하니 두번째 질문을 드린건데 아래와 같은 케이스 입니다.

public abstract class BaseJob implements Job {
    private final String jobId;
    private final JobMeta jobMeta;
}
public final class JobMeta {
    private final Map<Class<? extends Property>, Object> property;
}

BaseJob 클래스에 JobMeta 라는 필드를 가지고 있는데 이 타입은 Map<Class<? extends Property>, Object> 타입을 키로하는 맵을 가지고 있을 때 입니다.

지금에서 드는 생각은 JPA를 사용할 생각이 있으면 처음부터 엔티티를 고려하여 설계가 되야지 안그러면 힘든 사태가 ㅠㅠ

JPA가 객체를 더 객체답게 사용하기 위해서 나온 기술이라 생각했는데 해보니 한계가 있는듯 합니다.