Java Spring : DI, IoC 컨테이너

김선미·2022년 6월 27일

DI (의존성 주입)

예를 들어 Repository에서 id, pw를 파라미터로 받아야 하는 조건이 생기는 경우 service, controller 에서도 id, pw가 필요해진다.

  1. 여러 개의 controller에서 하나의 service에 접근할 경우 각 controller 마다 service 객체를 생성한다.
  2. service는 repository 객체를 생성한다. 이때 repository의 id, pw를 알아야한다.
  3. 결국 controller도 repository의 id, pw를 알아야한다.
  4. 미리 생성한 repository 객체를 모두 가져다 쓸 경우 service, controller를 수정하지 않아도 된다. 변경사항이 생겨도 repository만 수정한다.
  5. 이렇게 객체를 직접 생성하지 않고 이미 생성한 객체를 가져다 쓰는 것을 의존성 주입(Dependency Injection)이라고 한다.
  6. 또한 기존의 객체를 생성하여 사용하던 방식에서 생성한 객체를 가져다 쓰는 방식이라고 해서 제어의 역전 (IoC: Inversion of Control) 이라고 한다.

Spring IoC 컨테이너

스프링 프레임워크는 DI 방식을 사용할 수 있도록 객체를 생성하는 기능을 제공한다.

  • 빈 (Bean): 스프링이 생성해주는 객체
  • 스프링 IoC 컨테이너: 빈을 모아둔 통
  • @Configuration : 설정 또는 빈을 등록하기 위한 어노테이션
    • Bean을 등록할때 싱글톤(singleton)이 되도록 보장해준다.
    • 스프링컨테이너에서 Bean을 관리할수있게 됨.
  • @Controller, @RestController, @Service, @Repository 와 같이 앞에 '@' 를 붙이는 것을 어노테이션이라고 부르고, 모두 스프링의 빈으로 등록된다.
  • 구현
  • BeanConfiguration.java
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class BeanConfiguration {
    @Bean
    public ProductRepository productRepository() {
        String dbId = "sa";
        String dbPassword = "";
        String dbUrl = "jdbc:h2:mem:springcoredb";
        return new ProductRepository(dbId, dbPassword, dbUrl);
    }

    @Bean
		@Autowired
    public ProductService productService(ProductRepository productRepository) {
        return new ProductService(productRepository);
    }
}
  • ProductRepository.java
public class ProductRepository {
    private String dbId;
    private String dbPassword;
    private String dbUrl;

    // 생성자
    public ProductRepository(String dbId, String dbPassword, String dbUrl) {
        this.dbId = dbId;
        this.dbPassword = dbPassword;
        this.dbUrl = dbUrl;
    }

    ...
}
  • ProductService.java
public class ProductService {
    // 멤버 변수 선언
    private final ProductRepository productRepository;

    // 생성자: ProductService() 가 생성될 때 호출됨
    @Autowired
    public ProductService(ProductRepository productRepository) {
        // 멤버 변수 생성
        this.productRepository = productRepository;
    }

    public List<Product> getProducts() throws SQLException {
        // 멤버 변수 사용
        return productRepository.getProducts();
    }

    public Product createProduct(ProductRequestDto requestDto) throws SQLException {
        // 요청받은 DTO 로 DB에 저장할 객체 만들기
        Product product = new Product(requestDto);
        productRepository.createProduct(product);
        return product;
    }

    public Product updateProduct(Long id, ProductMyPriceRequestDto requestDto) throws SQLException {
        Product product = productRepository.getProduct(id);
        if (product == null) {
            throw new NullPointerException("해당 아이디가 존재하지 않습니다.");
        }
        int myPrice = requestDto.getMyprice();
        productRepository.updateProductMyPrice(id, myPrice);
        return product;
    }
}
  • ProductController.java
@RestController // JSON으로 응답함을 선언합니다.
public class SearchRequestController {

    private final NaverShopSearch naverShopSearch;

    @Autowired
    public SearchRequestController(NaverShopSearch naverShopSearch) {
        this.naverShopSearch = naverShopSearch;
    }

    @GetMapping("/api/search")
    public List<ItemDto> getItems(@RequestParam String query) {
        String resultString = naverShopSearch.search(query);
        return naverShopSearch.fromJSONtoItems(resultString);
    }
}
profile
백엔드 개발 공부

0개의 댓글