스프링 프레임워크 입문 무료강의 by 백기선

Inversion of Control

의존성의 뒤바뀜.

원래 의존성의 제어권은 자기자신이 가지고 있다.

예를 들어서, petclinic 샘플 코드 내에서 OwnerController 클래스를 보면 아래 처럼 돼있다.

@Controller
class OwnerController {
	private final OwnerRepository owners;

	public OwnerController(OwnerRepository clinicService) {
		this.owners = clinicService;
	}
}

의존성이 뒤바뀌지 않았다면, 아래와 같이 일반적으로 의존성에 대한 제어권을 가질 것이다.

class OwnerController {
	private OwnerRepository repository = new OwnerRepository();
}

OwnerRepository는 OwnerController의 의존성이다.
OwnerRepository가 있어야 OwnerController를 제대로 쓸 수 있다. OwnerController는 OwnerRepository를 필요로한다.

화면에서 받은것을 OwnerRepository를 처리하듯이 반드시 OwnerRepository는 OwnerController에 필요하다.

그런데, 이걸 누가 만들고 관리하느냐?

내가 관리를 안하고 나 이외의 밖에서 넣어주는 그런 형태를 Inversion of Controller라고 한다

class OwnerController {
	private OwnerRepository repo;

	public OwnerController(OwnerRepository repo) {
		this.repo = repo;
	}
}

이걸 누군가가 생성자가 주겠지? 라는 가정하에서 repo를 사용하면 된다.

class OwnerControllerTest {
	@Test
	public void create() {
		OwnerRepository repo = new OenerRepository();
		OwnerController controller = new OwnerController(repo);
	}
}

예를 들어서, 위와 같은 테스트코드, 즉 OwnerController 클래스 밖에서, OwnerRepository를 OwnerController 한테 생성자를 통해 넘겨줄 수 있는데, 이것을 의존성 주입이라고 한다.

이런 전체적인 관리형태를 Inversion of Control 이라고 한다.

제어가 바뀐 것이다. 나 자신이 아닌 다른 누군가에 의해서.


IoC 컨테이너

스프링 프레임워크는 IoC 용 컨테이너를 제공해준다. 컨테이너의 핵심적인 인터페이스가 바로 ApplicationContext 라고한다.

하지만 IoC 컨테이너를 직접 쓸 일이없다

코드어디에도 ApllicationContext는 찾아 볼 수 없다.

ApllicationContext는 위에 코드를 동작하게 만들어준다.

IoC 컨테이너 내부에서 OwnerController를 만들어준다.

OwnerController와 OwnerRepository를 예롤 들자면 둘다 ApllicationContext 내부에서 만들어주는 bean이다. 둘의 의존성은 IoC의컨테이너가 관리해주는데 오로지 bean만 관리해준다. 오너는 빈이 아니다.

인텔리제이에서 보면 Owner는 왼쪽에 아무런 표시가 없다. OwnerController 옆에는 초록색콩이있다.

어노테이션 Controller 가 붙으면 자동으로 빈에 등록이 된다. 빈으로 등록 되는 애들은 IoC컨테이너 내부에서 그 객체들을 만들고 그 객체ㅡ들의 의존성을 관리해준다.

빈은 OwnerController에 필요한 OwnerRepository의 타입을 찾아서 생성자에 주입을 한다. 그래서 널이아니다.


빈 Bean

빈은 스프링 IoC 컨테이너가 관리하는 객체이다.

오너는 스프링ioc가 관리하는 객체가 아니다. 그렇기때문에 빈이아니다.
오너컨트롤러는 스프링아이오씨의 컨테이너인 applicationcontext가 관리하는 객체가 맞다. 그렇기 때문에 빈이된다.

펫은 스프링 ioc가 관리하는 객체가 아니다. 그렇기때문에 빈이아니다.

빈이 되게 하려면?
등록하는 방법은 2가지
1. Component Sacnning
2. 직접 일일이 등록하는 방법

Component Scanning
스프링 부트로 만든 어플은 스프링부트어플리케이션의의 어노테이션을 가지는 메서드가 있다. 이 어노테이션의 코드를 따라가면 컴포넌트 스캔을 찾을수있다.

어노테이션 자체에는 기능이없다 . 어노테이션은 주석과도 같다. 그 주석을 단지 어디에 붙일수있냐 또는 언제까지 그 주석을 유지할것이냐 이런 속성을 가질 뿐이다
어노테이션 자체는 기능이 없다. 어노테이션을 마커로사용해서 ㅓ노테이션을 처리하는 프로세스들이있다
마찬가지로 컴포넌트 스캔을 처리하는 프로세스가있다.

모든 패키지의 컴포넌트라는 어노테이션이 ㅂㅌ어있는 클래스를 찾아서 빈으로 등록을 해준다. 빈이된다고했는데 컨트롤러인데 왜 빈이되냐?

컨트롤러의 코드를 열어보면 ㅇ컴포넌트라는 어노테이션이 붙은것을 볼수있따. 결국에 컨트롤러는 컴포넌트랑 같다. 그렇기때문에 빈으로 등록이 된다.

