[Spring 3.1] 관심사의 분리와 스프링
추후 유지 보수를 고려했을 때 관심사 (도메인) 를 작업 단위로 소스코드를 분리해서 작성하는 편이 합리적이다.
이런 측면에서 추상 클래스와 인터페이스는 매우 중요하다.
확장성 있는 애플리케이션을 구현하기 위해 디자인패턴 중 템플릿 메서드 패턴을 사용한다.
abstract class Car {
public void doorOpen() { }
public abstract void drive() { }
}
class ACar extends Car {
public void drive() {...}
}
슈퍼 클래스에 기본적인 로직을 만들어 놓고, 일부 기능을 추상 메서드로 만든다.
이후 서브 클래스에서 해당 메서드를 필요에 따라 구현해서 사용하도록 하는 패턴이다.
변화의 성격이 다른 것들을 분리해서 서로 영향을 주지 않은 채로 독립적으로 변경할 수 있도록 설계해 추후 프로젝트의 유지 보수나 고도화 작업을 쉽게 수행하자.
관심사와 도메인에 따라 코드를 분리하고, 분리하는 과정에서 여러 가지 디자인 패턴을 사용한다.
궁극적인 목적을 기억하자. 핵심은 확장성 있는 프로그램의 설계이다.
관심사의 깔끔한 분리를 위해 인터페이스를 사용한다.
프로젝트를 진행할 때, 데이터베이스 연결 부분만 따로 분리해서 진행한다고 생각 해 보자.
상속이나 다른 클래스로 분리해서 진행한다면 의존성 문제가 발생해 좋은 방법이 아니다.
해당 그림처럼 인터페이스를 도입하고 프로젝트에 적합한 구현체를 구현하면 프로젝트 클래스에서 구현체 클래스에 의존하지 않고 적합한 기능을 사용할 수 있게 된다.
완벽한 분리를 위해 프로젝트 클래스의 생성자에서 어떤 구현체를 사용할 지 정해주도록 설정하자. (해당 클래스를 사용하는 클라이언트가 결정하게 된다)
프로젝트 클래스의 클라이언트는 팩토리를 호출해 원하는 객체를 반환받도록 설계하자.
이제 데이터베이스 설정 관련 부분이 변경하더라도 프로젝트 클래스를 변경할 필요가 없어진다.
완성된 다이어그램은 위와 같은 형태를 가진다.
팩토리는 프로젝트 클래스의 생성자를 통해 원하는 데이터베이스 연결을 가져오고 클라이언트에게 해당 객체를 반환한다.
애플리케이션의 컴포넌트 역할을 하는 오브젝트와 구조를 결정하는 오브젝트를 분리했다.
객체지향 원칙 중 하나인 OCP (Open Closed Principle) 는 확장에는 열려 있고 변경에는 닫혀 있음을 의미한다.
위에서 작성한 프로젝트 클래스도 데이터베이스 연결에 대한 부분은 열려 있고 이 외 다른 기능을 함께 변경할 필요가 없기에 객체지향 원칙을 잘 지켰다고 할 수 있다.
IoC (Inversion of Control) 는 제어의 역전으로, 오브젝트를 제어 권한을 가지는 특별한 오브젝트에 의해 결정하는 방식이다.
라이브러리와 프레임워크의 차이도 IoC에 있다.
라이브러리는 IoC가 적용되지 않는다. 동작하는 중 필요한 기능이 있으면 능동적으로 라이브러리를 활용하는 방식으로 흘러간다.
프레임워크는 IoC가 적용된다. 애플리케이션 코드는 프레임워크에 의해 사용돼 흐름을 주도한다.
위에서 언급한 팩토리 패턴도 IoC 개념이 적용돼있다.
오브젝트를 만드는 제어권을 팩토리에게 위임해 프로젝트 클래스는 수동적으로 작동한다.
스프링은 IoC 컨테이너이다.
스프링 프레임워크에서는 스프링이 제어권을 가지고, 다루는 오브젝트를 빈이라고 부른다.
빈들을 관리하는 IoC 오브젝트를 빈 팩토리 또는 애플리케이션 컨텍스트라고 부르고, 빈의 생성과 제어 관련 작업을 총괄한다.
@Configuration
public class Factory {
@Bean
public DBConnect connect() {
...
}
}
ApplicationContext ctx = new AnnotationConfigApplicationContext(Factory.class);
DBConnect dc = ctx.getBean("DBConnect", DBConnect.class);
직접 만든 클래스를 애플리케이션 컨텍스트로 활용하려면 @Configuration 애너테이션과 @Bean 애너테이션을 사용한다.
설정 클래스에 @Configuration 애너테이션을, 오브젝트를 만들어 주는 메서드에 @Bean 애너테이션을 붙인다.
이후 ApplicationContext의 getBean 메서드를 사용해 오브젝트를 가져올 수 있다. (빈 이름과 클래스를 사용한다)
@Configuration 애너테이션이 붙은 클래스는 애플리케이션 컨텍스트가 설정 정보로 활용할 수 있다.
위와 같이 자바 코드의 애너테이션을 기반으로 해서 설정을 진행할 수도 있고, XML을 따로 정의해서 설정을 진행할 수 있으니 두 방법 모두 적절히 사용해주자.
스프링이 IoC 컨테이너로 동작해 싱글톤 레지스트리, 오브젝트 생성 후처리 등 구현하기 까다로운 기능들을 편하게 사용할 수 있도록 도와준다.
IoC 방식의 핵심은 DI (Dependency Injection) 이다.
A가 B에 의존한다면, B가 변할 때 A도 함께 변해야 한다. (반대는 성립하지 않는다)
DI 는 런타임 시점에서 의존관계가 컨테이너에 의해 결정되고, 사용할 오브젝트에 대한 레퍼런스를 외부에서 주입함을 의미한다. (인터페이스 타입을 사용해야 하고, 주입받는 대상과 주입하는 대상 모두 빈으로 등록되어야 한다)
DL (Dependency Lookup) 과 다름에 유의하자.
의존관계 검색의 예시로는 애플리케이션 컨텍스트가 제공하는 getBean이 있다.
public class ProjectClass {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Factory.class);
dbconnection = ctx.getBean("dbconnection", DBConnect.class);
}
미리 정해놓은 이름을 전달해서 이름에 해당하는 오브젝트를 찾는 방식으로 작동한다.
이 때 ProjectClass 클래스는 빈으로 등록되지 않아도 괜찮다.
자신이 사용할 오브젝트에 대한 제어를 외부로 넘기고 자신은 수동적으로 주입받는 오브젝트를 사용하기에 DI는 IoC의 개념에 잘 들어맞는다. (스프링을 DI 컨테이너라고도 부른다)
DI를 사용해 애플리케이션을 유연하고 편하게 확장할 수 있다.
스프링은 오브젝트가 어떻게 설계되고 어떻게 서로 관계를 맺고 사용되는지에 집중하는 프레임워크이다.
스프링의 도움을 받아 오브젝트를 어떻게 분리하고 설계할 지 고민하자.
'Spring > Spring 3.1' 카테고리의 다른 글
[Spring 3.1] Aspect Oriented Programming (0) | 2023.04.28 |
---|---|
[Spring 3.1] 트랜잭션과 서비스 추상화 (0) | 2023.04.23 |
[Spring 3.1] 스프링과 예외처리 (0) | 2023.04.20 |
[Spring 3.1] 템플릿과 콜백 (0) | 2023.04.19 |
[Spring 3.1] 스프링과 테스트 (0) | 2023.04.16 |
댓글
이 글 공유하기
다른 글
-
[Spring 3.1] 트랜잭션과 서비스 추상화
[Spring 3.1] 트랜잭션과 서비스 추상화
2023.04.23 -
[Spring 3.1] 스프링과 예외처리
[Spring 3.1] 스프링과 예외처리
2023.04.20 -
[Spring 3.1] 템플릿과 콜백
[Spring 3.1] 템플릿과 콜백
2023.04.19 -
[Spring 3.1] 스프링과 테스트
[Spring 3.1] 스프링과 테스트
2023.04.16