Service 끼리 의존 하는 것에 대하여

2025. 1. 14. 01:46CS
목차
  1. 문제 상황
  2. 올바른 설계 예시
  3. 순환참조랑 쓸데없이 많은 메서드를 가진 클래스를 의존 받는 건 어떻게 할 건데!!!!!!!!!!

📢 각 도메인 별 Repository 에 의존할 경우 도메인 규칙을 정해놓은 서비스를 이용하지 않아 유지보수성이 떨어지게 됩니다.
예를 들어 지갑(Wallet) 엔티티에 돈을 빼는 메서드가 있다고 합시다. Wallet에 돈을 빼면 땅바닥에 둘 수 없으니, 다른 Wallet (ex. Admin Wallet) 에 보관합니다. 위 로직은 Entity 내에 작성할 수 없는 코드입니다.

 

이를 간단한 예시로 설명 드리겠습니다.


문제 상황

초기 상태

WalletService 는 돈을 빼는 비즈니스 로직을 가지고 있습니다. 돈을 뺀 후에는 특정 규칙(여기서는 어드민 지갑에 추가) 이 적용됩니다.


      
public class WalletService {
private final WalletRepository walletRepository;
@Transational
public void 돈빼는메서드(Long walletId) {
Wallet wallet = findById(walletId);
int money = wallet.돈을뺀다(1000원);
// 규칙: 돈을 뺀 후 어드민 지갑에 추가
Wallet adminWallet = walletRepository.findById(1); // 어드민 아이디는 1로 고정
adminWallet.돈을추가한다(money);
}
public Wallet findById(Long walletId) {
return walletRepository.findById(walletId); // 예외 생략
}
}

 

 

기능 추가 및 문제 발생

근데 팀 내에 신입 개발자가 들어오고, 각종 기능이 추가되기 시작했습니다.

사람이 돈을 빼는 행동이 필요하다고 해서 Wallet 을 Human 이 다루게 되었습니다.

 

이것을 HumanService 에서 구현했지만, 신입은 규칙을 몰랐습니다.


      
public class HumanService {
private final HumanRepository humanRepository;
private final WalletRepository walletRepository;
@Transational
public void 사람이돈을빼는메서드(Long humanId) {
Human human = findById(humanId);
Wallet humanWallet = walletRepository(human.getWalletId());
// 규칙 누락: 돈을 뺀 후 어드민 지갑에 추가하지 않음
humanWallet.돈을뺀다(1000원);
}
public Human findById(Long humanId) {
return humanRepository.findById(humanId); // 예외 생략
}
}

 

 

결국 규칙이 누락되면서 전체적으로 도메인 규칙이 맞지 않게 되었습니다.


 

규칙 변경 시

다행히도 신입이 잘 규칙을 적용했습니다. 하지만 HumanService 에 규칙을 적용 시켰습니다.


      
Human human = findById(humanId);
Wallet humanWallet = walletRepository(human.getWalletId());
humanWallet.돈을뺀다(1000원);
Wallet adminWallet = walletRepository.findById(1); // 어드민 아이디는 1로 고정
adminWallet.돈을추가한다(money);

 

규칙이 다시 바뀝니다. 이제 어드민 지갑에 돈을 추가하지 않고 그냥 지워버립니다.


      
public class WalletService {
private final WalletRepository walletRepository;
@Transational
public void 돈빼는메서드(Long walletId) {
Wallet wallet = findById(walletId);
int money = wallet.돈을뺀다(1000원);
// 기존 규칙 삭제: 어드민 지갑에 돈을 추가하지 않음
// Wallet adminWallet = walletRepository.findById(1);
// adminWallet.돈을추가한다(money);
}
}

 

WalletService 는 수정이 되었지만, HumanService는 수정되지 않았습니다.

서비스가 운영된지 한참이 지나 HumanService 에 Wallet 의 규칙이 적용된지는 아무도 모릅니다.

 

결국 문제가 발생하게 됩니다.

 

그래서 Service끼리 의존해야하는 것입니다.

 