PetTypeFormatter는 컴포넌트라는 어노테이션이 붙어있는데 그것은 명시적으로 그냥 빈이 되는 것이다.

직접 ㄱ일일이 등록하는 방법

@Bean
public String kyu() {
return "kyu";
}
메서드의 이름이 이 빈의 이름이 된다.
String xㅏㅇ비의 빈을 등록했다.
단, Configuration라는 어노테이션을 가지는 클래스 안에 저으이를 해야한다.
컨피결레이션이라는 어노테이션이 스프링부트어플리케이션 어노테이션안에있다
어노테이셤안에 여러개의 어노테이션이 있는데 붙여야할게 많아서 그냥 합쳐놓은거다.
그래서 이미 있는거기때문에 저런식으로 빈을 안에 등록할수있따

그럼 어떻게 꺼내서 써야하나?

@Autowired 를 이용해서 어플리케이션 컨텍스트 안에있는 빈들을 꺼내쓸수있다.

@Autowired
String kyu;

@GetMapping*"/context")
public String context() {
	return "hello " + kyu;
}

오로지 빈들만 의존성을 관리해준다. 오너,펫 이런건 의존성을 관리해주지않는다.


의존성 주입

의존성 주입은 주로 @Autowird 또는 @Inject 를 받아서 사용한다.

코드의 예제에는 @Autowird 가 없다.

어떤 bean에 생성자가 오직하나있고 파라미터에 받는 타입의 빈이 존재한다면, 이 빈은 주입을 해준다. @Autowird가 없더라도 기본적으로 주입을 해준다.

다른 방법으로는, 필드 위에 @Autowird 를 붙일 수 있다. 또 다른 방법은 세터에 붙이는 방법도 있다.

기본적으로는 생성자에 붙이고,
필드와 세터 중에 어디에 붙이냐면 세터를 가진다면 세터에 붙이고 세터에 없다면 필드에 붙인다.


AOP (Aspect Oriented Programming) 소개

AOP의 핵심은 흩어진 코드를 한곳에 모으는 코딩 기법이라는 것이다.

강의를 보면 그냥 중복을 줄이는 것 뿐이라는 생각이 드는데 이게 무슨 기법이라는 거지? 나중에 찾아보자

이런식으로 구현하는 기법이 여러개가 있는데 바이트 코드를 조작하는 기법이 있다. 바이트 코드를 조작해서 이미 컴파일된 코드에 중복된 코드를 넣는 방법이 있다.

또, 프록시 패턴이 있다.


AOP 적용예제

@Transactional 이 들어간게 AOP 이다.

어떤 메서드가 호출 됐을때 호출된 시간을 로그로 남겨보자.
특정 어노테이션이 달린 메서드만 처리하도록 @interface를 이용해서 어노테이션을 만들어 주고 그 어노테이션을 처리할 프로세스를 또 만든다.


PSA (Portable Service Abstarction) 소개

바꿔끼기 좋은 서비스 추상화

잘만든 인터페이스

왜 잘 만들었냐?

확장성이 좋지 못한 코드 혹은 기술에 특화되어 있는 코드를 쓰면
테스트를 만들기 어렵고 기술을 바꿀때마다 내 코드가 바뀐다.

잘 만든 인터페이스가 있다면 그 인터페이스를 이용해서 내 코드를 작성하기때문에 다른것과 바꿔끼기가 좋다. 인터페이스 밑에있는 기술 자체를 JDBC를 쓰다가 하이퍼넷을 쓰다던가 할 때 내 코드가 바뀌지 않는다. PSA는 매우 잘만든 인터페이스이기 때문이다.

스프링은 어떤 PSA를 제공하느냐?

대부분의 API가 전부 다 PSA이다.


스프링 트랜잭션
스프링 캐시


웹 MVC

서블릿을 쓰는 것일수도있고 리액티브를 쓸수도 있다. 의존성을 확인해봐야한다
컨트롤러와 겟매핑을 썼지만 추상화 기술을 독립적으로 만들어준다고 할 수 있다
파라미터에도 서블릿이 없다. 그렇기때문에 코드들은 리액티브로 바뀔수도 있다.
대부분은 윗단이 추상화되어있기때문에 내 코드가 바뀌지않는다.
이게 PSA의 가장 큰 장점이자 목표이다. 테스트하기도 쉽고.


강좌 마무리

스프링의 핵심은 IoC, AOP, PSA 이다.
대부분의 라이브러리는 PSA이다. 다 추상화 되어있는 Abstraction 계층이다.

IoC는 OwnerController가 OwnerRepository를 사용할때 내가 직접 만들어서 사용하는게 아니라 누군가로부터 주입을 받아서 생성자를 통해서 들어온다고 가정하고 코드를 하면 된다. 이걸 스프링이 해준다. 구체적으로는 ApllicationContext 이 그것을 해준다.


좋은 웹페이지 즐겨찾기