Backend
Frontend
Database & Infra
Project
codesche’s blog
/
Education
/
토비의 스프링 6
/
토비의 스프링 6
Backend
Frontend
Database & Infra
Project
codesche’s blog
/
Education
/
토비의 스프링 6
/
토비의 스프링 6
Share
Backend
Frontend
Database & Infra
Project
토비의 스프링 6
토비의 스프링 6
Search
오브젝트와 의존관계
Spring 개념, 이론
•
관심사의 분리 (Separation of Concerns - SoC)
◦
관심사 - 변경이라는 관점에서 설명할 수 있음
•
메소드 추출 - option + command + m
•
참고정보
◦
환율 API 활용 사이트
https://open.er-api.com/v6/latest/USD
관심사의 분리
•
하나의 클래스 안에 두 가지 관심사가 여전히 남아있다는 문제를 확인한 이후 좀 더 유연하게 확장하여Payment 서비스 자체는 재사용이 가능하도록 개선하는 작업을 수행
상속을 통한 확장
•
상속을 통해서 클래스 계층 구조 하나를 유지하는 게 아니고 클래스를 안전하게 분리시킨다.
•
Payment를 준비하는 클래스와 환율 정보를 가져오는 클래스를 완전히 독립적인 클래스로 만든다.
클래스의 분리
•
상속이 가진 문제 때문에 클래스를 분리함
•
상속을 쓰지 않고 이름을 통일하고 싶은 경우 →
인터페이스 도입
인터페이스 도입
•
PaymentService - ExRateProvider, WebApiExRateProvider 의존
◦
new WebApiExRateProvider ⇒ 관계설정 책임의 분리라고 말한다.
◦
PaymentService를 수정하지 않고 재사용할 수 있는 방법
▪
앞에 하나를 더 만들면 된다. (Client → PaymentService …)
▪
런타임 의존관계를 앞으로 옮긴다.
관계설정 책임의 분리
•
Client는 두 개의 관심사를 가지고 있다. ⇒ 분리가 필요함
•
웹 같은 경우 해당 Client가 컨트롤러가 될 수도 있다.
•
관심사 분리 - 다음과 같이 분리한다.
•
Client가 사용할 PaymentService를 얻어온다. (ObjectFactory 생성)
오브젝트 팩토리
•
개방 폐쇄 원칙(Open-Closed Principle-OCP
)
◦
클래스나 모듈은 확장에는 열려 있어야 하고 변경에는 닫혀 있어야 한다.
•
높은 응집도와 낮은 결합도(High Coherence and low coupling)
◦
응집도가 높다는 것은 하나의 모듈이 하나의 책임 또는 하나의 관심사에 집중되어 있다는 의미.
◦
변화가 일어날 때 해당 모듈에서 변하는 부분이 크다. ⇒ 변경 비용이 적게 든다.
◦
책임과 관심사가 다른 모듈과는 낮은 결합도, 즉 느슨하게 연결된 형태를 유지하는 것이 바람직하다.
•
전략 패턴
◦
자신의 기능 맥락(context)에서, 필요에 따라 변경이 필요한 알고리즘을 인터페이스를 통해 통째로 외부로 분리시키고, 이를 구현한 구체적인 알고리즘 클래스를 필요에 따라 바꿔서 사용할 수 있게 하는 디자인 패턴
•
제어의 역전(Inversion of Control)
◦
제어권 이전을 통한 제어관계 역전 - 프레임워크의 기본 동작 원리
원칙과 패턴
•
DI(Dependency Injection) - 의존관계 주입(의존관계를 외부에서 주입해준다)
•
현재 코드 구조 상황
◦
여기서 ObjectFactory → BeanFactory로 바꿔서 생각
◦
Bean: 오브젝트라고 바꿔서 생각해도 상관없음 (어플리케이션 담당하고 제공하는 클래스의 오브젝트)
◦
오브젝트(Object) 팩토리 = 빈 팩토리(Bean Factory)
◦
빈(Bean) - PaymentService, WebApiExRateProvider
◦
구성정보(Configuration): 빈 클래스, 의존관계
•
현재 진행 상황
스프링 컨테이너와 의존관계 주입 (DI)
•
스프링 컨테이너가 하는 역할
•
스프링은 많은 경우 그 안에서 생성하고 구성하는 오브젝트들을 싱글톤으로 만든다.
•
하나를 만들어서 여러 사용자에 걸쳐서 공유할 수 있도록 만들어준다.
•
스프링 안에서 만들어지는 Bean 오브젝트는 딱 한 개 즉, 스프링은 싱글톤 레지스트리 역할을 한다. (스프링 안에서 만들어지는 빈 오브젝트는 딱 한 개만 만들어져서 이 빈 프로젝트를 사용하는 다른 오브젝트가 여러 개가 된다 할지라도 동일반 오브젝트가 사용된다!)
싱글톤 레지스트리
•
오브젝트 합성을 이용하는 디자인 패턴을 적용할 때 스프링의 의존관계 주입(Dependency Injection)을 사용한다.
•
데코레이터(Decorator) 디자인 패턴
◦
오브젝트에 부가적인 기능/책임을 동적으로 부여한다.
◦
현재 코드 구조
◦
데코레이터 디자인 패턴 적용 후
DI와 디자인 패턴
의존성 역전 원칙 (Dependency Inversion Principle)
•
상위 수준의 모듈은 하위 수준의 모듈에 의존해서는 안 된다. 둘 모두 추상화에 의존해야 한다.
•
추상화는 구체적인 사항에 의존해서는 안 된다. 구체적인 사항은 추상화에 의존해야 한다.
•
모듈:
◦
전체 시스템을 작은 단위로 쪼개놓은 것이다.
◦
자바에서는 패키지가 모듈을 설명해준다.
•
현재 모듈 구성도
의존성 역전 원칙
수동 테스트의 한계
•
프린트된 메시지를 수동으로 확인하는 방법은 불편하다.
•
사용자 웹 UI까지 개발한 뒤에 확인하는 방법은 테스트가 실패했을 때 확인할 코드가 많다.
•
테스트할 대상이 많아질 수록 검증하는데 시간이 많이 걸리고 부정확함.
작은 크기의 자동 수행되는 테스트(Automated Test)
•
개발자가 만드는 테스트 - 매우 중요!
◦
개발자가 코드를 만든다.
•
개발한 코드에 대한 검증 기능을 코드로 작성한다.
•
자동으로 테스트를 수행하고 결과를 확인한다.
•
테스팅 프레임워크를 활용한다.
•
테스트 작성과 실행도 개발 과정의 일부이다.
자동으로 수행되는 테스트
•
JUnit 5
◦
메소드에 테스트라는 애노테이션을 붙인다 (@Test 테스트 메소드)
◦
@BeforeEach 테스트
▪
각 테스트 전에 실행된다
▪
모든 테스트에 공통으로 필요한 준비가 있다면 이것을 실행한다.
◦
테스트마다 새로운 인스턴스가 만들어진다.
JUnit 테스트 작성
요구사항 정리
PaymentService 테스트
문제점
1.
우리가 제어할 수 없는 외부 시스템에 문제가 생기면?
2.
ExRateProvider가 제공하는 환율 값으로 계산한 것인가?
3.
환율 유효 시간 계산은 정확한 것인가?
테스트의 구성 요소
•
테스트 대상 (SUT - System Under Test)
•
테스트 오브젝트 참여
•
어떤 경우에는 협력자(Collaborator)들이 붙기도 한다.
외부에 제약을 덜 받게 해주는 방법 - 의존관계 주입하여 진행
PaymentService 테스트 문제점
•
해당 테스트 코드의 문제
◦
직접 제어할 수 없는 외부의 API를 이용하는 기능이 테스트를 수행하는 동안에 발생한다.
◦
우리가 제어할 수 있는 클래스로 바꾼다.
테스트와 DI (1)
수동 DI를 이용하는 테스트
•
테스트용 협력자(Collaborator)/의존 오브젝트를 테스트 대상에 직접 주입하고 테스트
스프링 DI를 이용하는 테스트
•
테스트용 협력자(Collaborator)/의존 오브젝트를 스프링의 구성 정보를 이용해서 지정하고 컨테이너로부터 테스트 대상을 가져와서 테스트
◦
@ContextConfiguration
◦
@AutoWired
테스트와 DI (2)
학습 테스트
•
직접 만들지 않은 코드, 라이브러리, 레거시 시스템에 대한 테스트
•
테스트 대상의 사용방법을 익히고 동작방식을 확인하는데 유용함
•
외부 기술, 서비스가 버전이 올라갔을 때 이전과 동일하게 동작 하는지 확인할 수 있음
•
클럭에 대한 학습 테스트 적용
학습 테스트(Learning Test)
Clock을 이용한 시간 테스트
•
도메인 모델 아키텍처 패턴
◦
도메인 로직, 비즈니스 로직을 어디에 둘 지를 결정하는 패턴
▪
트랜잭션 스크립트 - 서비스 메소드(PaymentService.prepare)
▪
도메인 모델 - 도메인 모델 오브젝트 (Payment)
정리 - 개발자가 만드는 테스트
•
개발한 코드에 대한 검증 기능을 코드로 작성
•
자동으로 테스트를 수행하고 결과를 확인
•
테스팅 프레임워크를 활용
•
테스트 작성과 실행도 개발 과정의 일부
도메인 오브젝트 테스트
•
개방 폐쇄 원칙(OCP)
◦
클래스나 모듈은 확장에는 열려 있어야 하고 변경에는 닫혀 있어야 한다.
◦
변화의 특성이 다른 부분을 구분하고 각각 다른 목적과 이유에 의해 다른 시점에 독립적으로 변경될 수 있는 효율적인 구조를 만들어야 한다.
•
템플릿
◦
코드 중에서
변경이 거의 일어나지 않으며 일정한 패턴으로 유지되는 특성을 가진 부분
을
콜백(자유롭게 변경되는 성질을 가진 부분)
으로부터 독립시켜서 효과적으로 활용할 수 있도록 하는 방법
다시 보는 개방 폐쇄 원칙
•
리팩터링의 전제 - 버그가 생기면 안 된다!
•
리팩터링을 잘하려면 테스트를 잘 만들어주어야 한다!
WebApiExRateProvider 리팩터링
•
WebApiExRateProvider의 구성
◦
URI를 준비하고 예외처리를 위한 작업을 하는 코드
◦
API를 실행하고, 서버로부터 받은 응답을 가져오는 코드
◦
JSON 문자열을 파싱하고 필요한 환율정보를 추출하는 코드
•
메소드 추출
변하는 코드 분리하기 - 메소드 추출
•
템플릿(Template)
◦
템플릿은 어떤 목적을 위해 미리 만들어둔 모양이 있는 틀.
◦
고정된 틀 안에 바꿀 수 있는 부분을 넣어서 사용하도록 만들어진 오브젝트.
◦
템플릿 메소드 패턴도 템플릿을 사용.
•
템플릿 메소드 패턴?
◦
템플릿 메소드 패턴은 고정된 틀의 로직을 가진 템플릿 메소드를 슈퍼클래스에 두고, 바뀌는 부분을 서브클래스의 메소드에 두는 구조로 이루어진다.
•
메소드 추출 후 코드
변하지 않는 코드 분리하기 - 메소드 추출 (템플릿의 탄생)
Load more