올바른 설계 예시


      
public class WalletService {
private final WalletRepository walletRepository;
@Transational
public void 돈빼는메서드(Long walletId) {
Wallet wallet = findById(walletId);
int money = wallet.돈을뺀다(1000원);
// 변경된 규칙 적용: 돈을 버림 (더 이상 어드민 지갑에 추가하지 않음)
}
public Wallet findById(Long walletId) {
return walletRepository.findById(walletId); // 예외 생략
}
}

 


      
public class HumanService {
private final HumanRepository humanRepository;
private final WalletService walletService;
@Transational
public void 사람이돈을빼는메서드(Long humanId) {
Human human = findById(humanId);
// HumanService는 WalletService를 호출하여 도메인 규칙을 따름
walletService.돈빼는메서드(human.getWalletId());
}
public Human findById(Long humanId) {
return humanRepository.findById(humanId); // 예외 생략
}
}

 

레포지토리는 데이터 접근만을 책임지고 비스니스 로직은 서비스 계층에서 관리해야합니다.
그러니까 어? 그럼 레포지토리 단에 규칙을 적용하면 되는 거 아닌가? 라고 생각하지마세요.
저도 오래 고민해봤는데 아닌 거 같아요.

 

서비스 레이어 테스트를 할 때 테스트의 범위가 모호해질 수 있습니다.

 

결국 유지 보수가 떨어집니다.

 

저도 예전에 정말 궁금해서 검색을 해봤는데

소규모 프로젝트에서는 된다는 말이 많습니다.

 

저는 다 귀찮아서 만들어내는 핑계라고 생각합니다.

 

👉 "소규모 프로젝트니까 된다" 는 핑계며, 오히려 작은 프로젝트일수록 더 짜임새있는 설계가 필요합니다.

 

순환참조랑 쓸데없이 많은 메서드를 가진 클래스를 의존 받는 건 어떻게 할 건데!!!!!!!!!!

관리 힘들면 서비스를 더 잘게 나누어 관리하세요

 

ReadService

SaveService 등

 

이것도 안 된다면, 설계가 잘못된게 아닌가를 의심해봐야 합니다.

 

그리고 메서드가 많다고 해서 스프링은 싱글톤 빈을 사용하니 메모리는 별 영향 없습니다.

 

서비스 나누는 건 적절히 트레이드 오프하는게 좋아보여요

저작자표시 (새창열림)

'CS' 카테고리의 다른 글

Hibernate 는 Getter 없이 어떻게 엔티티 값을 저장할까?  (0) 2025.05.19
RAG란 무엇일까?  (0) 2025.02.01
@Transactional 은 어떻게 작동할까요?  (0) 2024.12.24
  1. 문제 상황
  2. 올바른 설계 예시
  3. 순환참조랑 쓸데없이 많은 메서드를 가진 클래스를 의존 받는 건 어떻게 할 건데!!!!!!!!!!
'CS' 카테고리의 다른 글
  • Hibernate 는 Getter 없이 어떻게 엔티티 값을 저장할까?
  • RAG란 무엇일까?
  • @Transactional 은 어떻게 작동할까요?
wonow_
wonow_
꾸준히 성장하는 개발자 WONOW 입니다. 🤗
wonow_
wonow_
wonow_
전체
오늘
어제
  • 분류 전체보기
    • Language
      • JAVA
    • TIL
    • 코딩테스트
      • 프로그래머스
      • 백준
    • 프로젝트
      • JAVA
      • Spring
    • 기타
    • ERROR
      • Spring
    • CS
      • 알고리즘
      • DB
      • Kafka
    • 잡담
    • 활동
      • 척척박사

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 홀짝 구분하기
  • 나는바봉가봉가
  • 공부열심히하자
  • 티스토리 꾸미기
  • 오블완
  • 문자열 붙여서 출력하기
  • 문자열 돌리기
  • 프로그래머스
  • 티스토리챌린지

최근 댓글

최근 글

hELLO · Designed By 정상우.v4.2.1
wonow_
Service 끼리 의존 하는 것에 대하여
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.