스프링 3.1의 DI

정훈희·2022년 11월 16일
0

Spring

목록 보기
22/24
post-thumbnail

참조

  • 토비의 스프링 vol.1 7장

자바 언어의 변화와 스프링

  1. 어노테이션의 메타정보 활용
    • 자바 코드의 메타정보를 이용한 프로그래밍 방식이 확산되기 시작했다.
    • 어노테이션은 자바코드가 실행되는 데 직접 참여하지 못한다.
    • 어노테이션의 활용이 늘어난 이유는?
      • 애플리케이션의 핵심 로직을 담은 자바코드 + IoC 프레임워크 + 프레임워크가 참조하는 메타정보 이 세가지로 구성하는 방식에 잘 어울린다.
      • 어노테이션의 장점
        • 정의하기에 따라서 타입, 필드, 메서드, 파라미터 등 여러 레벨에 적용할 수 있다. → 어느 레벨에서 적용되어 있는지에 대한 정보를 획득할 수 있다.
        • 단순히 어노테이션 하나 추가하는 것만으로 어노테이션이 부여된 클래스의 패키지, 클래스 이름, 접근제한자 등 메타정보를 알 수 있다. → xml은 이걸 다 명시적으로 표현해야하고, 텍스트 정보라서 오타가 발생하기도 쉽다. → 리팩토링할때 안전하지 못하다.
      • 어노테이션의 단점
        • 변경할 때마다 매번 클래스를 새로 컴파일 해줘야한다
      • but 흐름은 어노테이션으로 가고있다. 스프링 3.1부터 xml을 완전히 배제한 설정이 가능하다.
  2. 정책과 관례를 이용한 프로그래밍
    • 메타정보를 활용하는 프로그래밍 방식 → 명시적으로 동작 내용을 기술하는 대신 코드 없이도 미리 약속한 규칙/관례를 따라서 프로그램이 동작하도록 만드는 프로그래밍 스타일을 적극 포용함
      • 규칙, 관례의 예시: @Transactional을 클래스에도 붙히고, 클래스 안의 메소드에도 붙힌 다면 트랜잭션 속성이 최종적으로 어떻게 적용될까?
      • 단점: 정책과 관례를 잘 모르면 의도대로 동작하지 않는 코드를 만들 수 있다.
      • but 간결하고 빠른 개발이 가능하기 때문에 이런 스타일이 늘어남.

자바 코드를 이용한 빈 설정

스프링 3.1부터 xml을 사용하지 않고 설정이 가능

EX) 자바 코드를 이용한 QueryDsl 설정파일

@Configuration
public class QueryDslConfig {
  @PersistenceContext private EntityManager em;

  @Bean
  public JPAQueryFactory jpaQueryFactory() {
    return new JPAQueryFactory(em);
  }
}

@Configuration이 붙은 설정 클래스를 사용하는 컨테이너가 사용되면, 컨테이너가 직접 빈 후처리기를 등록해준다

기존의 태그는 위와 같이 @Bean 어노테이션을 사용할 수 있다.

빈 스캐닝과 자동 와이어링

  • 자동 와이어링 → @Autowired: 컨테이너가 이름/타입 기준으로 주입될 빈을 찾아준다 → 프로퍼티 설정을 직접 해주는 코드를 줄일 수 있다.
    • 장점: DI 관련 코드를 대폭 줄일 수 있다.
    • 단점: 다른 빈과 의존관계가 어떻게 맺어져있는지 파악하기 어렵다.
  • 빈 스캐닝 → @Component: 클래스에 붙이면 빈 스캐너를 통해 자동으로 빈으로 등록될 대상이 된다.
    • @Component가 붙은 클래스가 발견되면 새로운 빈을 자동으로 추가한다.
    • @Component 로 추가되는 빈의 id는 별도 지정이 없으면 클래스 이름의 첫 글자를 소문자로 바꿔서 사용.
    • @Service, @Repository 등은 Component 어노테이션이 포함되어 있다.

컨텍스트 분리와 @Import

  • 컨텍스트 분리
    • 테스트를 위해 만든 빈은 테스트에서만 사용되어야 하고, 실제 애플리케이션에선 포함하지 않아야함 → 성격이 다른 DI정보를 분리해보자
      • @Configuration이 붙은 빈 설정 파일을 테스트에만 쓰이는 설정과 실서비스 동작 시 쓰이는 설정 두가지로 분리
      • 실 서비스에서는 실서비스 동작 시 쓰이는 설정만 참조. 테스트에서는 두 가지 모두 사용
  • @Import
    • SQL 서비스 처럼 다른 애플리케이션에서도 사용할 수 있고, 독립적으로 개발/변경될 가능성이 높은 서비스는 독립적인 모듈처럼 취급하는게 좋다.
      • 아래와 같이 SQL관련 설정 클래스를 분리하고, @Import를 통해 적용시키기
        @Import(SqlServiceContext.class)
        public class AppContext {
        	...
        }

프로파일

  • 테스트와 운영환경에서 각기 다른 빈 정의가 필요한 경우에는 양쪽 모두 필요하면서 내용만 다른 것들은 설정정보를 변경하고 조합하는 것으로는 한계가 있다. → 실행환경에 따라 빈 구성이 달라지는 내용을 프로파일로 정의해서 만들어두고, 실행시점에 지정해서 사용
  • 아래와 같이 설정 클래스 단위로 지정하고 context를 쓰는곳에서 active profile를 지정
    @Configuration
    @Profile("test")
    public class TextAppContext {
    	@ActiveProfiles("test")
    	@ContextConfiguration(classes=AppContext.class)
    	public class UserServiceTest { ... }
    }

프로퍼티 소스

  • db 연결정보와 같은 부분은 환경에 따라 다르게 설정 && 필요에 따라 쉽게 변경할 수 있어야함 → 프로퍼티 파일에 저장해놓고 쓰자.
  • 컨테이너가 프로퍼티 값을 가져오는 대상을 property source라고 한다.
    @PropertySource("/database.properties")
    public class AppContext { ... }
    이렇게 등록해두면 컨테이너가 관리하는 Environment 타입의 환경 오브젝트에 프로퍼티가 저장된다.

@Enable

모듈화된 빈 설정을 가져올 때, @Enable 로 시작하는 메타 어노테이션을 사용하자.

→ @Repository, @Service 처럼 빈의 종류나 계층을 나타내고 특정 어노테이션이 달린 빈만 AOP로 부가기능을 넣을 수도 있다.

profile
DB를 사랑하는 백엔드 개발자입니다. 열심히 공부하고 열심히 기록합니다.

0개의 댓글