Cộng đồng Hỏi & Đáp của Inflearn
Member 도메인이 PasswordEncoder를 받는 구조 질문 있습니다.
Đã giải quyết
Viết
·
40
0
예제에서는 도메인에 별도 PasswordEncoder 인터페이스를 정의해 사용하고 있습니다.
만약에, Member 도메인이 Spring Security의 PasswordEncoder 인터페이스를 직접 의존한다면, 구현체가 아니라 인터페이스를 참조하더라도 순수 도메인 설계 관점에서 위반으로 봐야 할까요?
저는 인터페이스 의존이라 괜찮을 수 있다고 생각했지만 AI는
도메인에서는 자체 PasswordEncoder 포트만 사용하고,
Spring Security PasswordEncoder는 인프라 어댑터에서 위임하는 것이 좋다.
고 제안했습니다.
토비님은 어느 쪽이 더 적절하다고 보시는지, 판단 기준도 함께 듣고 싶습니다.
Câu trả lời 2
1
흥미로운 질문을 주셨네요.
저는 실무 일을 할 때 스프링 기술의 특정 인터페이스 하나가 도메인 또는 서비스 계층의 로직을 독립적으로 잘 표현한다면, 그걸 기술 구현체와 상관없이 가져다 쓰기도 합니다. 대부분은 구현 레벨을 쓰는 영역에서 스프링 기술을 쓸게 분명합니다. 그러면서 인터페이스만 보자면, 패키지 이름에 스프링이 들어가는 걸 제외하면 얼마든지 순수하게 도메인과 애플리케이션 서비스의 아이디어를 표현해 내기도 합니다.
말씀하신 PasswordEncoder가 바로 그런 예이죠.
그럼에도 도메인 코드에 스프링이 들어가는 것을 못겼뎌하는, 스프링에 의존적인 코드라고 맹비난하는 순수한(?) 열혈 개발자들이 가끔 보입니다.
그렇다면 의존이란 무엇인가요? 왜 의존이 나쁘다고 하는 것일까요. 코드 차원에서 의존이란, 내가 의존하는 대상이 변경되거나 바뀌면 내 코드도 따라서 바뀔 가능성이 높은 경우를 말합니다. 예를 들어 비밀번호 기술 A 라이브러리를 도메인과 여기저기서 쓰도록 만들었는데, 비밀번호 기술을 따로 만들어서 클래스와 인터페이스, 메소드 시그니처가 바뀌면 내 코드도 따라서 바뀐다면 의존한다고 할 수 있죠. 그럼 스프링에 의존한다는 것은, 스프링을 안쓰고(과연 그럴 수가 있을지 모르겠지만) 다른 기술을 쓴다면, 혹은 스프링 기술이 업데이트 되면서 핵심 인터페이스를 확 바꾼다면(그런 경우는 역사적으로 거의 없습니다만), 도메인 코드도 바뀌고 그래야 하니 의존한다고 할 수 있겠죠.
그렇다면 스프링 시큐리티의 PasswordEncoder 인터페이스도 그렇게 의존성을 부여할 것인가? 라고 한다면 비밀번호를 다루는 코드가 가지는 정말 너무 뻔하고, 대표적인, 지극히 평범한 로직을 담은 것 이상을 그 인터페이스에서 찾을 수가 없습니다.
그래서 이럴 때는 스프링 시큐리티 인터페이스를 도메인이나 서비스에서 사용해도 아무런 문제가 없습니다. 매우 희박하지만 스프링을 쓰면서 시큐리티 기술을 다른 것을 쓴다고 하더라도, 비밀번호를 다루는 로직을 가진 다른 구현 기술을 쓰더라도, 스프링의 인터페이스를 구현해서 그 기술을 사용하도록 어댑터를 하나 추가하면 나머지 코드는 전혀 손을 대지 않아도 됩니다. 그러니까 의존 문제가 발생하지 않는다는 것이죠.
그럼에도 별도의 인터페이스를 정의해서 사용한 것은, 그래도 괜찮기 때문입니다. 아직 스프링 시큐리티 기술을 잘 검토하지 않은 상태에서 도메인 모델에 담긴 비밀번호 처리 로직을 가지고 얼마든지 인터페이스를 정의하고 도메인 개념을 담아 사용할 수 있죠. 그리고 어댑터에서 스프링 시큐리티의 거의 비슷한 이름의 기술을 사용하도록 만들어도 사실 문제 없습니다.
이건 그다지 차이가 없는 결과에 대한, 개발팀의 취향, 경험에 의한 판단의 결과라고 봐도 됩니다. 스프링 시큐리티의 PasswordEncoder에 이미 익숙하고 모두가 잘 이해하고 있고, 하나라도 더 인터페이스를 추가하고 싶지 않다면 스프링 것을 도메인에서 사용해도, 그 코드를 모두가 잘 이해하고 도메인 개념을 잘 표현했다고 생각할 수 있을 겁니다. 반대로 도메인 관점에서 먼저 인터페이스를 설계해서 넣고, 나중에 스프링 시큐리티 어댑터를 만들어서 사용해도 아무 문제는 없겠죠. PasswordEncoder가 도메인 코드로 직접 표현되어 있으면, 아 이런 개념으로 비밀번호를 다루는 것이구나라는 기술 사용에 관한 도메인 로직을 잘 이해할 수도 있을 겁니다. 아직 스프링 시큐리티에 친숙하지 않은 주니어 개발자들이 많다면 이렇게 해도 괜찮아 보이네요.
저는 둘 다 적절하고, 별 차이는 없다고 생각합니다. 제가 혼자 개발한다면 스프링 인터페이스를 가져다 쓸 겁니다. 그러다 혹시 스프링 시큐리티를 안 쓰게 되더라도, 그 인터페이스 클래스 하나만 빼서 프로젝트에 남겨놓고 써도 되겠죠. 아니면 아주 작은 시큐리티 코어 jar 파일 하나를 덤으로 넣어서 쓰던지요.
0
안녕하세요, 인프런 AI 인턴입니다. 이런개발님께서 제기하신 질문에 대해 답변드리겠습니다.
도메인 모델이 외부 라이브러리, 특히 특정 기술에 종속적인 인터페이스나 클래스를 직접 의존하는 것은 일반적으로 권장되지 않습니다. 이는 도메인 모델의 순수성을 유지하고, 기술적인 변화에 대해 유연하게 대응할 수 있는 구조를 만들기 위한 것입니다.
도메인의 순수성을 위한 설계 기준
기술적 종속성 회피: 도메인이 특정 프레임워크나 라이브러리의 API에 종속되면, 나중에 라이브러리를 교체하거나 업그레이드할 때 영향을 받게 됩니다. 이러한 종속성을 피하기 위해 도메인에서는 자신만의 인터페이스(포트)를 정의하고, 외부 기술에 대한 의존성은 인프라스트럭처 계층에서 해결하는 것이 바람직합니다.
변화에 대한 유연성: 애플리케이션 아키텍처가 변화하거나, 새로운 요구사항이 추가될 때, 도메인 모델을 최대한 변경하지 않고도 대응할 수 있어야 합니다. 자체적으로 PasswordEncoder 인터페이스를 정의하면, 이를 구현하는 다양한 전략을 쉽게 전환할 수 있습니다.
헥사고날 아키텍처 원칙 준수: 헥사고날 아키텍처에서는 외부 세계와의 경계를 명확히 하고, 도메인 모델이 비즈니스 로직에 집중할 수 있도록 설계합니다. 따라서, 외부 기술과의 의존성을 도메인 영역에서 분리하는 것이 중요합니다.
이러한 이유로, 도메인에서는 자체적으로 필요한 인터페이스를 정의하고, Spring Security의 PasswordEncoder와 같은 외부 구성 요소는 어댑터 계층에서 도메인의 인터페이스를 구현하는 형태로 위임하는 것이 적절한 접근 방식으로 여겨집니다.
관련된 질문과 답변을 통해 더 깊이 있는 이해를 도와드릴 수 있습니다:
- 인터페이스 위치를 결정하는 기준에 대해
저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다. 현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏 추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.





상세한 답변 감사합니다!