@Autowired null 문제, 왜 발생하는가
@Autowired null 문제는 대부분 Spring 컨테이너가 객체를 관리하지 않을 때 발생합니다. 즉, 의존성 주입이 되려면 해당 객체가 Spring Bean이어야 하는데, 이 조건이 깨지면 필드에 null이 들어옵니다.
여기서 중요한 포인트는 "객체 생성 주체"입니다. Spring이 생성한 객체인지, 직접 new로 생성한 객체인지에 따라 결과가 완전히 달라집니다.
가장 흔한 원인: new 키워드로 객체 생성
실무에서 가장 많이 보는 케이스입니다. Spring Bean을 사용해야 하는데 직접 new로 생성해버리는 경우입니다.
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
}
위 코드 자체는 문제가 없습니다. 그런데 아래처럼 사용하면 문제가 생깁니다.
UserService userService = new UserService();
userService.doSomething();
이 경우 userRepository는 null입니다. Spring이 만든 객체가 아니기 때문입니다.
이 부분은 처음에 특히 많이 헷갈립니다. 클래스에 @Service가 붙어 있다고 해서 모든 인스턴스가 자동으로 관리되는 것은 아닙니다.
Bean 등록이 안 된 경우
두 번째로 자주 보는 케이스는 Bean 자체가 등록되지 않은 경우입니다.
@Component 계열 어노테이션 누락
Spring이 Bean으로 인식하려면 다음 중 하나가 필요합니다.
@Component
@Service
@Repository
@Controller
이 어노테이션이 빠져 있으면 Bean으로 등록되지 않고, 결국 @Autowired 대상이 존재하지 않게 됩니다.
@ComponentScan 범위 문제
패키지 위치 때문에 스캔이 안 되는 경우도 있습니다. Spring Boot는 기본적으로 메인 클래스 기준 하위 패키지만 스캔합니다.
패키지 구조를 잘못 잡으면 Bean이 존재하지 않는 것처럼 보일 수 있습니다.
static 필드에 @Autowired 사용
static 필드에 @Autowired를 붙이면 null이 들어옵니다.
@Autowired
private static UserRepository userRepository;
Spring은 인스턴스 기반으로 의존성을 주입합니다. static은 클래스 레벨이기 때문에 주입 대상이 아닙니다.
이 부분은 문법적으로는 문제 없어 보이기 때문에 디버깅이 길어지는 경우가 있습니다.
생성자 주입을 쓰지 않은 경우의 함정
필드 주입(@Autowired 필드 방식)을 사용할 때는 null 문제가 더 늦게 드러나는 경향이 있습니다.
반면 생성자 주입을 사용하면 Bean 생성 시점에 문제가 바로 발생합니다.
@Service
public class UserService {
private final UserRepository userRepository;
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
}
이 방식은 의존성이 없으면 애초에 애플리케이션이 시작되지 않습니다.
실무에서는 이 방식이 문제를 빨리 드러내기 때문에 유지보수에 유리합니다.
테스트 코드에서 자주 발생하는 케이스
테스트 코드에서 @Autowired null 문제가 발생하는 경우도 많습니다.
public class UserServiceTest {
@Autowired
private UserService userService;
}
이 경우 @SpringBootTest 또는 관련 테스트 설정이 없으면 Spring 컨테이너가 뜨지 않습니다.
즉, 테스트 환경 자체가 DI를 지원하지 않는 상태입니다.
실무 기준으로 보는 해결 방법
@Autowired null 문제는 원인을 하나씩 확인하면 금방 해결됩니다. 다만 처음부터 기준을 잡아두면 이런 문제를 예방할 수 있습니다.
1. 객체는 절대 new로 생성하지 않는다
Spring Bean은 항상 컨테이너에서 가져옵니다. 직접 생성하는 순간 DI는 깨진다고 보면 됩니다.
2. 생성자 주입을 기본으로 사용한다
필드 주입은 편하지만 문제를 늦게 발견합니다. 생성자 주입은 초기 단계에서 오류를 드러내기 때문에 더 안전합니다.
3. Bean 스캔 범위를 항상 확인한다
패키지 구조는 생각보다 자주 원인이 됩니다. 특히 모듈 구조가 나뉘어 있을 때 더 주의해야 합니다.
정리
@Autowired null 문제는 복잡한 문제가 아니라, Spring이 객체를 관리하지 않는 상황에서 발생합니다.
핵심은 한 가지입니다. "이 객체를 누가 만들었는가"를 확인하면 됩니다.
이 기준만 잡혀 있으면 대부분의 케이스는 빠르게 원인을 찾을 수 있습니다.
'개발 > JAVA' 카테고리의 다른 글
| [JAVA] Spring Boot 실행은 되는데 API 호출이 안 되는 이유 (0) | 2026.05.12 |
|---|---|
| [JAVA] ApplicationContext 로딩 실패 문제 해결 경험 (0) | 2026.05.10 |
| [JAVA] Whitelabel Error Page 원인 추적 방법 (0) | 2026.05.09 |
| [JAVA] Circular dependency 문제 왜 생기고 어떻게 풀었는지 (0) | 2026.05.08 |
| [JAVA] BeanCreationException 원인 찾는 방법 (실무 기준) (0) | 2026.05.07 |
