관리 메뉴

공부한것들을 정리하는 블로그 입니다.

토비의스프링3.1 8장. 스프링이란 무엇인가 본문

Spring/공부

토비의스프링3.1 8장. 스프링이란 무엇인가

호 두 2022. 7. 30. 00:05
반응형

토비의스프링 8장. 스프링이란 무엇인가
 - 스프링은 무엇일까? IoC와 DI 프레임워크로 제한하기엔 스프링이 너무 다재다능하다.

8.1 스프링의 정의

스프링의 가장 잘 알려진 정의는
 - 자바 엔터프라이즈 개발을 편하게 해주는 오픈소스 경량급 애플리케이션 프레임워크
 - 자바 엔터프라이즈란 JVM에서 동작하는 기업 운영에 필요한 기술들의 집합체라고 한다.

스프링의 특징들

애플리케이션 프레임워크
 - 애플리케이션 프레임워크란 특정 계층이나 기술, 업무에 국한되지 않고 애플리케이션 전 영역을 포괄하는 프레임워크를 말한다. 
 - 즉, 스프링의 목적은 AOP, DI/IoC 등 제공하는 다양한 기술에 프로그래밍 모델을 일관적으로 적용하여 각기 다른 자바 엔터프라이즈를 다룰 때 단일한 전략과 규칙으로도 편리하게 개발할 수 있도록 돕는 것이다.

경량급
 - 스프링은 불필요하게 무겁지 않다.
 - 과거의 자바의 주류 기술이였던 EJB는 개발환경, 운용서버, 빌드, 테스트, 코드 작성 모두를 무겁게 만들었다. 그리고 고가의 느리고 무거운 WAS가 필요했다. 
 - 그에 반해 스프링은 톰캣이나 제티같은 가벼운 WAS에서도 동작한다. 서블릿 컨테이너만으로도 충분히 동작하기 때문에 개발 과정도 단순해진다. 이런 측면에서 '경량급'이라 부를 수 있다.

자바 엔터프라이즈 개발을 편하게
 - 편리한 애플리케이션의 개발이란 것은, 로우레벨 기술에 많은 신경을 쓰지 않고도 핵심 비즈니스 로직을 빠르게 개발하는 것을 말한다고 한다. 
 - 스프링은 초기 기술 설정을 잘하고 나면 추후 스프링과 관련된 코드에 크게 신경쓸 필요가 없다.

오픈소스
 - 오픈소스의 특징으로, 스프링 또한 커뮤니티가 있으며 버그를 신고하거나 새 기능추가 요청을 자유롭게 할 수 있다.


8.2 스프링의 목적

왜 자바 엔터프라이즈 시스템 개발은 복잡할까?

복잡함의 원인
 - 기존 엔터프라이즈 프레임워크들이 실패했던 이유는, 비즈니스 로직과 엔터프라이즈 기술이라는 두 가지 복잡함이 얽혀있기 때문이다. 비즈니스 로직을 구현할 때 기술적인 문제까지 고려해야 하는 일이 많아졌다.

EJB는 왜 실패했는가?
 - EJB는 몇몇 기술적인 특징으로 두 가지 종류의 복잡함을 제거할 수 있었지만, EJB의 틀 안에서 코드를 작성하도록 강제했기 때문에 EJB의 환경과 스펙에 종속적으로 코드를 작성해야만 했다. 이로 인해 자바의 강점마저 잃어버렸다.

반면교사 : 스프링의 해결법
 - 스프링은 EJB의 전철을 밟지 않았다. EJB의 규약이 코드에 묻어나는 침투적인 기술의 단점을 해소하고자 했다.
 * 침투적인(invasive) : 특정 프레임워크의 규약 등이 코드에 묻어나는 것. 코드가 프레임워크에 종속적일 때.
 - 그에 비해 스프링은 non-invasive, 즉 비침투적인 방법을 취해 스프링 스스로가 애플리케이션의 비즈니스 로직을 담당하는 코드에 불필요하게 등장하지 않도록 했다. 
 - 성격이 다른 복잡함을 깔끔하게 분리할 수 있었다.

