spring DI

klmjiho·2025년 7월 16일

궁금한것들

목록 보기
3/3

1장 오브젝트와 의존관계


1.6. 의존관계 주입(DI)


1.7.1 제어의 역전(IoC)과 의존관계 주입

  • 스프링 IoC 방식의 핵심을 짚어주는 의존관계 주입(Dependency Injection)이라는 이름을 사용하기 시작
  • 오브젝트는 다른 오브젝트에 주입할 수 있는 게 아니고 오브젝트의 레퍼런스가 전달될 뿐
  • DI는 오브젝트 레퍼런스를 외부로부터 제공(주입)받고 이를 통해 다른 오브젝트와 다양하게 의존관계가 만들어지는 것이 핵심

1.7.2. 런타임 의존관계 설정

런타임? 컴퓨터 프로그램이 실행되고 있는 동안의 동작

                        <A가 B에 의존하고 있음 >
  • 의존하고 있다? 의존대상, 여기서는 B사 변하면 그것이 A에 영향을 미친다는 뜻
  • 의존관계에는 방향성이 있다.
    A가 B에 의존하고 있지만, 반대로 B는 A에 의존하지 않는다. 의존하지 않는다는 말은 B는 A의 변화에 영향을 받지않는다는 뜻

UML에서 말하는 의존관계는 설계 모델의 관점에서 이야기하는 것
그러나 모델이나 코드에서 클래스와 인터페이스를 통해 드러나는 의존관계외에, 런타임 시에 오브젝트 사이에서 만들어지는 의존관계도 있다.
이를 런타임 의존관계, 오브젝트 의존관계라고 하는데 모델링 시점의 의존관계와는 성격이 라드다.

  • 런타임 시에 의존관계를 맺는 대상, 즉 실제 사용 대상인 오브젝트를 의존 오브젝트(Dependency Object)라고 한다.

  • 의존관계 주입은 구체적인 의존 오브젝트(여기서는 UserDao)와 그것을 사용할 주체, 보통 클라이언트(UserDaoTest)라고 부르는 오브젝트를 런타임 시에 연결해주는 작업을 말한다.

  • 의존관계 주입이란 다음 세가지 조건을 충족하는 작업을 말한다.

    • 클래스 모델이나 코드에는 런타임 시점의 의존관계가 드러나지 않는다. 그러기 위해서는 인터페이스에만 의존하고 있어야 한다.
    • 런타임 시점의 의존관계는 컨테이너나 팩토리가튼 제 3의존재가 결정한다
    • 의존관계는 사용할 오브젝트에 대한 레퍼런스를 외부에서 제공(주입)해줌으로써 만들어진다.
  • 의존관계 주입의 핵심은 설계 시점에는 알지 못했던 두 오브젝트의 관계를 맺도록 도와주는 제3의 존재가 있다는 것이다.

  • DI에서 말하는 제3의 존재는 바로 관계설정 책임을 가진 코드를 분리해서 만들어진 오브젝트라고 볼 수 있다.

UserDao의 의존관계 주입

@Configuration
public class DaoFactory {

    @Bean
    public UserDao userDao() {
        return new UserDao(testConnectionMaker());
    }

    @Bean
    public ConnectionMaker testConnectionMaker() {
        return new DConnectionMaker();
    }
}
public class UserDao {

	// 생성자의 파라미터로 이미 만들어진 오브젝트 전달
    public UserDao(ConnectionMaker connectionMaker) {
        this.connectionMaker = connectionMaker;
	}
}
  • DI는 자신이 사용할 오브젝트에 대한 선택과 생성 제어권을 외부로 넘기고 자신은 수동적으로 주입받은 오브젝트를 사용한다는 점에서 IoC의 개념에 잘 들어맞는다.

1.7.3. 의존관계 검색과 주입

  • 의존관계를 맺는 방법이 외부로부터 주입이 아니라 스스로 검색을 이용하기 때문에 의존관계 검색(dependecy lookup)이라고 불리는 것도 있다.
    의존관계 검색은 자신이 필요로 하는 의존 오브젝트를 능동적으로 찾는다.

  • 메소드나 생성자를 통한 주입 대신 스스로 컨테이너에게 요청하는 방법을 사용

public class UserDao {
	
    AnnotationConfigApplicationContext ctxt =
    		new AnnotationConfigApplicationContext(DaoFactory.class);
    this.connectionMaker = ctxt.getBean("connectionMaker", ConnectionMaker.class);
}
  • 의존관계 검색이 필요한 경우
    * UserDaoTest와 같은 클라이언트에서는 스프링 IoC와 DI를 컨테이너를 적용했다고 하더라도, 애플리케이션의 기동 시점에서 적어도 한 번은 의존관계 검색 방식을 사용해 오브젝트를 가져와야 한다. 스태틱 메소드인 main()에서는 DI를 이용해 오브젝트를 주입받을 방법이 없기 때문이다.

의존관계 검색과 의존관계 주입에서의 가장 큰 차이는 의존관계 주입에서는 주입받는 오브젝트 자신도 스프링 빈이어야 한다. 반면에 의존관계 검색에서는 검색하는 오브젝트 자신이 스프링 빈일 필요가 없다는 점이다.

1.7.4. 의존관계 주입의 응용

DI의 장점? 다른 책임을 가진 사용 의존관계에 있는 대상이 바뀌거나 변경되더라도 자신은 영향을 받지않으며, 변경을 통한 다양한 확장방법에는 자유롭다는게 지금까지 설명한 장점

기능 구현의 교환

운영DB와 개발DB를 번갈아가며 써야하는 상황이라면?

  • 이전 초난감 DAO와는 다르게 ConnectionMaker 인터페이스를 상속하는 클래스를 구현하고 connectionMaker 빈이 반환하는 객체만 변경해주면 된다.
@Bean
public ConnectionMaker connectionMaker() {
    return new LocalDBConnectionMaker();
}

부가기능 추가

DB 연결횟수를 세는 기능 추가한다면?

  • DAO와 DB커넥션을 만드는 오브젝트 사이에 연결횟수를 카운팅하는 오브젝트를 하나 더 추가
public class CountingConnectionMaker implements ConnectionMaker{
    int counter = 0;
    private ConnectionMaker realConnectionMaker;

	// 생성자
    public CountingConnectionMaker(ConnectionMaker realConnectionMaker) {
        this.realConnectionMaker = realConnectionMaker;
    }

    @Override
    public Connection makeConnection() throws ClassNotFoundException, SQLException {
        counter++;
        return realConnectionMaker.makeConnection();
    }
}

1.7.5. 메소드를 이용한 의존관계 주입

  • 의존관계 주입 시에 반드시 생성자를 이용해야 하는 것은 아니다.

수정자 메소드를 통한 의존관계 주입

수정자 메소드? 외부에서 오브젝트 내부의 애트리뷰트 값을 변경하려는 용도로 주로 사용됨

  • 한 번에 한 개의 파라미터만 가질 수 있다.
  • 부가적으로 입력 값에 대한 검증이나 그 밖의 작업도 수행 가능하다.
  • 스프링은 전통적으로 수정자 메소드를 가장 많이 사용해왔다.
  • XML을 사용하는 경우 자바빈 규약을 따르는 수정자 메소드가 가장 사용하기 편하다.
  • setter는 IDE에서 자동으로 생성해주는 규약을 따르는 것이 좋다.

일반 메소드를 통한 의존관계 주입

  • 수정자 메소드처럼 set~으로 시작해야 한다.
  • 한번에 여러 개의 파라미터를 받을 수 있다.

0개의 댓글