300===Dev Framework/Spring

@Autowired 어노테이션 완벽 가이드 🚀

블로글러 2024. 12. 6. 00:22

@Autowired란? 🤔

스프링의 강력한 의존성 주입(Dependency Injection) 기능을 제공하는 어노테이션입니다.
쉽게 설명하면, 레고 블록처럼 필요한 부품(객체)을 자동으로 조립해주는 마법 같은 기능이에요!

@Autowired 사용법 📝

1. 필드 주입

@Service
public class UserService {
    @Autowired
    private UserRepository userRepository;
}

2. 생성자 주입 (권장 방식)

@Service
public class UserService {
    private final UserRepository userRepository;

    @Autowired  // Spring 4.3부터는 생략 가능!
    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }
}

3. 수정자(Setter) 주입

@Service
public class UserService {
    private UserRepository userRepository;

    @Autowired
    public void setUserRepository(UserRepository userRepository) {
        this.userRepository = userRepository;
    }
}

동작 원리 🎯

  1. 스프링 컨테이너 시작

    • 애플리케이션이 구동되면 스프링이 빈(Bean) 객체들을 생성
  2. 의존성 분석

    • @Autowired가 붙은 필드/생성자/메서드를 찾음
    • 주입할 적절한 빈을 탐색
  3. 자동 주입

    • 찾은 빈을 해당 위치에 자동으로 주입
    • 마치 퍼즐 조각이 알맞은 자리를 찾아 들어가는 것처럼!

주입 우선순위 🎯

타입이 같은 빈이 여러 개일 때는?

  1. @Primary

    @Primary
    @Component
    public class MainUserRepository implements UserRepository {
        // 이 구현체가 우선적으로 주입됨
    }
  2. @Qualifier

    @Autowired
    @Qualifier("specificRepo")
    private UserRepository userRepository;

주의사항 ⚠️

  1. 순환 참조 문제

    • A가 B를 참조하고, B가 A를 참조하면?
    • 생성자 주입을 사용하면 컴파일 시점에 발견 가능!
  2. NPE(NullPointerException) 위험

    • required = false 설정 시 주의
      @Autowired(required = false)
      private UserRepository userRepository;
  3. 단위 테스트의 어려움

    • 필드 주입 사용 시 테스트가 어려움
    • 생성자 주입을 사용하면 테스트가 용이

베스트 프랙티스 💡

  1. 생성자 주입을 사용하자

    @Service
    @RequiredArgsConstructor  // Lombok 사용
    public class UserService {
        private final UserRepository userRepository;
    }
  2. final 키워드 활용

    • 불변성 보장
    • 실수로 값이 변경되는 것을 방지
  3. 단일 책임 원칙 준수

    • 너무 많은 의존성이 있다면 클래스 분리 고려

테스트 코드 작성 예시 📝

@ExtendWith(MockitoExtension.class)
class UserServiceTest {
    @Mock
    private UserRepository userRepository;

    @InjectMocks
    private UserService userService;

    @Test
    void getUserTest() {
        // given
        when(userRepository.findById(anyLong()))
            .thenReturn(Optional.of(new User(1L, "테스트")));

        // when
        User user = userService.getUser(1L);

        // then
        assertThat(user.getName()).isEqualTo("테스트");
    }
}

정리 📋

@Autowired는 스프링의 핵심 기능 중 하나로, 개발자가 직접 의존성을 관리하는 부담을 줄여줍니다.
생성자 주입 방식을 권장하며, 이를 통해 더 안전하고 테스트하기 쉬운 코드를 작성할 수 있습니다.


참고문헌:

  • Spring Framework Documentation
  • Effective Java 3rd Edition
  • Clean Code by Robert C. Martin

#Spring #Autowired #DependencyInjection #SpringBoot #Java

728x90