Spring
Spring Framework는 앞서 공부한대로 자바 기반의 웹 애플리케이션 개발을 위한 프레임워크이다.
객체지향적으로 개발할 수 있도록 도와주고, 애플리케이션을 빠르고 효율적으로 개발할 수 있도록 기본 틀과 공통 프로그래밍 모델, API 등을 제공한다.
- Spring Container
스프링은 스프링 컨테이너 또는 애플리케이션 컨텍스트라고 불리는 런타임 엔진을 제공하는데, 스프링 컨테이너는 설정 정보를 참고하여 애플리케이션을 구성하는 오브젝트(빈)을 생성하고 관리한다. 그리고 의존성을 갖는 객체에 대해 의존성 주입(Dependency Injection, DI)를 통해 두 객체의 결합도를 낮추도록 도와준다.
- 공통 프로그래밍 모델
스프링은 애플리케이션을 구성하는 객체(빈)이 생성되고 동작하는 틀을 제공해주며 코드를 어떻게 작성해야하는지에 대한 기준도 제공한다.
이를 일반적으로 프로그래밍 모델이라고 부르는데, 스프링에서는 크게 3가지 핵심 프로그래밍 모델을 지원하여 이에 맞춰 개발할 것을 권장하고 있다.
- IoC/DI
- 서비스 추상화
- AOP
IOC/DI
IoC(Inversion of Control)은 직역하자면 제어의 역전 이라는 뜻인데,
IoC를 적용하지 않은 코드를 보면
// 클라이언트가 직접 객체를 생성하는 코드
public class ClientWithoutIoC {
private final MyServiceImpl service = new MyServiceImpl();
public void execute() {
// 직접 생성한 객체를 사용
service.performOperation();
}
public static void main(String[] args) {
// 클라이언트가 직접 MyServiceImpl 객체를 생성
ClientWithoutIoC client = new ClientWithoutIoC();
client.execute();
}
}
객체의 생명주기(객체의 생성, 초기화, 소멸, 메서드 호출 등)를 클라이언트 구현 객체가 직접 관리한다.
반대로 IoC를 적용한 코드를 보면
// 서비스 인터페이스
public interface Service {
void performOperation();
}
// 구현 클래스
public class MyServiceImpl implements Service {
@Override
public void performOperation() {
System.out.println("Operation performed by MyServiceImpl");
}
}
// 클라이언트 클래스
public class Client {
private final Service service;
// 의존성 주입을 통해 Service 객체를 주입받음
public Client(Service service) {
this.service = service;
}
public void execute() {
// 제어의 역전: 클라이언트가 직접 객체를 생성하지 않음
service.performOperation();
}
public static void main(String[] args) {
// IoC 컨테이너에서 Service 객체를 주입받아서 클라이언트를 생성
Service myService = new MyServiceImpl();
Client client = new Client(myService);
client.execute();
}
}
이렇게 객체들의 동작은 우리가 직접 구현하기는 하지만, 해당 객체들이 어느 시점에 호출될 지는 신경쓰지 않는다. 단지 프레임워크가 요구하는대로 객체를 생성하면, 프레임워크가 해당 객체들을 가져다가 생성하고, 메소드를 호출,소멸시킨다. 즉, 클라이언트 클래스는 구현체가 구현된대로,시키는대로 행동할 수밖에 없고 이 말은 클라이언트의 제어권은 구현체에 있게된다.
쉽게 말해서 클라이언트 클래스는 게임패드고 각각의 객체는 게임이라고 생각하면 된다.
본인은 주어진 X,Y,O,△를 키를 누르지만 각 게임에 따라 같은 X키여도 공격버튼이 될 수도 있고, 축구게임의 패스버튼이 될 수 있듯이, 클라이언트가 어떤 행동을 제어하는 건 구현체에 달린것이다.
그리고 이런 설계 원칙을 수행하기 위한 디자인 패턴이
DI(Dependency Injection) 의존성 주입이다.
의존대상 B가 변하면, 그것이 A에 영향을 미친다.
아주 간단한 코드로 알아보면
public class A {
private B b = new B();
}
public class A {
private B b;
public A(B b) {
this.b = b;
}
}
두 코드 다 B가 변하면 A가 영향을 받는다
윗 코드는 클래스 내부에 직접 B를 생성해서 의존시키는 경우, 아래는 외부에서 생성자 주입으로 의존성을 주입시킨다.
다만 아래 코드는 의존 대상을 직접 생성(결정)하는 게 아닌 외부로부터 주입을 받음으로써, 만약 B를 인터페이스로 추상화하고 주입한다면 다양한 구현체가 들어옴으로써 의존성을 다각화 할 수 있다.
즉, 스프링에서 제공하는 IoC/DI를 적용함으로써 객체의 책임을 분리하고 협력하도록 하여 유연하고 확장성이 뛰어난 설계를 할 수 있다.
PSA
PSA(Portable Service Abstraction)
스프링을 사용하면 서비스 추상화를 통해 특정 환경이나 서버, 기술에 종속되지 않으며 유연한 애플리케이션을 개발할 수 있다. 스프링에서는 추상화 계층을 통해 구체적인 기술과 환경에 종속되지 않도록 한다. 예를 들어 MyBatis나 JPA 등 세부 기술에 종속적인 에러들을 추상화하여 기술에 종속적이지 않은 에러들로 처리할 수 있도록 도와준다.
스프링을 자세히 공부하다 보면 추상화를 위해 프록시(Proxy) 패턴과 같은 디자인 패턴이 매우 자주 사용됨을 파악할 수 있다.
AOP
AOP(Aspect Oriented Programming, 관점 지향 프로그래밍)는 애플리케이션에 공통적으로 나타나는 부가적인 기능들을 독립적으로 모듈화하는 프로그래밍 모델이다. 애플리케이션의 요구 사항이 점점 복잡해져가고, 기술적인 난해함이 더해지면 모든 책임과 관심사를 분리하는 것이 상당히 어렵다. 그래서 스프링은 AOP를 지원하여 다양한 엔터프라이즈 서비스를 적용하고도 책임을 분리하여 깔끔한 코드를 유지할 수 있고, 객체지향스럽게 개발할 수 있도록 도와준다.
예를 들어 비즈니스 로직과 트랜잭션 관리를 위한 로직이 결합된다면 로직이 중복되고, 여러 책임을 갖는 등의 단점이 존재하게 된다. Spring에서는 AOP를 적용하여 @Transactional이라는 선언적 트랜잭션 기능을 구현하여 큰 장점을 누릴 수 있도록 도와준다.
계층형 아키텍쳐와 3가지 계층
계층형 아키텍쳐와 3가지 계층
관심, 책임, 성격 등이 서로 다른것들을 분리하면 분리된 각 요소의 응집도가 높아지고 결합도는 낮아진다. 만약 서로 다른 모듈을 분리하지 않으면 1가지의 변경 사항에 대해 다른 요소들까지 영향을 받을 수 있어 이러한 문제를 해결하고자 계층을 3가지로 나누었다.
1.Presentation Layer(프레젠테이션 계층)
클라이언트로부터 HTTP 요청을 수신하고 그에 맞는 응답을 돌려주는 계층
이 계층에서는 어떠한 요청을 받고, 어떠한 응답상태와 데이터를 반환하는지에 대한 책임이 있다.
즉, 우리가 항상 사용하는 @Controller, @RestController를 사용 함으로써 프레젠테이션 계층이라고 명시할 수 있다.
2.Service Layer(서비스 계층)
요구사항에 맞게 비지니스 로직을 작성하는 계층
그렇기 때문에 서비스의 핵심 로직이 주로 담겨있는데, @Service를 사용함으로써 서비스 계층으로 명시할 수 있다.
3.Data Access Layer(데이터 접근 계층)
데이터를 저장하거나 조회하기 위해 DB에 접근하는 계층
@Repository를 사용함으로써 데이터 접근 계층으로 명시
이렇게 각 계층은 자신의 계층이 갖는 책임에만 충실하도록 개발해야한다.
흔히 저지르는 실수 중 하나가 프레젠테이션 계층에 종속적인 객체를 그대로 서비스 계층으로 전달하는 것인데 HttpServeletRequest/Response같은 객체들은 서비스계층에 넘기지 않는것이 좋다.
'SPRING' 카테고리의 다른 글
SpringBoot의 JPA - (spring - 7) (0) | 2023.12.23 |
---|---|
영속성 컨텍스트 - (spring - 6) (0) | 2023.12.23 |
Spring MVC - (spring - 4) (0) | 2023.12.22 |
HTTP란 무엇일까 - (spring - 3) (0) | 2023.12.22 |
Spring과Spring Boot의 간략한 차이점 - (spring - 2) (0) | 2023.12.22 |