녕의 학습 기록
비즈니스 로직을 어디에 위치시킬 것인가? 2024.8.10 수정 본문
왓슈 프로젝트를 진행하며 비즈니스 로직을 어디에 작성해야하는 지에 관해 고민을 많이 했었다.
"가입 신청 취소" api에서는 일련의 과정을 거친 뒤 가입 신청 엔티티의 status를 canceled로 바꿔주어야 한다.
이때 ClubJoinRequest 엔티티의 status 필드를 어디에서 바꿔줘야 할까?
1. 외부(ex_service 레이어)에서 status 필드를 직접 변경한다.
2. 엔티티 내에서 status 필드를 직접 변경한다.
관련해서 다른 블로그도 찾아본 뒤 엔티티 내에 비즈니스 로직을 위치시키자는 결론을 지었으나 왜 그래야하는 지에 대해 스스로에게 물었을 때 명확하게 답변을 할 수 없었다.
그러다 최근 조영호님의 객체지향의 사실과 오해를 읽고나서 깨달은 바가 있어 생각을 정리해보고자 한다.
객체지향의 사실과 오해를 읽고나면 다음과 같은 견해를 가질 수 있다.
객체지향이란 곧 객체 간의 협력을 의미한다. 객체는 그 협력 내에서 각자의 책임을 가진다. 객체는 메세지를 전달 받아 그에 맞는 행동을 하고 그 결과 객체의 상태가 변한다. 객체의 상태를 결정하는 것은 객체 자신의 행동이다. 한 객체가 다른 객체의 상태를 마음대로 변경할 수는 없다. 다른 객체에게 메세지를 보내고 그 객체가 책임에 따라 행동하기를 기대할 뿐이지, 실제로 그 상태에 대한 정보는 알지 못한다. 객체의 상태는 객체 자신의 행동과 기존의 상태에 의존할 뿐이다. 따라서 객체 지향적 프로그래밍에서 객체는 행동을 함으로써 자신의 상태를 변화시킨다.
ClubJoinRequest도 마찬가지이다. ClubJoinRequest의 상태를 변경하는 것은 ClubJoinRequest 본인이어야 한다. 외부의 서비스 레이어에서는 ClubJoinRequest 객체에 메세지를 보내 요청하고 ClubJoinRequest 객체가 책임을 완수해 status가 변경될 것이라고 기대하는 것이 전부이다.
이는 곧 비즈니스 로직을 객체(엔티티) 내에 위치시킨다는 것이다.
그러면 이렇게 했을 때 어떤 장점이 있을까?
위에서 살펴본 내용은 캡슐화 개념과 관련이 있다. 외부에서는 ClubJoinRequest에게 status를 cancel로 바꿀 것을 요청할 뿐 그 과정이 어떻게 되는 지는 알지 못한다. 이처럼 설계할 경우 어떤 객체의 로직이 바뀌어도 해당 객체 내 로직만 변경하면 된다. 객체 간의 협력관계는 더 단단하게, 변화에는 더 유연하게 대응할 수 있다는 장점이 있다.
BEFORE
외부의 서비스 레이어에서 ClubJoinRequest의 현재 상태에 따라 예외 처리를 하고 그 값을 변경한다.
AFTER
외부의 서비스 레이어에서는 ClubJoinRequest에게 취소될 것을 요청한다.
ClubJoinRequest는 자신의 현재 상태에 따른 행동을 취해 상태를 변경한다.
경우에 따라 다른 방법이 더 적절할 수 있겠지만, 현재 상황에서는 이처럼 비즈니스 로직을 엔티티 내에 위치시키는 것이 객체지향적으로 잘 설계하기에 한걸음 더 다가가는 법이라고 생각한다.
===================================================================
2024.08.10
이 글을 작성할 때까지는 도메인과 엔티티를 분리하지 않았다. 즉 도메인 객체에 jpa관련 애노테이션을 덕지덕지 발랐다.
절대 이게 틀린 것이 아니지만 클린 아키텍처, 헥사고날 아키텍처를 공부한 지금은 도메인 객체와 영속성 객체인 엔티티를 분리하여 생각하는 중이다.
이 글에서는 비즈니스 로직을 엔티티 내에 위치시키는 것이 아닌, 도메인 내에 위치시키는 것이라고 해석하면 된다.
'Dev' 카테고리의 다른 글
Java Reflection을 사용해 private 필드 값 설정하기 (0) | 2025.01.10 |
---|---|
단위 테스트 고민과 해결 : DI와 DIP 적극 활용하기 (0) | 2024.12.27 |
Java11의 CharSequence에서 isEmpty() 사용 시 컴파일 에러 발생 (0) | 2024.09.02 |
JPA metamodel must not be empty 에러 해결 (0) | 2024.07.16 |