고을마을 : 나의 코딩 이야기

항해99 7기 3주차 WIL[DI, IoC, Bean] 본문

항해99 7기/WIL(Weekly I Learned

항해99 7기 3주차 WIL[DI, IoC, Bean]

고을마을 2022. 5. 29. 22:22

2022년 5월 29일 

항해99에 참여한지 3주가 된 날이다.

 

이번주 중요했던 부분을 다시한번 살펴보고 그 내용을 적어보고자 한다.


DI?

DI는 Dependency Injection의 줄임말로, 다양한 우리 말 번역이 있지만, 이 글에서는 의존성 주입이라는 말로 사용하고자 한다.

“A가 B를 의존한다.”는 표현은 어떤 의미일까? 추상적인 표현이지만, 토비의 스프링에서는 다음과 같이 정의한다.

 

의존대상 B가 변하면, 그것이 A에 영향을 미친다.

- 이일민, 토비의 스프링 3.1, 에이콘(2012), p113

 

즉, B의 기능이 추가 또는 변경되거나 형식이 바뀌면 그 영향이 A에 미친다.

 

이번에 배운 코드를 바탕으로 설명해보고자 한다.

 

public class ProductController {

    private final ProductService productService;

    public ProductController(ProductService productService) {
        this.productService = productService;
    }
public class ProductService {

    private final ProductRepository productRepository;

    public ProductService(ProductRepository productRepository) {
        this.productRepository = productRepository;
    }
public interface ProductRepository extends JpaRepository<Product, Long> {
    List<Product> findAllByUserId(Long userId);
}

ProductController는 ProductService에게, 

ProductService는 ProductRepository에게 의존하게끔 주입해줬다.

 

이러한 주입은 주입대상이 변하더라도 그 구현 자체를 수정할 일이 없거나 그 일이 줄어들게 된다.

각각의 클래스를 형성해 놓고 주입만 하면 되기 때문에 재사용성이 높은 코드가 된다.

 


IoC?

IoC란 Inversion of Control의 줄임말로 한글로 번역하면 제어의 역전이라는 말이다.

"제어의 역전" 이라는 의미는 말 그대로 메소드나 객체의 호출작업을 개발자가 결정하는 것이 아니라,

외부에서 결정되는 것을 의미한다.

 

제어의 역전 개념은 이미 폭넓게 적용되어 있다. 일반적으로 자바 프로그램은 main() 메소드에서 시작해서

개발자가 미리 정한 순서를 따라 객체가 생성되고 실행된다.

그런데 서블릿을 생각해보자. 서블릿을 개발해서 서버에 배포할 수는 있지만, 배포하고 나서는 개발자가

직접 제어할 수 있는 방법은 없다. 대신 서블릿에 대한 제어 권한을 가진 컨테이너가 적절한 시점에

서블릿 클래스의 객체를 만들고 그 안의 메소드를 호출한다.

 

이 방식은 대부분의 프레임워크에서 사용하는 방법으로,

개발자는 필요한 부분을 개발해서 끼워 넣기의 형태로 개발하고 실행하게 된다.

프레임워크가 이러한 구조를 가지기 때문에, 개발자는 프레임워크에 필요한 부품을 개발하고,

조립하는 방식의 개발을 하게 된다.

이렇게 조립된 코드의 최종 호출은 개발자에 의해서 제어되는 것이 아니라,

프레임워크의 내부에서 결정된 대로 이뤄지게 되는데, 이러한 현상을 "제어의 역전"이라고 표현한다.

 


Bean?

빈은 스프링이 관리하는 객체이며, 스프링 IoC 컨테이너는 '빈'을 모아둔 통을 말한다.

 

클래스 위에 @Component를 달아주면 빈이 설정된다. (빈... 영단어 그대로 커피콩처럼 생겼다!)

 

아래처럼 직접 객체를 생성해서 @Bean으로 빈을 요청할 수도 있다.

import org.springframework.context.annotation.Bean;
        import org.springframework.context.annotation.Configuration;

@Configuration
public class BeanConfiguration {

    @Bean
    public ProductRepository productRepository() {
        String dbUrl = "jdbc:h2:mem:springcoredb";
        String dbId = "sa";
        String dbPassword = "";

        return new ProductRepository(dbUrl, dbId, dbPassword);
    }
}

 

@Controller와 @Service에는

아래와 같이 @Component가 포함되어 있어서 따로 @Component를 포함시키지 않아도 된다.

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Controller {
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Service {

 


 

주특기숙련주차로 넘어가니 강의를 들어도 완벽하게 이해가 되지 않는다.

이미 각오하고 있었지만 저번 주에 비해 너무 힘겹다.

과제도 해야하는데... 강의는 쌓여져있고 굉장히 부담스러운 주간이다.

 

내일은 보다 더 발전할 수 있길...