작성
·
106
1
안녕하세요 선생님 제가 이해가 잘 안된걸 수 있어서 확인차 질문 드립니다!
var executor = new RegisterProductCommandExecutor(productRepository::save);
executor.execute(command, uuid, sellerId);
명령 조회를 개선하면 RegisterProductCommandExecutor 라는 실행기를 만들어서 execute 로 실행하는 동작으로 이 구조를 pdf 자료에서 확인하면
궁금한점이
명령모델이 new RegisterProductCommandExecutor(productRepository::save); 로 실행기를 만들면 명령모델이 실행기를 만들면서 productRepository 라는 기반구조에 의존하고 있는거 아닌가요?
구조자체에서 보면 명령실행기는 execute 를 통해서 실행기가 참조하는 기반구조 기능을 실행하는 건 직접 의존하지 않아서 자유도가 높아보인다? 라는 생각이드는데요, 실행기를 만들때 명령모델은ProductRepository 를 알아야할 것같아서 의미가 없어보입니다.
실행기를 만들때 실행기 자체가 bean으로 등록이 되고 실행기 bean 안에서 ProductRepository 를 스프링에서 주입받고, 실행기를 만드는 명령 모델은 실행기만 주입받고 파라미터로 repository 를 넘겨도 되지 않으니 이게 정말 의존하지않는 구조같은데요.
(제가 말한 (2) 방식이라면) 이이렇게 되면 그냥 돌고돌아서 결국엔 처음 방식인 ProductRepository 인터페이스를 (추상화 되어있으니) 그냥 바로 빈을 주입받는 것이랑 별차이 없다고 생각합니다
조회도 역시 이런생각이 들었습니다. 명령과 조회를 분리한다는 개념은 이해가 갈거같은데 각 명령과 조회 모델이 기반구조에 의존? 한다는 개념을 잘 이해가 가지 않습니다!
답변 2
1
규영님 안녕하세요. 강의 수강해주셔서 고맙습니다. :)
실습 코드를 정확히 이해하기 위해서 열심히 노력하고 계신 것 같습니다. 👍
도움이 되도록 이해하기 어려우신 내용에 대해 설명을 드려 보겠습니다.
Product
엔터티는 JPA를 사용하는데요, JPA를 사용할 때 JpaRepository<T, ID>
를 제공하는 Spring Data JPA를 반드시 사용해야 하는 것은 아닙니다. JPA를 지원하는 다른 도구들도 많습니다.
그래서 RegisterProductCommandExecutor
를 만들 때 EntityManager
등 다른 도구를 사용하고 싶을 수 있습니다.
EntityManager em = ...
var executor = new RegisterProductCommandExecutor(p -> {
em.getTransaction().begin();
em.persist(p);
em.getTransaction().commit();
});
이 때 어떤 도구가 사용되는지는 RegisterProductCommandExecutor
는 알지 못하고 알 필요도 없습니다. 그래서 RegisterProductCommandExecutor
는 JpaRepository<T, ID>
또는 Spring Data JPA라는 특정 기반구조 도구로부터 독립적인 설계가 됩니다. 재사용성이 조금 더 올라가는 거죠. 만약 RegisterProductCommandExecutor
클래스가 ProductRepository
를 주입받으면 Spring Data JPA가 있어야 동작하는 특정 기반구조에 의존적인 코드가 되죠.
명령 모델과 API가 별도의 모듈로 분리된다면 의미가 더 명확해 집니다.
+--------------------------------+
| Command Model | +---------+
| RegisterProductCommandExecutor |------->| JPA |
+--------------------------------+ +---------+
^ ^
| |
| |
+--------------------------+ +----------------------+
| API | | Spring Data JPA |
| SellerProductsController |---->| JpaRepository<T, ID> |
+--------------------------+ +----------------------+
다만 이런 독립적인 설계가 유용한지 아닌지는 각 프로젝트마다 상황이 다릅니다. 따라서 규영님이 말씀하신 2번 설계를 사용하는 것이 더 좋을 수도 있습니다.
엔지니어는 한 가지 설계 방식만 아는 것 보다는 다양한 설계 방식을 이해하고 실무에서 주어진 환경에 따라 가장 적절한 방식을 사용하는 것이 더 바람직 하다는 관점에서, 의존성이 극히 낮은 설계 방식도 경험해 본다고 이해하시면 좋을 것 같습니다. :)
혹시 이해하시기에 설명이 부족하다면 말씀해주세요!
0
안녕하세요, 인프런 AI 인턴입니다. 김규영님.
CQRS(Command Query Responsibility Segregation) 패턴에 대해 궁금하신 점을 잘 정리해주셨습니다. 이 패턴의 핵심은 명령(command)과 조회(query)의 책임을 분리하여 시스템이 더 유연하고 확장 가능하게 만드는 것입니다. 이제 질문하신 내용에 대해 하나씩 답변드리겠습니다.
명령 모델이 실행기를 만들면서 Repository에 의존하는 문제:
RegisterProductCommandExecutor
를 생성하면서 productRepository
에 직접적으로 의존하지 않도록 설계하는 것이 중요합니다. 이를 위해 Command Executor(명령 실행기)를 별도의 Bean으로 등록하고, 실행기는 필요한 Repository
를 DI(Dependency Injection)를 통해 주입받습니다. 이 방식은 명령 모델의 독립성을 유지하면서, 실행기는 필요한 작업을 수행할 수 있게 합니다.Command Executor의 의존성 주입:
RegisterProductCommandExecutor
가 Spring Bean으로 등록되며, ProductRepository
를 스프링 컨텍스트에서 주입받도록 하면, 명령 모델은 실행기만 알고 있으면 됩니다. 이로 인해 명령 모델은 Repository의 존재를 알 필요가 없어집니다.명령 및 조회 모델의 기반구조 의존성 이해:
실행기 자체의 구조라든지, 명령과 조회의 명확한 분리와 의존성 주입 예시에 대한 이해를 돕기 위해 아래 링크에서 관련 논의를 확인해 보시면 좋겠습니다:
이 논의에서는 프로젝트 구조 개선과 관련된 다양한 최적화 방법과 함께, 명령 및 조회의 분리에 대한 이해를 제고할 수 있는 여러 모범 사례를 다룹니다.
저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.
감사합니다!