-
IoC 와 DI 용어 이해하기스프링 2023. 4. 15. 23:59
IoC = 설계 원칙
DI = 디자인 패턴
설계 원칙을 기반으로 디자인 패턴을 잘 수행하여 코드를 작성하면 좋은 코드를 만들 수 있다.
좋은 코드란?
- 논리가 간단해야 한다.
- 중복을 제거하고 표현을 명확하게 한다.
- 코드를 처음 보는 사람도 쉽게 이해하고 수정할 수 있어야 한다.
- 의존성을 최소화해야 한다.
- 새로운 기능을 추가 하더라도 크게 구조의 변경이 없어야 한다.
- …
따라서 Spring 은 개발자가 Java 를 사용하여 쉽게 좋은 코드를 작성할 수 있도록 도와주는 역할을 해줍니다.
여기서 IoC 와 DI 는 Spring 에서 도와주는 핵심 기술 중 하나라고 할 수 있습니다.
그리고 IoC 에 대해 ‘IoC 는 DI 로도 알려져 있다’ 라고 소개하고 있습니다.
의역해보자면 ‘DI 패턴을 사용하여 IoC 설계 원칙을 구현하고 있다’ 라고 이해하시면 좋을 것 같습니다.
이처럼 Interface 다형성의 원리를 사용하여 구현 하면 고객이 어떠한 음식을 요구하더라도 쉽게 대처할 수 있습니다.
public class Consumer{
void eat(Food food) {
food.eat();
}
public static void main(String[] args) {
Consumer consumer = new Consumer();
consumer.eat();
consumer.eat();
}
}
interface Food{
void eat();
}
class Chiken implements Food{
@Override
public void eat(){
System.out.printf("치킨을 먹는다.");
}
}
class Tteokbokki implements Food{
@Override
public void eat(){
System.out.printf("떡볶이를 먹는다.");
}
}Food 인터페이스를 선언한 후 치킨과 떡뽂이 클래스가 Food인터페이스를 구현하고 있다.
그리고 Consumer클래스는 Food인터페이스를 매개변수로 받아서 매개변수로 들어오는 구현체 내부에 있는 eat메서드를 실행한다. eat 메서드 내부 Food 매개변수 안에 Consumer 즉 고객이 먹고 싶어 하는 음식 클래스를 인서턴스화 하여 넘겨주면 "치킨을 먹는다.","떡뽂이를 먹는다"의 메서드가 각각 실행이 된다.
이러한 관계를 약한 결합 및 약한 의존성 이라고 말할 수 있습니다.
주입이란?
- 우리가 주사기를 통해 백신을 우리 몸속에 주입 하듯이
- 코드에서의 주입도 마찬가지로 여러 방법을 통해 필요로 하는 객체를 해당 객체에 전달하는 것입니다.
- 코드를 통해 코드에서의 주입에 대해 이해해보겠습니다.
필드에 직접 주입
public class Consumer {
Food food;
void eat() {
this.food.eat();
}
public static void main(String[] args) {
Consumer consumer = new Consumer();
consumer.food = new Chicken();
consumer.eat();
consumer.food = new Tteokbokki();
consumer.eat();
}
}
interface Food {
void eat();
}
class Chicken implements Food{
@Override
public void eat() {
System.out.println("치킨을 먹는다.");
}
}
class Tteokbokki implements Food{
@Override
public void eat() {
System.out.println("떡볶이를 먹는다.");
}
}이처럼 Food 를 Consumer 에 포함 시키고 Food 에 필요한 객체를 주입하여 사용할 수 있습니다.
메서드를 통한 주입
public class Consumer {
Food food;
void eat() {
this.food.eat();
}
public void setFood(Food food) {
this.food = food;
}
public static void main(String[] args) {
Consumer consumer = new Consumer();
consumer.setFood(new Chicken());
consumer.eat();
consumer.setFood(new Tteokbokki());
consumer.eat();
}
}
interface Food {
void eat();
}
class Chicken implements Food{
@Override
public void eat() {
System.out.println("치킨을 먹는다.");
}
}
class Tteokbokki implements Food{
@Override
public void eat() {
System.out.println("떡볶이를 먹는다.");
}
}이처럼 set 메서드를 사용하여 필요한 객체를 주입하여 사용할 수 있습니다.
생성자를 통한 주입
public class Consumer {
Food food;
public Consumer(Food food) {
this.food = food;
}
void eat() {
this.food.eat();
}
public static void main(String[] args) {
Consumer consumer = new Consumer(new Chicken());
consumer.eat();
consumer = new Consumer(new Tteokbokki());
consumer.eat();
}
}
interface Food {
void eat();
}
class Chicken implements Food{
@Override
public void eat() {
System.out.println("치킨을 먹는다.");
}
}
class Tteokbokki implements Food{
@Override
public void eat() {
System.out.println("떡볶이를 먹는다.");
}
}이처럼 생성자를 사용하여 필요한 객체를 주입하여 사용할 수 있습니다.
제어의 역전이란?
- 위의 예시를 통해 간단하게 설명해 보자면 인터페이스를 구현한 객체를 필요로 하는 객체에 전달하여 제어를 넘기는 것입니다.
- 더 풀어서 설명해 보자면 기존에는 Consumer 가 직접 먹고 싶어하는 음식을 생성하여 먹었습니다.
- 즉, 제어의 흐름이 Consumer → Food 였습니다.
- 하지만 Interface 즉, Food 를 구현한 Chicken 객체를 Consumer 에 주입(전달)함으로써 제어의 흐름이 Food → Consumer 로 역전 되었습니다.
- 더 깊이 있는 이해를 위해 직접 Java 로 예제를 만들어보며 이해해보겠습니다.
'스프링' 카테고리의 다른 글
스프링부트 (타임스탬프,오전 1시 마다 가격 업데이트) (0) 2023.04.20 스프링 부트 (메모장만들기) * (0) 2023.04.17 스프링 ㅡMVC (Response, Request) (0) 2023.04.15 JPA (Java와 DB 연동) (0) 2023.04.15 SQL (Query문) (0) 2023.04.14