
토비의 스프링 6 - 이해와 원리
노트 작성자
logt
오브젝트와 의존관계
오브젝트와 의존관계
클래스와 오브젝트
클래스: 오브젝트를 만들어 내기 위해서 필요한 구조체
오브젝트: 프로그램을 실행시키기 위한 기능, 즉
인스턴스
의존관계
성립되기 위해서는 2개 이상의 객체가 존재해야 한다.
부모 객체가 변경되면 자식 객체도 영향을 받는다.
핵심 체크
오브젝트는 프로그램을 실행하는 런타임 환경에서 의존관계가 만들어 지는데, 클래스 레벨의 의존관계와 런타임 레벨의 의존관계가 다를 수 있다. 이것이 스프링이 제공해주는 핵심 원리의 바탕이 된다.
클래스의 분리
인터페이스 도입
인터페이스를 사용하여 데이터 타입을 인터페이스 아래에 구현체들로 만들 수 있다. 그러나 여전히 생성자는 사용할 구현체의 생성자에 맞게 변경해야 하는 번거로움이 발생한다.
관계설정 책임의 분리
여전히 PaymentService 클래스 안에서 ExRateProvider 인터페이스의 구현체(WebApiExRateProvider)의 생성자가 필요로 하다.
런타임 의존관계:
PaymentService = WebApiExRateProvider
의존관계를 설정하는 코드를 다른 걸로 바꾸는 것이다. Client(Controller)로 주는 것이다. 그러면 Service는 변경될 필요가 없어진다.
원칙과 패턴
OCP(개방-폐쇄 원칙): 클래스나 모듈은 확장에는 열려 있어야 하고 변경에는 닫혀 있어야 한다.
Spring에서 자주 인터페이스들을 implement하게 된다. 이것은 확장이다. 그렇다고 인터페이스 안에 기존에 존재하던 구현체의 코드를 변경할 순 없다.
스프링 컨테이너와 의존관계 주입
***스프링 특징은
IOC-DI를 제공하는 컨테이너이다(제어의 역전 / 의존성 주입).bean은 애플리케이션의 기능을 담당하고 제공하는 핵심 클래스의오브젝트이다.
싱글톤 레지스트리
`getbean()`을 두 번 호출해도 같은 오브젝트를 반환한다. 이것은 스프링이 싱글톤 패턴을 기반으로 둔다는 것을 알 수 있다.
`@Configuration` 선언 아래에 존재하는 모든 bean은 하나의 오브젝트로 돌아갈 수 있게 설정되어 있다.
의존성 역전 원칙(DIP)
추상화란 인터페이스를 도입하는 것.모듈 이란 하나의 레이어라고 생각하면 된다. 예를 들어, 정책을 정하기 위한 모여 있는 Policy Layer(상위 모듈), 그리고 그것의 구현체가 있는 Mechanism Layer(하위 모듈). 아주 단순하게 package 라고 생각해도 좋다.
인터페이스의 소유권을 어느 레이어에 설정할지를 잘 고려해야 한다.
정리: 의존성 역전 원칙을 잘 따르는 코드를 만들 때는 인터페이스를 만들어 내고 추상화를 한 다음, 모든 코드가 추상화에만 의존하도록 만드는 것이 첫 번째 작업이다. 두 번째는 인터페이스를 구현한 클래스가 있는 모듈에 두는 것이 아닌, 사용하는 코드가 있는 상위 모듈에 이동(역전)시키는 것이다.
테스트
테스트의 구성 요소
SUT(System Under Test) 테스트 대상.
예를들어, PaymentService가 SUT라고 했을 때, WebApiExRateProvider은 콜라보레이터이다.
작은 단위로 테스트를 하고 싶은데 PaymentService를 테스트를 할 때 어쩔 수 없이 WebApiExRateProvider를 사용해야 한다.
만약에 WebApiExRateProvider가 제대로 기능하지 않는다면 어떡하지? -> 테스트하는 동안만 테스트 대상의 협력자, stub을 만드는 것이다.
템플릿
WebApiExRateProvider 리팩터링
ApiExecutor 콜백과 메소드 주입
콜백(Callback): 실행되는 것을 목적으로 다른 오브젝트의 메소드에 전달되는 오브젝트.
function을 실행시키는 목적의 오브젝트. 하나의 메소드를 가진 인터페이스 타입(SAM)의 오브젝트 또는 람다 오브젝트.템플릿은 전략 패턴의 컨텍스트.
콜백은 전략 패턴의 전략.
메소드 주입: 콜백이 템플릿 메소드로 전달되는 과정.
스프링에서 템플릿에다가 콜백을 주입할 때 이 콜백은 대부분 메소드가 하나만 존재한다.
디폴트 콜백과 템플릿 빈
우리가 어떤 것을 싱글톤 빈으로 만들 수 있나 없나를 생각할 때에 제일 큰 것은 이것을 매번 새로운 인스턴스를 만들어야 하는지, 한 번 만들어 놓고 여러 스레드에서 서버는 동시에 여러 클라이언트의 요청을 받아서 처리해도 되는지를 잘 고려해서 빈을 설정해주는 것을 잘 기억해두자.
스프링이 제공하는 템플릿
RestTemplate
HTTP API 요청을 처리하는 템플릿
HTTP Client 라이브러리 확장:
ClientHttpRequestFactoryMessage Body를 변환하는 전략:
HttpMessageConverter
이전에 자바의 굉장히 오래된 URL Connection을 가지고 만들어 보기도 하고, 자바 11에서 지원하는 HttpClient 호출방식으로 만들어 봤는데, RestTemplate도 이러한 기능을 가지고 있다.
예외
예외를 다루는 방법
예의의 종류
Error
Exception(checked)
RuntimeException(unchecked)
Error: 근본적으로 VM이나 시스템의 여러 가지 설정들을 손을 봐서 시스템 엔지니어 차원에서 서버를 잘 구축해줘야 되는 문제이기에 코딩에서 컨트롤할 수 없다.
시스템에 비정상적인 상황이 발생
OutOfMemoryError
ThreadDeath
Checked Exception
catch나throws를 강요초기 라이브러리의 잘못된 예외 설계/사용
다른 언어에서는 체크 예외를 사용하는 경우가 드물다. 이에 따라 최신 자바 표준 API도 체크 예외 처리가 굉장히 드물어 지고 있는 추세이다.
만약
Exception의 종류를 자세히 파악해서 복구할 수 있는 상황이라면 대처할 수 있겠지만, 그것이 아니라면 적절한런타임 예외 처리를 하는 방식으로 갈 수 있다.
스프링에서 관심을 가지는 Exception의 철학
사용 기술에 따라 같은 문제에 대해 다른 종류에 예외 발생
예를 들어, A와 B의 라이브러리의 기술이 다르지만, 결국 같은IOException을 던지는 예외 처리 방식이라면 이것을 추상화하여 예외 번역이 필요하다.
DataAccessException과 예외 추상화
스프링에서 제공해주는 예외 번역 기능을 사용하여 많은 엔진들만의 예외들을 통일해둔 시스템을 이용할 수 있다.
서비스 추상화
트랜잭션 서비스 추상화
Toby's 추상화:
구현의 복잡함과 디테일을 감추고 중요한 것만 남기는 기법.
여러 인프라 서비스 기술의 공통적이고 핵심적인 기능을 인터페이스로 정의하고 이를 구현하는 어댑터를 만들어 일관된 사용이 가능하게 만드는 것이 서비스 추상화.
트랜잭션마다 코드나 기술이 다른데 이것을 추상화 하는 것이 있다.
그렇다면 클라이언트는 트랜잭션 기술이 변경될 때마다 코드를 변경해줘야 하는 것인가?
특정 기술에 종속되지 않는 공통적인 추상회된 메소드를 갖고 있는
PlatformTransactionManager라는 인터페이스가 있다.