복잡함을 상대하는 스프링의 전략
 - 기술에 대한 일관적인 접근방법
   - 기술의 변화에 효과적으로 대응하기 위해 스프링은 서비스 추상화를 택했다. 
   - 기술적인 복잡함은 추상화를 통해 로우레벨의 복잡한 구현을 인터페이스 아래 숨기고, 환경과 세부 기술에 독립적인 인터페이스에 의존하도록 했다.
   - 템플릿/콜백 패턴으로 반복적인 작업 흐름과 API 사용을 반복하지 않도록 만들었다.
   
 - 기술과 관련된 코드와 비즈니스 로직의 핵심 코드와 분리하기
   - 비즈니스 로직 전후로 트랜잭션 경계를 설정하는 것을 비즈니스 로직과 분리하는 것을 책에서 다루었다. 
   - 책임에 따라 계층을 구분하더라도 근본적으로 책임이 다른 코드가 섞이는 것을 방지하기 어려운데, AOP로 이 문제를 해결했다.

 - 비즈니스/애플리케이션 로직의 복잡함 상대하기
   - 비침투적인 프레임워크를 만드려는 스프링의 노력 덕에 비즈니스 로직과 기술적인 코드가 분리될 수 있었다. 
   - 기술적인 부분에 문제가 발생했다면 서버 리셋이나 서버 증설등의 문제로 해결할 수 있지만, 비즈니스 로직에 문제가 있다면 계좌의 돈이 이유없이 줄어들거나 주식 주문이 체결로 이어지지 않는 불상사가 발생할 수도 있다.

 - 스프링의 핵심 도구 : 객체지향과 DI
   - 스프링의 AOP, 템플릿/콜백, 서비스 추상화 등은 DI에 기반을 두고 있으며, DI도 객체지향 설계위에 존재한다. 
   - DI를 사용하다보면 자연스럽게 객체지향적인 생각에 도달하게 해준다. 코드에서 어떤 것이 자주 바뀔 수 있을까? 성격이 다르고 변경의 이유가 다른건 무엇일까?를 찾게 되면 이러한 지점에서 오브젝트를 분리하고 인터페이스에 의존하며 DI로 주입받게 될 것이다.
   - 결국 스프링은 자바의 객체지향적 특성을 최대한 활용하기 위한 기술이다.


8.3 POJO 프로그래밍

그래서 POJO는 무엇일까?
 - 특정 규약(contract)에 종속되지 않는다.
 - 특정 환경에 종속되지 않는다.
 - 단일 책임 원칙을 지키는 클래스
위 원칙을 지키며 POJO에 핵심 로직을 담고 설계하는 방법을 POJO 프로그래밍이라 부를 수 있다.

POJO의 장점은 무엇일까?
 - 특정한 기술과 환경에 종속되는 코드가 사라져 깔끔하게 작성할 수 있고 디버깅과 테스트 자동화가 용이하다.
 - OOP, 도메인 모델, 디자인 패턴 등 객체지향적인 설계를 적용할 수 있다.


8.4 스프링의 기술
 - 기술과 비즈니스 로직의 분리는 스프링과 같은 POJO 프레임워크로 가능하다. 
 - 스프링에는 POJO 프로그래밍을 쉽게 할 수 있는 3가지 Enabling Technology를 제공하는데, 위의 스프링의 삼각형에서 소개된 IoC/DI, AOP, PSA이다. 
 - 스프링은 이 세 가지 기술을 자바 엔터프라이즈 개발의 전 영역에 자연스럽게 녹아들 수 있도록 프레임워크 형태로 제공된다.
이 세 가지 Enabling Technology가 목적이 아니라, POJO 기반의 개발을 편하게 해주는 도구라고 생각하면 좋다.


IoC/DI
 - 왜 두 개의 오브젝트를 분리해서 만들고, 인터페이스로 느슨하게 연결하여 프레임워크로 하여금 DI하여 사용하도록 만들까? 
 - '유연한 확장이 가능하게 하기 위해서' 라고 할 수 있다. 
 - SOLID 원칙 중 OCP는 확장에는 열려있지만(주입하는 빈은 구현이 바뀌거나 다른 클래스가 될 수 있음) 변경에는 닫혀있다(주입받는 클래스는 빈이 어떻게 바뀌든 변경의 이유가 생기지 않음)으로 설명할 수 있다.

