dev_공부일지/Spring 개념 정리

Spring IoC/DI 개념정리 (우아한 형제등 유안)

dev_0hoon 2021. 5. 5. 21:11

*이 글은 유투브 우아한tech의 유안님께서 발표한 강의를 배경으로 정리식으로 작성된 글입니다. 그렇기에 제가 잘못 이해 했을 수 있으니 읽기전에 주의하시길 바랍니다.

 

 

ioc/ di 란?


토비의 스프링에서는

스프링 프레임워크의 근간
오브젝트의 생명주기와 의존관계에 대한 프로그래밍 모델
유연하고 확장성이 뛰어난 코드를 만들 수 있게 해주는 프로그래밍 모델

유연하고 확장성이 뛰어나다 

=> 변경이 있을 떄 수정이 쉽다(쓸데 없는 부분은 신경쓰지않고 수정할 수 있다)
=> 수정할 부분만 수정하면 된다
=> 관심사의 분리가 잘 이루어졌다

 

 

전략패턴
관심사의 분리를 위해 준비한 코드


public class Car {
	private MovingStrategy movingStrategy;
	private int distance;

	public Car(MovingStrategy movingStrategy){
		this.movingStrategy = movingStrategy;
		this.distance = 0;
	}

	void move(){
		if(MovingStrategy.isMovable()){
			distance++;
	}
}


자동차의 움직임을 수정하고 싶을때에는 자동차를 수정하는 것이 아닌

movingStrategy라는 인터페이스만 수정하면 된다.

이렇게 되면 내가 어떤 객체인 movingStrategy를 수정하게 되는지 알수없다

주도권이 나에게 없다는 것이다.

그럼 제어권 주도권이 누구에게 있을까? 나에게 없으니 카객체를 사용하는 객체에게 있을것이다

 

//클라이언트 쪽을 보면

public class Racing{
	private static final int NUM_OF_CARS = 10;
	private List<Car> cars = new ArrayList<>();

	public Racing(){
		MovingStrategy strategy = new RandomMovingStrategy();
		
		for (int i = 0 ; i<NUM_OF_CARS; I++) {
			cars.add(new Car(strategy));
		}
	public void move(){
		cars.forEach(car::move);
	}
	}
}


카 객체의 양과 카객체가 어떻게 행동할지도 제어를 해주고있다

자세히보면 관심사의 분리가 적절히 이루어 졌다고 보기 힘들다

여기는 레이싱을 위한 것이있어야하는데 카를 생성하는 코드도 있다

관심사가 섞여있는 것이다. 

여기서 알 수 있는것은 제어에는 두가지 관점이 있다는 것인데

카의 생성, 카의 행동관점이 들어있다

 

제어의 두 가지 관점

1.어떤 연관관계를 맺으며 생성될 것인가?
2.어떻게 사용될 것인가?


racing에는 1번이 아닌 2번만이 적절하게 들어가야 할 것인데

public class CarFactory {
	public static Car car(){
		return new Car(movingStrategy());
	}
	private static MovingStrategy movingStrategy() {
 		return new RandomMivingStrategy();
	}
}

->>

public class Racing{
	private static final int NUM_OF_CARS = 10;
	private List<Car> cars = new ArrayList<>();

	public Racing(){
		MovingStrategy strategy = new RandomMovingStrategy();
		
		for (int i = 0 ; i<NUM_OF_CARS; I++) {
			//cars.add(new Car(strategy)); 변경
			cars.add(carFactory.car());
		}
	public void move(){
		cars.forEach(car::move);
	}
	}
}


생성에 대한 책임을 carFactory로 가게 되고 

이제 생성에 대한 주도권은 carFactory

어떻게 행동하냐는 racing이 가지게 되었다

만약 카의 움직임을 다르게 주고싶다면

 

public class CarFactory {
	public static Car car(){
		return new Car(movingStrategy());
	}
	private static MovingStrategy movingStrategy() {
 		return new RandomMivingStrategy();
	}
}


--> 코드 변경


public class CarFactory {
	public static Car car(){
		return new Car(movingStrategy());
	}
	private static MovingStrategy movingStrategy() {
 		return new staticMovingStrategy(); //<-- 코드바뀜
	}
}


이렇게 어떤움직임의 차를 만들지는 carFactory에서 수정이 된다
그럼 카에 대한 주도권을 확인 할 수 있다

반대로 레이싱은 움직임은 이렇게 하나의 객체안에서만 변경하도록 할 수 있도록 할수있다.

public class Racing{
	private static final int NUM_OF_CARS = 100;  // <== 10에서 100으로 변경
	private List<Car> cars = new ArrayList<>();

	public Racing(){
		MovingStrategy strategy = new RandomMovingStrategy();
		
		for (int i = 0 ; i<NUM_OF_CARS; I++) {
			cars.add(carFactory.car());
		}
	public void move(){
		//cars.forEach(car::move);
		for (int i = 0 ; i<RANDOM_NUMBER; I++) {
			cars[i].move();  // 움직임 변경
		}
	}
	}
}


당연한 이야기지만 실제로 ioc가 이렇게 작동한다.

1.어떤 연관관계를 맺을 것인가?
 -팩토리 -> 빈 컨테이너

2.어떻게 사용될 것인가?
 -클라이언트 ->스프링 내부 코드


결론

ioc/di 는 사실 우리 모두 레벨 1부터 자연스럽게 사용하고 있던 것

관심사의 분리를 통해 유연하고 확장성이 쉬운 코드를 만들다보니
자연스럽게 만들어진 프로그래밍 모델

스프링 IoC/DI 가  어떻게 이루어 지는지 이해하고 우리가 작성하는 코드내에서도 조그만
IoC/DI를 더 잘 활용하면 좋겠다