DTO에 @Autowired를 붙이면 안 되는 이유

Daniel·2025년 5월 19일
0

Back-End

목록 보기
51/54

Spring 프로젝트를 하다 보면 종종 다음과 같은 생각이 들 수 있다:

"DTO 클래스에 서비스나 레포지토리를 주입해서 뭔가 처리하면 안 될까?"

하지만 결론부터 말하자면 DTO 클래스에 의존성을 주입하는 것은 바람직하지 않으며, 실제로도 잘 작동하지 않는다.
왜 그런 걸까?

DTO란 무엇인가?

DTO(Data Transfer Object)는 말 그대로 데이터를 전달하는 객체이다.

  • 주로 Controller ↔ Service, Service ↔ View 사이에서 데이터 전송에 사용된다.
  • 단순히 필드 + Getter/Setter만 존재하며, 어떤 로직도 포함하지 않는다.
  • 즉, 순수 데이터 컨테이너(Pure Data Holder) 역할만 한다.
public class UserRequestDTO {
    private String username;
    private String email;
	
    // Getter / Setter
}

그런데 여기에 @Autowired를 붙이면?

public class UserRequestDTO {
	
    @Autowired
    private UserService userService; // 이런 식으로 서비스 주입
	
    ...
}

이렇게 하면 실제로 Spring이 빈을 주입해주지 않는다. 이유는 다음과 같다:

❓ 왜 DTO에 빈 주입이 안 되는가?

1. Spring은 DTO를 빈(bean) 으로 관리하지 않는다.

Spring은 @Component, @Service, @Controller 등으로 등록된 클래스만 스프링 컨테이너가 관리하는 빈으로 인식하고, 여기에만 @Autowired로 의존성을 주입할 수 있다.

DTO는 대부분 외부에서 new로 생성되며, 스프링이 관리하는 대상이 아니다.
즉, Spring 입장에서 UserRequestDTO는 관심 대상이 아니다.

2. DTO는 비즈니스 로직이나 의존성을 포함해서는 안 된다.

DTO는 오직 데이터 전달에만 집중해야 한다.

  • Service나 Repository에 의존하게 되면 계층 간 의존성 역전이 발생할 수 있다.
  • DTO는 재사용성과 테스트 용이성을 위해 순수하고 가벼운 구조로 유지하는 것이 좋다.
  • 한마디로, DTO는 “오염되지 않은 구조”여야 한다.

3. 설계 원칙 위반 (SRP, DIP 위배)

DTO에 빈을 주입하는 행위는 단일 책임 원칙(SRP)의존성 역전 원칙(DIP) 을 위배한다.

  • DTO는 데이터 전달이라는 하나의 책임만 가져야 한다.
  • 비즈니스 로직을 처리하거나 의존성을 가지면 다른 계층과 엮이기 시작하고, 설계가 무너진다.

✅ 그럼 의존성이 필요한 경우는?

DTO에서 뭔가 비즈니스 로직이 필요한 상황이라면 그 로직은 DTO가 아니라 Service 또는 Facade 계층에 위치해야 한다.
즉, “DTO는 단순히 전달하고, 판단과 처리는 Service가 한다” 는 원칙을 지키면 된다.

정리하자면

항목DTOService/Component
역할데이터 전달비즈니스 로직
빈 등록❌ 일반적으로 아님✅ 스프링 관리 대상
의존성 주입❌ 불가능 / 지양✅ 사용 가능
상태 보존가능하지만 최소화상태 및 로직 중심
설계 책임단일 책임 (데이터 보관)업무 처리 책임

마무리

DTO는 단순하고 깨끗해야 한다.
간혹 “DTO 안에서 뭔가 처리가 되면 더 편하지 않을까?”라는 유혹이 들 수 있지만, 그렇게 되면 결국 계층 간 책임이 섞이고 유지보수가 어려워진다.

Spring의 구조적 특성을 이해하고, DTO는 순수하게, 로직은 로직답게, 분리해서 작성하자.

“DTO에 @Autowired를 붙이고 싶을 때는, 설계가 어긋난 건 아닌지 다시 돌아보자.”

profile
응애 나 애기 개발자

0개의 댓글