주로 아래와 같이 활용가능하다.
 - 핵심 기능의 변경
   - 전략 패턴과 같이 의존하는 대상의 구현 클래스를 DI 설정의 변경을 통해 쉽게 변경할 수 있다.
 - 핵심 기능의 동적인 변경
   - DI는 런타임 시 한 번 의존 오브젝트를 연결하면 바뀌지 않지만 동적으로 의존 오브젝트를 바꿀 수 있다.
   - 다이나믹 라우팅 프록시나 프록시 오브젝트 기법을 활용하여 적용할 수 있다.
 - 부가기능의 추가
   - 데코레이터 패턴과 같이 인터페이스에 의존하고 사용할 구체 클래스 인스턴스를 DI 받도록 만들면 핵심 기능을 구현한 코드에 영향을 주지 않고 부가기능을 쉽게 부여할 수 있다.
 - 인터페이스의 변경
   - 어댑터 패턴을 적용할 수 있다. A가 C에 의존하는데, A는 B 인터페이스를 사용하도록 구현하였고 C는 B를 구현하지 않았을 때, B를 구현한 클래스를 만들어 내부에서 C를 호출하도록 하고 이 클래스를 DI하는 방식으로 적용할 수 있다.
 - 프록시
   - Lazy Loading이나 원격 오브젝트를 로컬의 오브젝트처럼 사용할 수 있도록 하는 원격 프록시를 적용하려고 할 때 프록시가 필요하며, DI로 이를 구현할 수 있다./
 - 템플릿과 콜백
   - 반복되는 로직과 변하는 로직을 템플릿과 콜백으로 분리하면 지저분한 반복을 줄일 수 있다.
 - 싱글톤과 오브젝트 스코프
   - 컨테이너가 DI할 오브젝트의 생성, 이용, 소멸, 관계설정, 생명주기를 관리할 수 있다. 그 중 생명주기는 싱글톤, HTTP Request당 하나의 오브젝트, HTTP Session당 하나의 오브젝트 등 다양한 스코프로 제어가 가능하다.
 - 테스트
   - 다른 오브젝트와 밀접하게 협력하거나 연관된 오브젝트를 테스트하는 좋은 방법은 고립시키는 것이다. 이 고립된 테스트를 위해 스텁이나 목 오브젝트 같은 테스트 대역을 주입하여 실제 환경이나 또는 오래 걸리는 작업을 배제한 채 테스트에 집중할 수 있다.


AOP
 - 객체지향 프로그래밍 패러다임이 현대의 복잡한 요구항과 기술적인 난해함을 해결하는데 한계가 있는데 이를 보조해주는 것이 AOP이다. 
 - AOP와 OOP는 대척점에 있는게 아니라, AOP가 OOP를 보조하여 더욱 OOP에 맞는 코드를 작성할 수 있도록 돕는다.

AOP를 적용하는 방법은 크게 두 가지로 분류할 수 있다.
 - 스프링과 같이 다이나믹 프록시를 사용하는 방법
   - 데코레이터 패턴을 응용하여 부가기능을 적용하도록 다이나믹 프록시를 이용할 수 있다. 
   - 스프링에서 구현할 수 있지만 부가기능을 부여할 수 있는 곳이 오로지 메서드 호출지점이라는 단점이 존재한다.
 - 자바 언어의 한계를 넘어서는 언어의 확장을 이용하는 방법
   - 다양한 조인포인트를 이용하기 위해선 AspectJ라는 유명한 AOP 오픈소스 라이브러리를 사용할 수도 있다. 
   - 메서드 호출, 인스턴스 생성, 필드 엑세스 등에도 부가 기능을 적용할 수 있다. 
   - 직접 바이트코드를 수정하기 때문에 AOP 변경사항이 존재할 때 마다 새로 컴파일을 해주어야 한다는 단점이 있다.

AOP를 적용하는 3단계
 - 스프링이 제공하는 AOP 이용
   - 스프링이 대표적으로 제공하는 AOP는 트랜잭션이다. 
   - 특정 아키텍쳐에서 @Configurable 애너테이션을 이용한 도메인 오브젝트에 DI를 자동적용 해주는 AOP도 스프링에서 제공하지만 AspectJ를 필요로 한다.
 - 전담팀을 이용한 정책 AOP 적용
   - 처음엔 보안, 로깅, 트레이싱, 성능 모니터링과 같은 정책적인 기능을 전담하는 소규모 팀에서 AOP를 전담하도록 한다.
 - AOP의 자유로운 이용
   - 개발자가 AOP에 익숙해졌다면 개발자가 구현하는 기능에 적용할 AOP를 이용하도록 한다. 
   - 작은 단위에서도 AOP로 분리하면 좋을 기능들이 존재하기 마련이다.

Portable Service Abstraction
   - PSA는 환경과 세부 기술의 변화에 관계없이 일관된 방식으로 기술에 접근할 수 있도록 한다. 
   - POJO 코드가 기술에 직접적으로 노출되어 만들어져서는 안된다는 의미이다.
   - 스프링이 정의한 트랜잭션 추상화 인터페이스인 PlatformTransactionManager를 통해 트랜잭션 기술을 이용한다면, 추후DB가 바뀌거나 하는 문제들에도 코드는 변하지 않고 제 역할을 해낼 것이다.


반응형
Comments