토비의 스프링 Vol.1 - 9장 스프링 프로젝트 시작하기

2020-11-03

스프링 프로젝트 시작하기

자바 엔터프라이즈 플랫폼과 스프링 애플리케이션

스프링으로 만들 수 있는 애플리케이션의 종류에는 제한이 없다. 자바 언어를 사용하는 모든 종류의 프로젝트라면 어디든 사용할 수 있다. 웹을 이용하는 자바 엔터프라이즈 시스템 개발, 스윙이나 이클립스 RCP로 만드는 독립형 프로그램, 사용할 수 있는 기능에 제한이 있기는 하겠지만 애플릿이나 모바일 애플리케이션 개발에도 이용할 수 있다.

그러나 스프링은 주로 자바 엔터프라이즈 환경에서 동작하는 애플리케이션을 개발하는 목적으로 사용된다. 자바 엔터프라이즈 애플리케이션은 서버에서 동작하며 클라이언트를 상대로 서비스를 제공하도록 되어 있다. 즉 클라이언트의 요청을 받아서 그에 대한 작업을 수행하고 그 결과를 돌려주는 것이 기본적인 동작 방식이다.

클라이언트와 백엔트 시스템

엔터프라이즈 애플리케이션은 자신이 클라이언트가 돼서 또 다른 엔터프라이즈 시스템에 서비스를 요청할 수도 있다. 또는 데이터베이스나 레거시 시스템 같은 엔터프라이즈 정보 시스템(EIS)이라고 불리는 백엔드 시스템의 기능을 이용해 동작하기도 한다.

가장 많이 사용되는 구조는 클라이언트가 웹 브라우저이고 백엔드 시스템이 DB인 구성이다. 간단히 ‘DB를 사용하는 웹 애플리케이션’이라고 한다.

스프링 엔터프라이즈 애플리케이션이 이용하는 백엔드 시스템으로는 DB는 물론이고 메시징 서버, 메일 서버, 메인프레임도 가능하다. 자바가 제공하는 접속 방식을 지원하는 시스템이면 된다. 웹 서비스를 제공하는 서버도 자주 사용된다.

애플리케이션 서버

스프링으로 만든 애플리케이션을 자바 서버환경에 배포하려면 JavaEE(또는 J2EE) 서버가 필요하다. JavaEE 표준을 따르는 애플리케이션 서버는 크게 두 가지로 구분할 수 있다. 하나는 JavaEE의 대부분의 표준 기술을 지원하고 다양한 형태의 모듈로 배포가 가능한 완전한 웹 애플리케이션 서버(WAS)이고, 다른 하나는 웹 모듈의 배포만 가능한 경량급 WAS 또는 서블릿/JSP 컨테이너다.

  • 경량급 WAS/서블릿 컨테이너
    • 스프링은 기본적으로 톰캣이나 제티같은 가벼운 서블릿 컨테이너만 있어도 충분하다.
  • WAS
    • 고가의 WAS를 사용하면 성능 면에서는 대단히 낫지 않더라도 미션 크리티컬한 시스템에서 요구하는 고도의 안정성이나 고성능 시스템에서 필수적인 안정적인 리소스 관리, 레거시 시스템의 연동이나 기존 EJB로 개발된 모듈을 함께 사용하는 등의 필요가 있을 때 등에서 큰 장점이 있다.
      스프링소스 tcServer

      실제로 개발환경과 운영환경에서 가장 많이 사용되는 자바 서버는 웹 모듈만 지원하는 서블릿 컨테이너인 아파치 톰캣이다. 스프링 개발을 책임지고 있는 기업인 스프링소스에는 아파치 프로젝트인 HTTPD 서버와 톰캣의 핵심 개발자들이 포진해 있다. 톰캣 전문가인 이들이 중심이 돼서 톰캣을 기반으로 엔터프라이즈 스프링 애플리케이션에 최적화된 경량급 애플리케이션 서버인 tcServer를 개발했다. tcServer를 이용하면 기존 톰캣에서는 아쉬웠던 고급 서버 관리 기능, 배포 기능과 진단 기능을 포함해서 톰캣 전문가에게 받는 기술지원도 함께 제공받을 수 있다. 고급 WAS를 구매하는 데 비싼 비용을 들이기는 부담스럽고, 그렇다고 운영하고 관리하기 불편한데다 필요할 때 기술지원도 받을 길이 없는 오픈소스 제품인 톰캣을 그대로 사용하기는 불안하다면 tcServer가 좋은 대안이다.

      스프링 애플리케이션의 배포 단위

      1. 독립 웹 모듈
      
    • 스프링은 보통 war로 패키징된 독립 웹 모듈로 배포된다. 톰캣 같은 서블릿 컨테이너를 쓴다면 독립 웹 모듈이 유일한 방법이다. 2. 엔터프라이즈 애플리케이션
    • 확장자가 ear인 엔터프라이즈 애플리케이션으로 패키징해서 배포할 수도 있다. 하나 이상의 웹 모듈과 별도로 분리된 공유 가능한 스프링 컨텍스트를 엔터프라이즈 애플리케이션으로 묶어주는 방법이다. 3. 백그라운드 서비스 모듈
    • rar 패키징 방법. rar는 리소스 커넥터를 만들어 배포할 때 사용하는 방식인데, 만약 스프링으로 만든 애플리케이션이 UI를 가질 필요는 없고 서버 내에서 백그라운드 서비스처럼 동작할 필요가 있다면 rar 모듈로 만들어서 배포할 수 있다.

      운영 플랫폼이나 서버의 종류는 개발 중에라도 언제든지 필요에 따라 변경이 가능하다. 다만 특정 서버환경에서만 제공하는 기능을 사용한다면 변경이 힘들 수도 있다. 장기적으로 서버를 변경하거나 서버의 종류를 바꿀 가능성이 있다면, 서버의 기능에 종속되지 않도록 주의하거나 손쉽게 다른 서버의 기능으로 변경 가능하도록 추상화해서 사용해야 한다.


개발도구와 환경

JavaSE와 JavaEE

JavaSE/JDK

스프링 3.0은 JavaSE 5 버전에서 추가된 새로운 언어와 문법의 특징을 최대한 활용해서 개발됐기 때문에 기본적으로 JDK 5.0 또는 그 이상을 필요로 한다.

JavaEE/J2EE

스프링 3.0이 사용될 자바 엔터프라이즈 플랫폼으로는 J2EE 1.4 버전이나 JavaEE 5.0이 필요하다.

IDE

스프링 애플리케이션은 자바 5 또는 그 이상의 언어를 지원하는 자바 개발도구와 스키마를 지원하는 XML 편집기 정도만 있다면 어떤 개발환경에서든지 불편 없이 개발이 가능하다. 여기에 ANT나 Maven 같은 빌드 툴을 지원하고 톰캣이나 자바 서버로 바로 배포해서 실행해볼 수 있는 환경이라면 더할 나위 없다.

SpringSource Tool Suite

스프링 애플리케이션 개발을 위한 IDE로 이클립스를 선택했다면, 스프링 개발업체인 스프링소스가 직접 만들어 제공하는 이클립스의 확장판인 SpringSource Tool Suite(STS)를 사용할 수 있다.

STS는 최신 이클립스를 기반으로 주요한 스프링 지원 플러그인과 관련 도구를 모아서 스프링 개발에 최적화되도록 만들어진 IDE다. 이클립스와 같이 플러그인 방식을 지원하는 툴을 사용하면 원하는 기능을 필요에 따라 추가할 수 있다는 장점이 있다. 반면에 각 플러그인과 이클립스의 버전을 호환하도록 계속 관리해야 하는 불편한 점도 있다. 그렇기 때문에 스프링소스가 제공하는, 플러인 조합이 완료된 STS를 사용하는 편이 여러모로 유리하다.

SpringIDE 플러그인

SpringIDE는 스프링 개발에 유용한 기능을 제공하는 플러그인의 모음이다. 스프링 프로젝트와 설정파일 생성 위저드, 편리한 스프링의 XML 설정파일 에디터, 빈의 의존관계 그래프, 네임스페이스 관리 기능 등의 편리한 기능과 도구를 제공한다.

SpringIDE의 XML 에디터의 자동완성 기능
  • 빈 클래스 이름 자동완성
    • bean 태그의 class 애트리뷰트를 입력할 때 클래스 이름에 대한 자동완성을 지원한다. 카멜케이스 클래스 이름의 각 단어 첫 글자를 따서 입력하거나 클래스 이름 앞부분 몇 글자를 입력하고 Ctrl+Space Bar 키를 함께 눌러주면 된다.
    • 빈의 프로퍼티를 등록할 때도 수정자를 가진 클래스라면 property 태그의 name 부분에서 아무것도 입력하지 않은 채로 Ctrl+Space Bar를 눌러주면 클래스가 가진 프로퍼티 목록을 전부 볼 수 있다. 처음 한두 글자를 입력하고 찾으면 더 빨리 찾을 수 있다.
    • 마찬가지로 ref 애트리뷰트로 다른 빈을 참조할 때도 자동완성 기능을 사용할 수 있다.
  • 빈 설정 오류 검증 기능
    • 개발 중에 클래스나 프러퍼티 이름이 변경됐거나 XML 파일을 직접 수정하다가 주요한 이름을 잘못 건드린 경우에 빈 설정 오류검증 기능이 도움이 된다.
    • 빈 설정 내용을 작업하다가 존재하지 않는 클래스 이름을 넣거나 잘못된 프러퍼티 이름을 지정하면 바로 오류마크를 보여줘서 문제가 있음을 확인시켜준다.
  • 프로젝트 생성, 설정파일 생성, 빈 등록 위저드
    • 스프링 프로젝트 생성을 위해 스프링 프로젝트 위저드를 이용할 수 있다.
    • XML 설정파일 생성 위저드는 번거로운 스키마 선언부를 손쉽게 추가하거나 수정할 수 있게 해준다. 간단히 십여 개의 스프링 스키마/네임스페이스 중에서 원하는 것을 선택해 한 번에 XML 설정파일에 적용할 수 있다.
    • 빈을 등록할 때 XML을 직접 편집해서 입력하는 대신 위저드 방식으로 빈을 등록할수도 있다.
  • 빈 의존관계 그래프
    • SpringIDE는 XML 설정파일을 읽어서 자동으로 그래프를 그려준다. 각 빈이 서로 어떻게 참조하고 있는지, 어떤 프로퍼티를 갖고 있는지를 한눈에 볼 수 있다.
  • AOP 적용 대상 표시
    • AOP가 어려운 이유는 부가기능을 담은 어드바이스가 어느 오브젝트에 적용될지 한 눈에 보이지 않기 때문이다.
    • STS에는 SpringIDE 외에도 AJDT라는 AspectJ 개발플러그인이 함께 설치된다.
    • 이 AJDT의 지원으로 SpringIDE는 포인트컷이 적용되는 대상 빈을 설정파일 안에서 한눈에 확인할 수 있도록 해준다.
  • 기타 지원 기능
    • SpringIDE는 스프링 포트폴리오 프레임워크에 대한 지원을 포함한 다양한 기능을 제공한다.
      STS 플러그인

      STS 플러그인은 스프링 개발과 설정파일 편집을 지원하는 SpringIDE에 더해서 스프링 애플리케이션의 서버 배치와 같은 추가 기능을 제공해준다. STS는 대부분의 최신 JavaEE 서버로의 배치는 물론이고 스프링에 최적화된 애플리케이션 서버인 tcServer 그리고 OSGi 플랫폼인 dmServer, 스프링 기반의 클라우드 서비스인 스프링소스 Cloud Foundry로 배치할 수 있는 기능을 제공해준다. 그 밖에도 VMForce와 같은 VMWare 가상화와 클라우드 서비스에도 손쉽게 스프링 애플리케이션을 배치할 수 있도록 지원해준다.

      기타 플러그인
  • M2Eclipse
    • 자바의 대표적인 빌드 툴의 하나인 Maven을 지원하는 이클립스 플러그인이다. Maven은 특히 의존 라이브러리 관리에 뛰어나다. 외부의 리포지토리에 번들이라고 불리는 라이브러리와 의존정보를 두고 이를 프로젝트 모델 정보를 이용해 손쉽게 가져다 쓸 수 있게 되어 있다.
  • AJDT
    • AspectJ Development Tool의 약자로, 이클립스에서 AspectJ AOP를 이용한 개발을 지원하는 편리한 툴이다.
  • VMCI
    • VMWare 서버 또는 워크스테이션과의 연동을 지원하는 플러그인이다. STS의 VMWare 배치 기능에 주로 사용되기 위해 추가된 것이다.
  • 이클립스 표준 플러그인
    • 이클립스 플랫폼에서 제공하는 주요 표준 플러그인에 포함된 것으로는 웹 개발을 지원하는 WTP(Web Tool Platform), EMP(Eclipse Modeling Project), Mylyn, DSDP(Device Software Development Platform)등이 있다.

      라이브러리 관리와 빌드 툴

      라이브러리 관리의 어려움

      스프링은 20개의 모듈과 100여 개의 직접 참조 라이브러리가 있지만 그 모든 모듈과 라이브러리가 매번 다 쓰이는 건 아니다. 필요한 기능과 사용하기로 결정한 기술에 따라서 적절한 선택이 필요하다.

라이브러리 마다 여러 개의 버전이 있고, 각 라이브러리마다 정확히 어떤 버전을 사용해야 할지도 알아야 한다. 라이브러리 종류는 같지만 버전이 맞지 않으면 컴파일이 되지 않을 수 있고, 운이 나쁘면 컴파일은 정상적으로 되고 동작은 하지만 운영 중에 오류가 발생할 수 있다.

스프링을 이용한 애플리케이션을 만들 때 필요한 라이브러리의 종류와 버전을 적절히 선정하고 개발하면서 추가적으로 필요로 하는 라이브러리를 추가하거나 또는 제거하는 등의 관리 작업은 결코 쉬운 일이 아니다.

라이브러리 선정
  • 스프링 모듈
    • 사용할 기능과 기술 목록이 모두 만들어졌으면 일단 스프링 모듈부터 선정한다. 스프링에는 총 20개의 모듈이 있다.
  • 라이브러리
    • 스프링의 각 모듈은 또 다른 모듈에 의존하기도 하지만 오픈소스 라이브러리 또는 표준 API를 필요로 하기도 하고 경우에 따라서는 상용 제품의 라이브러리에 의존한다. 각 모듈이 반드시 필요로 하는 라이브러리가 무엇인지, 선택적으로 사용하는 것은 무언인지 스프링 모듈과 그에 의존하는 라이브러리의 종류와 특징을 살펴보고 그중에서 적절한 라이브러리를 선택한다.
      빌드 툴과 라이브러리 관리

      Maven과 ANT는 자바의 대표적인 빌드 툴이다.

이클립스와 같은 IDE는 코드만 작성하면 자동으로 컴파일해주는 자동빌드 기능이 있고, 관련 빌더를 추가하거나 확장함으로써 복잡한 빌드 작업도 간단히 진행할 수 있다. 하지만 IDE를 사용할 수 있는 환경이 아닌 경우에도 일관된 빌드가 가능하도록 만드는 것이 중요하다. 그래서 자동빌드 기능을 지원하는 IDE를 기본적으로 이용하면서 ANT나 Maven 같은 환경에 독립적인 빌드 툴을 함께 사용하는 것이 바람직하다.

ANT가 이클립스에 기본 내장돼서 제공될 정도로 사실상 표준 자바 빌드 툴로 자리 잡고 있을 때 Maven이라는 새로운 개념의 빌드 툴이 등장했다. Maven은 단순 빌드 툴을 넘어서 개발 과정에서 필요한 빌드, 테스트, 배치, 문서화, 리포팅 등의 다양한 작업을 지원하는 종합 프로젝트 관리 툴의 성격을 띠고 있다. Maven의 특징은 POM이라고 불리는 프로젝트 모델 정보를 이용한다는 점이다. 그래서 절차적인 스크립트와 구조가 비슷한 ANT와 달리 Maven은 선언적이다. 프로젝트의 주요한 구조와 특징, 필요한 정보를 POM의 프로젝트 모델 정보로 만들어두면, 이를 참조해서 Maven에 미리 정해진 절차에 따라 빌드 또는 프로젝트 관리 작업을 진행할 수 있다.

Maven POM이 가진 독특한 특징 중의 하나는 애플리케이션이 필요로 하는 의존 라이브러리를 선언해두기만 하면 원격 서버에서 이를 자동으로 다운로드 받아서 사용할 수 있게 해주는 것이다.

Maven의 의존 라이브러리 관리 기능이 제공하는 더 흥미로운 기능은 전이적(transitive) 의존 라이브러리 추적 기능이다. POM의 의존정보에 하나의 라이브러리를 지정하면, 지정된 라이브러리가 동작하는 데 필요한 여타 라이브러리까지 함께 다운로드해주는 기능이다.

사용예시

먼저 조직이나 팀이 관여하는 프로젝트 사이에 변하지 않고 공통적으로 사용하는 기술 목록을 만든다. 그리고 그 공통적인 기술을 적용할 때 필요한 모든 스프링 모듈과 라이브러리를 선정한다. 이렇게 만든 목록을 가지고 com.mycompany.common-deps 같은 이름으로 라이브러리 목록만 담긴 간단한 POM 파일을 만든다. 이 POM은 프로젝트를 위한 것이 아니라 라이브러리 목록을 정의해놓는 것이 목적이다. 그리고 사내 로컬 Maven 리포지토리를 셋업하고 여기에 앞에서 만든 common-deps POM 파일을 업로드해둔다.

그리고 개별 프로젝트에 Maven POM 파일을 만들고 여기서 만든 common-deps POM 자체를 의존정보로 넣는다. 이렇게 해주기만 해도 전이적 의존관계 추적 기능에 의해 common-deps POM에 담긴 모든 라이브러리가 프로젝트에 자동으로 등록된다.

같은 조직이고 같은 팀이라면 공통적인 모듈과 의존 라이브러리를 추출할 수 있을 것이고, 이를 공통 의존 라이브러리 정보로 만들어두면 매우 유용하다.

처음 한 번과 새로운 스프링 버전이 등장했을 때만 다시 수고해주면 지속적으로 활용 가능한 효과적인 의존관계 관리체계와 툴을 가져갈 수 있다.

  • 기술 그룹에 따른 POM을 이용해 애플리케이션의 의존 라이브러리를 선언하는 예 ```
// grouId와 artifactId, version을 ID로 해서 리포지토리에서 정보를 찾는다. com.mycompany.deps common-deps 1.0.0 pom com.mycompany.deps springmvc-deps 1.0.0 // 의존 라이브러리 구성이 새롭게 갱신되면 그에 맞게 버전을 바꿔주면 된다. pom com.mycompany.deps hibernate-deps 1.0.0 pom // 타입을 pom으로 하면 의존 라이브러리 목록을 갖고 있는 POM을 리포지토리에서 가져와서 의존정보를 추가해준다.
<hr/>

### 애플리케이션 아키텍처
아키텍처는 여러 가지 방식으로 정의되고 이해될 수 있는 용어다. 가장 단순한 정의를 보자면 어떤 경계 안에 있는 내부 구성요소들이 어떤 책임을 갖고 있고, 어떤 방식으로 서로 관계를 맺고 동작하는 지를 규정하는 것이라고 할 수 있다. 아키텍처는 단순히 정적인 구조를 나타내는 것으로만 생각하기 쉽지만 실제로는 그 구조에서 일어나는 동적인 행위와 깊은 관계가 있다.
#### 계층형 아키텍처
성격이 다른 모듈이 강하게 결합되어 한데 모여 있으면 한 가지 이유로 변경이 일어날 때 그와 상관이 없는 요소도 함께 영향을 받게 된다. 따라서 불필요한 부분까지 변경이 일어날 때 그와 상관이 없는 요소도 함께 영향을 받게 된다. 따라서 불필요한 부분까지 변경이 일어나고 그로 인해 작업은 더뎌지고 오류가 발생할 가능성이 높아진다. 어느 부분을 수정해야 할지를 파악하기도 쉽지 않다. 따라서 인터페이스와 같은 유연한 경계를 만들어두고 분리하거나 모아주는 작업이 필요하다.
##### 아키텍처와 SoC
책임과 성격이 다른 것을 크게 그룹으로 만들어 분리해두는 것을 아키텍처 차원에서는 **계층형 아키텍처: layered architecture**라고 부른다. 또는 계층이라는 의미를 가진 영어 단어인 티어(tier)를 써서 **멀티 티어 아키텍처**라고도 한다. 보통 웹 기반의 엔터프라이즈 애플리케이션은 일반적으로 세 개의 계층을 갖는다고 해서 **3계층: 3-tier 또는 3-layer** 애플리케이션이라고도 한다.
##### 3계층 아키텍처와 수직 계층
3계층 아키텍처는 백엔드의 DB나 레거시 시스템과 연동하는 인터페이스 역할을 하는 데이터 액세스(DataAccess) 계층, 비즈니스 로직을 담고 있는 서비스 계층, 주로 웹 기반의 UI를 만들어내고 그 흐름을 관리하는 프레젠테이션 계층으로 구분한다. 이 3계층 아키텍처의 각 계층을 부르는 이름은 워낙 다양하다.
* 3계층 아키텍처

클라이언트 <-> 프레젠테이션계층(웹 계층, UI계층, MVC 계층) <-> 서비스 계층(매니저 계층, 비즈니스 로직 계층) <-> 데이터 액세스 계층(DAO 계층, EIS 계층) <-> DB/레거시

* 데이터 액세스 계층<br/>
    ˚ 데이터 액세스 계층은 사용 기술에 따라서 다시 세분화된 계층으로 구분될 수 있다. 데이터 액세스 계층 안에서 다시 세분화하는 경우는 추상화 수준에 따른 구분이기 때문에 수직적인 계층이라고 부르기도 한다. 기본 3계층은 기술 계층보다는 역할에 따라 구분한 것이므로 보통 그림으로 나타낼 때도 가로로 배열한다. 반면에 같은 책임을 가졌지만 추상화 레벨에 따라 구분하는 경우는 세로로 배열해서 표현한다. <br/>
    
    ˚ 데이터 액세스 계층의 수직 계층구조<br/>
  
| DAO 코드 |
|:----------:|
| JdbcTemplate | 
| JDBC|트랜잭션 동기화 |
| DataSource |

   ˚ 스프링이 추가한 JdbcTemplate 추상 계층이 있기 때문에 DAO 코드는 직접 JDBC나 트랜잭션 동기화 계층의 API를 사용할 필요가 없다.<br/>
   ˚ 위로 갈수록 추상화 레벨이 높고 아래로 갈수록 추상화 레벨이 낮다.<br/>
   ˚ 추상화 계층은 필요하다면 얼마든지 추가할 수 있다.<br/>

| DAO 코드 |
|:----------:|
| SimpleJdbcLayer | 
| JdbcTemplate|SqlService |
| ... |

  ˚ SqlService와 JdbcTemplate을 통합해서 손쉽게 사용할 수 있도록 새로운 추상 API 계층을 추가했다.<br/>
  > 이렇게 새로운 계층을 추가하면 개발자의 애플리케이션 코드에 지대한 영향을 주기 때문에 매우 신중하게 결정해야 한다. 한번 새로운 계층과 API를 만들어 적용하면 이를 최대한 유지할 수 있도록 하위 계층의 변화에 대응해야 하는 책임도 갖게 된다.
* 서비스 계층
  * 잘 만들어진 스프링 애플리케이션의 서비스 계층 클래스는 이상적인 POJO로 작성된다. POJO로 만든다면 객체지향적인 설계 기법이 적용된 코드를 통해서 비즈니스 로직의 핵심을 잘 담아내고, 이를 쉽게 테스트하고 유연하게 확장할 수 있다. 서비스 계층은 DAO 계층을 호출하고 이를 활용해서 만들어진다. 
  * 서비스 계층은 특별한 경우가 아니라면 추상화 수직 계층구조를 가질 필요가 없다. 단순히 POJO 레벨에서 비즈니스 로직을 모델링하다가 상속구조를 만들 수 있을진 몰라도 기술 API를 직접 다루는 코드가 아니기 때문에 기술에 일관된 방식으로 접근하게 하거나 편하게 사용하게 해주는 추상화는 필요 없기 때문이다. 
  * 이상적인 서비스 계층은 백엔드 시스템과 연결되는 데이터 액세스 계층이 바뀌고, 클라이언트와 연결되는 프레젠테이션 계층이 모두 바뀌어도 그대로 유지될 수 있어야 한다. 엔터프라이즈 애플리케이션에서 가장 중요한 자신은 도메인의 핵심 비즈니스 로직이 들어 있는 서비스 계층이어야 한다.
* 프레젠테이션 계층
  * 프레젠테이션 계층은 가장 복잡한 계층이다. 매우 다양한 기술과 프레임워크의 조합을 가질 수 있기 때문이다. 
  * 스프링은 웹 기반의 프레젠테이션 계층을 개발할 수 있는 전용 웹 프레임워크를 제공한다. 동시에 스프링은 다양한 서드파티 웹 기술을 지원하기도 한다.
##### 계층형 아키텍처 설계의 원칙
* 각 계층은 응집도가 높으면서 다른 계층과는 낮은 결합도를 유지할 수 있어야 한다.
* 각 계층은 자신의 계층의 책임에만 충실해야 한다.

public ResultSet findUsersByName(String name) throws SQLException;

위의 코드는 데이터 액세스 계층의 기술과 그 역할을 다른 계층에 노출한다. 결과를 JDBC의 ResultSet 오브젝트로 돌려주면 이를 사용하는 서비스 계층의 코드는 ResultSet이라는 데이터 엑세스 계층에서 만들어진 오브젝트를 직접 다뤄야만한다. 결국 JDBC라는 특정 데이터 액세스 계층 기술에 종속되는 서비스 계층의 코드가 되고 만다. 또한 ResultSet을 다룰 때 발생하는 예외처리도 필요하고, 경우에 따라서는 리소스를 반환하거나 DB 커넥션을 종료시키는 등의 데이터 액세스 작업도 맡아야 한다. 

예외도 마찬가지다. SQLException이라는 JDBC 기술 종속적인 예외를, 그것도 체크 예외로 던져버리면, 이를 사용하는 서비스 계층에서는 SQLException을 해석해서 예외상황을 분석하고 이를 처리하는 코드를 만들어야 한다. 특정 데이터 액세스 계층의 구현에 종속되는 강한 결합이 만들어진다. 따라서 다음과 같이 수정돼야 한다.

public List findUsersByName(String name) throws DataAccessException; ```

Users는 사용자 정보를 담고 있는 단순한 오브젝트다. 따라서 특정 계층의 기술이나 구현에 종속되지 않는다. 또 데이터 액세스 예외와 같이 특별한 경우에만 전달될 가능성이 있는 것은 스프링의 DataAccessException처럼 런타임 예외로 만들어야 한다. 그래서 대개는 그 존재를 무시해도 되도록 만들어야 한다. 특별한 이유로 데이터 액세스 예외를 다뤄야 하는 경우에라도 JDBC, JPA, JDO, 하이버네이트처럼 특정 구현 방식에 종속되지 않는 추상적인 형태로 만들어줘야 한다. 그렇게 해야만 낮은 결합도를 유지할 수 있고 유연한 병경이 가능해진다.

또, 흔히 저지르는 실수 중의 하나는 프레젠테이션 계층의 오브젝트를 그대로 서비스 계층으로 전달하는 것이다. 서블릿의 HttpServletRequest나 HttpServletResponse, HttpSession 같은 타입을 서비스 계층 인터페이스 메소드의 파라미터 타입으로 사용하면 안 된다. 계층의 경계를 넘어갈 때는 반드시 특정 계층에 종속되지 않는 오브젝트 형태로 변환해줘야 한다.

어떤 경우에라도 계층 사이의 낮은 결합도를 깨뜨리지 않도록 설계해야 한다. 당연히 계층 사이의 호출은 인터페이스를 통해 이뤄져야 한다. 인터페이스를 사용하게 한다는건 각 계층의 경계를 넘어서 들어오는 요청을 명확히 정의하겠다는 의미다. 여기서 말하는 인터페이스란 단지 자바의 interface 키워드를 사용하라는 의미가 아니다. 인터페이스에 아무 생각 없이 클래스의 모든 public 메소드를 추가한다면 인터페이스를 사용하는 가치가 떨어진다. 한번 정의돼서 다른 계층에서 사용하기 시작한 인터페이스 메소드는 변경이 매우 까다롭고 비용이 많이 든다. 당연히 다른 계층에서 꼭 필요한 메소드만 노출해야 한다.

스프링의 DI는 기본적으로 오브젝트 사이의 관계를 다룬다. 따라서 계층 사이의 경계나 그 관계에 직접적으로 관여하지 않는다. 하지만 모든 경계에는 오브젝트가 존재하고 그 사이의 관계도 오브젝트 대 오브젝트로 정의되기 마련이다. 그런 면에서 스프링의 DI가 계층 사이의 관계에도 적용된다고 볼 수 있다. 하지만 DI는 계층을 구분해주지 않기 때문에 빈 사이의 의존관계를 만들 때 주의해야 한다. 한 계층의 내부에서만 사용되도록 만든 빈 오브젝트가 있는데, 이를 DI를 통해 다른 계층에서 함부로 가져다 쓰는 일은 피해야 한다. 또, 중간 계층을 건너뛰어서 관계를 갖지 않는 계층의 빈을 직접 DI 하지 않도록 주의해야 한다.

애플리케이션 정보 아키텍처

엔터프라이즈 애플리케이션에 존재하는 정보를 단순히 데이터로 다루는 경우와 오브젝트로 다루는 경우, 두 가지 기준으로 구분해볼 수 있다.

데이터 중심 아키텍처는 애플리케이션에 흘러다니는 정보를 단순히 값이나 값을 담기 위한 목적의 오브젝트 형태로 취급하는 구조다. 데이터 중심 설계의 특징은 비즈니스 로직이 DB 내부의 저장 프로시저나 SQL에 담겨 있는 경우가 많다는 점이다.

데이터 중심 아키텍처는 핵심 비즈니스 로직을 어디에 많이 두는지에 따라서 DB에 무게를 두는 구조와 서비스 계층의 코드에 무게를 두는 구조로 구분할 수 있다.

DB/SQL 중심의 로직 구현 방식

데이터 중심 구조의 특징은 하나의 업무 트랜잭션에 모든 계층의 코드가 종속되는 경향이 있다는 점이다. 대부분의 코드는 대응되는 작업 단위에 1:1로 매핑된다. 여러 작업에서 반복되는 기능이 있다면 그에 대한 코드는 중복되기 쉽다. 보통 작업 단위, 즉 업무 트랜잭션 단위로 코드를 묶어서 만들지 기능을 세분화해서 분리하고 재사용하지 않기 때문이다. 하나의 업무 트랜잭션을 모두 담은 서비스 계층 코드와 해다 업무에 특화된 SQL을 담은 하나 또는 여러 개의 DAO 메소드로 구성된다. 서비스 계층이 프레젠테이션 계층에 전달하는 결과의 포맷은 보통 DAO의 SQL 결과와 같고, 웹 페이지의 출력 내용과도 1:1로 대응된다.

이런 개발 방식은 변화에 매우 취약하다. 객체지향의 장점이 별로 활용되지 못하는데다 각 계층의 코드가 긴밀하게 연결되어 있기 때문이다. 중복을 제거하기도 쉽지 않다. 업무 트랜잭션에 따라 필드 하나가 달라도 거의 비슷한 DAO 메소드를 새로 만들기도 한다. 업무 트랜잭션에 따라 필드 하나가 달라도 거의 비슷한 DAO 메소드를 새로 만들기도 한다. 또한 로직을 DB와 SQL에 많이 담으면 담을수록 점점 확장성이 떨어진다.

거대한 서비스 계층 방식

DB에는 부하가 걸리지 않도록 저장 프로시저의 사용을 자제하고 복잡한 SQL을 피하면서, 주요 로직은 서비스 계층의 코드에서 처리하도록 만든다. 상대적으로 단순한 DAO 로직을 사용하고, 비즈니스 로직의 대부분을 서비스 계층에 집중하는 이런 접근 방법은 결국 거대한 서비스 계층을 만들게 된다.

거대 서비스 계층 방식의 장점은 애플리케이션의 코드에 비즈니스 로직이 담겨 있기 때문에 자바 언어의 장점을 활용해 로직을 구현할 수 있고 테스트하기도 수월하다는 점이다. 또한 DAO가 다루는 SQL이 복잡하지 않고 프레젠테이션 계층의 뷰와 1:1로 매핑되지 않아도 되기 때문에 일부 DAO 코드는 여러 비즈니스 로직에서 공유해서 사용할 수 있다.

하지만 데이터 액세스 계층의 SQL은 서비스 계층의 비즈니스 로직의 필요에 따라 만들어지기 쉽다. 그래서 계층 간의 결합도가 여전히 크다. 서비스 계층의 메소드는 크기가 큰 업무 트랜잭션 단위로 만들어지기 때문에 비슷한 기능의 코드가 여러 메소드에서 중복돼서 나타나기 쉽다. 자주 사용되는 세부 로직을 추출해서 공통 기능으로 뽑아내는 일도 불가능하진 않지만 일반화하기는 힘들다. 그 이유는 DAO가 제공해주는 값의 포맷에 따라 이를 취급하는 방법이 달라지기 때문이다.

데이터 중심 아키텍처의 특징은 계층 사이의 결합도가 높은 편이고 응집도는 떨어진다는 점이다. 화면을 중심으로 하는 업무 트랜잭션 단위로 코드가 모이기 때문에 처음엔 개발하기 편하지만 중복이 많아지기 쉽고 장기적으로 코드를 관리하고 발전시키기 힘들다는 단점이 있다.

오브젝트 중심 아키텍처

오브젝트 중심 아키텍처가 데이터 중심 아키텍처와 다른 가장 큰 특징은 도메인 모델을 반영하는 오브젝트 구조를 만들어두고 그것을 각 계층 사이에서 정보를 전송하는 데 사용한다는 것이다. 그래서 오브젝트 중심 아키텍처는 객체지향 분석과 모델링의 결과로 나오는 도메인 모델을 오브젝트 모델로 활용한다.

데이터와 오브젝트

데이터 중심의 아키텍처에서는 DAO가 만드는 SQL의 결과에 모든 계층의 코드가 의존하게 된다. 도메인 분석을 통해 작성된 모델정보는 DB에 대한 SQL을 작성할 때 외에는 코드에 반영되는 일이 없다.

반면에 오브젝트 방식에서는 애플리케이션에서 사용되는 정보가 도메인 모델의 구조를 반영해서 만들어진 오브젝트 안에 담긴다. 도메인 모델은 애플리케이션 전 계층에서 동일한 의미를 갖는다. 따라서 도메인 모델이 반영된 도메인 오브젝트도 전 계층에서 일관된 구조를 유지한 채로 사용될 수 있다. SQL이나 웹페이지의 출력 포맷, 입력 폼 등에 종속되지 않는 일관된 형식의 애플리케이션의 정보를 다룰 수 있게 된다.

도메인 오브젝트 사용의 문제점

최적화된 SQL을 매번 만들어 사용하는 경우에 비해 성능 면에서 조금은 손해를 감수해야 할 수도 있다. DAO는 비즈니스 로직의 사용 방식을 알지 못하므로, 도메인 오브젝트의 모든 필드 값을 다 채워서 전달하는 경우가 대부분이다. 그런데 하나의 오브젝트에 담긴 필드의 개수가 많아지다 보면 그중에는 드물게 사용되는 필드도 있을 수 있다. 어떤 비즈니스 로직에서 필요한 정보가 몇 개의 필드뿐이라면 DAO에서 도메인 오브젝트의 모든 필드 정보를 채워서 전달하는 것은 낭비일 수도 있다. 비즈니스 로직에 따라서 필요한 정보가 달라질 수 있기 때문에 발생하는 문제다.

결국 최적화를 고려해서 DAO를 작성하려면 DAO는 비즈니스 로직에서 각 오브젝트를 어디까지 사용해야 하는지 어느 정도 알고 있어야 한다.

지연된 로딩: lazy loading기법을 이용하면 일단 최소한의 오브젝트 정보만 읽어두고 관계하고 있는 오브젝트가 필요한 경우에만 다이내믹하게 DB에서 다시 읽어올 수 있다. 물론 도메인 오브젝트를 사용하는 코드는 이런 사실을 전혀 의식하지 않고 처음부터 모든 오브젝트의 정보가 다 제공된다고 생각하고 작성하면 된다.

필드가 너무 많은 테이블이 있다면 그중에서 자주 사용되는 것을 골라내서 별도의 오브젝트로 정의해두고 필요에 따라 구분해서 사용하게 할 수 있다. 물론 그에 따라 DAO 메소드가 추가돼야 하고, 어느 DAO를 사용할지를 서비스 계층에서 알고 있어야 하기 때문에, 약하긴 하지만 계층 사이의 결합이 발생한다.

가장 이상적인 방법은 JPA나 JDO, 하이버네이트, TopLinK와 같은 오브젝트/RDB 매핑(ORM)기술을 사용하는 것이다. 이런 데이터 액세스 기술은 기본적으로 지연된 로딩 기법 등을 제공해주기 때문에 번거로운 코드를 만들지 않고도 도메인 오브젝트의 생성을 최적화할 수 있다. 또한 SQL 결과를 가지고 도메인 오브젝트를 만들고 값을 채우는 등의 복잡한 DAO 코드를 만들지 않아도 된다. 내부적으로 최적화된 SQL을 사용하도록 세밀히 튜닝할 수도 있다.

오브젝트 중심의 아키텍처는 도메인 모델을 따르는 오브젝트를 사용해 각 계층 사이에 정보를 전달하고, 이를 이용해 비즈니스 로직이나 프레젠테이션 로직을 작성한다. 계층 간의 결합도는 낮아지고 일관된 정보 모델을 사용하기 때문에 개발 생산성과 코드의 품질, 테스트 편의성도 향상시킬 수 있다.

빈약한 도메인 오브젝트 방식

도메인 오브젝트에 정보만 담겨 있고, 정보를 활용하는 아무런 기능도 갖고 있지 않다면 이는 온전한 오브젝트라고 보기 힘들다. 그래서 이런 오브젝트를 빈약한 오브젝트라고 부른다.

사실 다루는 정보의 구조가 다를 뿐이지 빈약한 도메인 오브젝트 방식은 데이터 중심 아키텍처의 거대 서비스 계층 구조와 비슷하다. 빈약한 도메인 오브젝트 방식도 거대 서비스 계층 방식의 하나라고 보면 된다. 도메인 오브젝트는 3개의 계층에는 독립적으로 존재하면서 일관된 구조의 정보를 담아서 계층 간에 전달하는 데 사용된다.

비록 도메인 오브젝트라는 일관된 오브젝트를 활용하기 때문에 SQL에 의존적인 데이터 방식보다는 훨씬 유연하고 간결하지만, 여전히 서비스 계층의 메소드에 대부분의 비즈니스 로직이 들어 있기 때문에 로직의 재사용성이 떨어지고 중복의 문제가 발생하기 쉽다.

하지만 비즈니스 로직이 복잡하지 않다면 가장 만들기 쉽고 3계층 구조의 특징을 잘 살려서 개발할 수 있는 유용한 아키텍처다.

풍성한 도메인 오브젝트 방식

풍성한 도메인 오브젝트 또는 영리한 도메인 오브젝트 방식은 빈약한 도메인 오브젝트의 단점을 극복하고 도메인 오브젝트의 객체지향적인 특징을 잘 사용할 수 있도록 개선한 것이다. 어떤 비즈니스 로직은 특정 도메인 오브젝트나 그 관련 오브젝트가 가진 정보와 깊은 관계가 있다. 이런 로직을 서비스 계층의 코드가 아니라 도메인 오브젝트에 넣어주고, 서비스 계층의 비즈니스 로직에서 재사용하게 만드는 것이다.

도메인 오브젝트 안에 메소드로 들어가는 로직들은 대부분 해당 오브젝트나, 긴밀한 연관관계를 맺고 있는 관련 오브젝트의 정보와 기능만을 활용한다. 여러 종류의 도메인 오브젝트의 기능을 조합해서 복잡한 비즈니스 로직을 만들었다면 특정 도메인 오브젝트에 넣기는 힘들다. 이런 비즈니스 로직은 서비스 계층의 오브젝트에 두는 것이 적당하다.

도메인 오브젝트는 DAO 오브젝트를 DI 받을 수 없다. 도메인 오브젝트는 스프링 컨테이너가 관리하는 오브젝트, 즉 빈이 아니기 때문이다. DI를 받으려면 자신도 역시 스프링 컨테이너에서 관리되는 빈이어야 한다. 따라서 서비스 계층의 코드가 필요하다. 스프링의 빈으로 관리되는 3계층의 오브젝트들은 도메인 오브젝트를 자유롭게 이용할 수 있지만 그 반대는 안 된다.

도메인 계층 방식

도메인 오브젝트가 기존 3계층의 오브젝트를 DI 받아서 직접 이용할 수 있게 하기 위해 기존 3계층과 같은 레벨로 격상되어 하나의 계층을 이루게 하는 도메인 계층 방식이 등장했다. 도메인 오브젝트들이 하나의 독립적인 계층을 이뤄서 서비스 계층과 데이터 액세스 계층의 사이에 존재하게 되는 것이다.

도메인 계층 방식의 특징
  1. 도메인에 종속적인 비즈니스 로직의 처리는 서비스 계층이 아니라 도메인 계층의 오브젝트 안에서 진행된다. 데이터 액세스 계층을 통해 도메인 오브젝트를 가져왔던 상관없이 도메인 오브젝트에게 비즈니스 로직의 처리를 요청할 수 있다.
  2. 도메인 오브젝트가 기존 데이터 액세스 계층이나 기반 계층의 기능을 직접 활용할 수 있다.
    • 스프링이 관리하지 않는 도메인 오브젝트에 DI를 적용하기 위해서는 AOP가 필요하다. 물론 스프링 AOP는 부가기능을 추가할 수 있는 위치가 메소드 호출 과정으로 한정되고 AOP의 적용 대상도 스프링의 빈 오브젝트뿐이다. 하지만 스프링 AOP 대신 AspectJ AOP를 사용하면 클래스의 생성자가 호출되면서 오브젝트가 만들어지는 시점을 조인 포인트로 사용할 수 있고 스프링 빈이 아닌 일반 오브젝트에도 AOP 부가기능을 적용할 수 있다. 이를 이용해서 도메인 오브젝트가 생성되는 시점에 특별한 부가기능을 추가하게 만들어줄 수 있다. 이 부가기능은 오브젝트의 수정자 메소드나 DI용 애노테이션을 참고해서 DI 가능한 대상을 스프링 컨테이너에서 찾아 DI 해주는 기능이다. 스프링이 직접 관리하지 않는 오브젝트에 대한 DI 서비스가 일종의 AOP 부가기능으로 도메인 오브젝트에 적용될 수 있다.
도메인 오브젝트의 사용 범위
  1. 여전히 모든 계층에서 도메인 오브젝트를 사용한다.
    • 도메인 모델을 따르는 오브젝트 구조를 활용하는 면에서 오브젝트 중심 아키텍처의 장점을 그대로 누릴 수 있다.
    • 막강한 기능을 가진 도메인 오브젝트를 프레젠테이션 계층이나 뷰 등에서 사용하게 해주면 이를 함부로 사용하는 위험이 뒤따른다.
  2. 도메인 오브젝트는 도메인 계층을 벗어나지 못하게 한다.
    • 도메인 계층 밖으로 전달될 때는 별도로 준비된 정보 전달용 오브젝트에 도메인 오브젝트의 내용을 복사해서 넘겨줘야 한다. 이런 오브젝트는 데이터 전달을 위해 사용된다고해서 DTO(Data Transfer Object)라고 불린다. DTO는 상태의 변화를 허용하지 않고 읽기전용으로 만들어지기도 한다. 반대로 사용자가 등록한 값이나 외부 시스템으로부터 전달받은 정보를 도메인 계층으로 전달하는 경우에도 DTO를 이용할 수 있다.
    • DTO는 기능을 갖지 않으므로 사용하기 안전하다. 또, 도메인 오브젝트를 외부 계층의 코드로부터 보호해준다. 반면에 도메인 오브젝트와 비슷한 구조를 가진 오브젝트를 따로 만들어야 하고 이를 매번 변환해줘야 하는 번거로움이 있다. 따라서 AOP와 같은 방법을 이용해 변환을 자동으로 해주도록 만들 필요가 있다. ###### DTO와 리포트 쿼리 도메인 계층 방식의 경우 도메인 계층을 벗어난 정보를 DTO라 불리는 특정 계층에 종속되지 않는 정보 전달의 목적을 가진 단순 오브젝트에 담아 사용하기도 한다. 그 외의 방법에서도 DTO의 사용이 꼭 필요할 때가 있다.
    • 리포트 쿼리(report query)라고 불리는 DB 쿼리의 실행 결과를 담는 경우다. 리포트 쿼리는 리포트를 출력하기 위해 생성하는 쿼리라는 의미인데, 단지 리포트를 위해서라기보다는 보통 종합 분석 리포트처럼 여러 테이블에 걸쳐 존재하는 자료를 분석하고 그에 따른 분석/통계 결과를 생성하는 쿼리라는 의미다. 이런 쿼리의 결과는 DB 테이블에 담긴 필드의 내용보다는 그 합계, 평균과 같은 계산 값이거나 아니면 여러 테이블의 필드를 다양한 방식으로 조합해서 만들어진다. 따라서 DB 쿼리의 실행 결과를 담을 만한 적절한 도메인 오브젝트를 찾을 수 없다. 그래서 이런 리포트 쿼리의 결과는 DTO라고 불리는 단순한 자바빈이나 아니면 키와 값 쌍을 갖는 맵에 담아서 전달해야 한다.
    • DB의 쿼리 하나로 최종 결과를 만들어내기 힘들기 때문에 코드를 통해 데이터를 분석하고 가공하는 작업이 필요하다. 이런 경우에도 최종 결과는 DTO나 맵, 컬렉션에 담겨서 전달돼야 한다.
    • 웹 서비스 등의 시스템과 자료를 주고받을 때 전송 규약에 맞춰서 도메인 오브젝트에 담긴 정보를 가공해야 할 때가 있다. 이런 경우도 DTO나 맵을 이용해 해당 형식에 맞도록 변경하는 작업이 필요하다. #### 스프링 애플리케이션을 위한 아키텍처 설계 ##### 계층형 아키텍처 3계층 구조는 스프링을 사용하는 엔터프라이즈 애플리케이션에서 가장 많이 사용되는 구조다. ##### 정보 전송 아키텍처 스프링의 기본 기술에 가장 잘 들어맞고 쉽게 적용해볼 수 있는 것은 오브젝트 중심 아키텍처의 도메인 오브젝트 방식이다. 도메인 오브젝트를 계층 간의 정보 전송을 위해 사용하고, 이를 각 계층의 코드에서 활용한다. ##### 상태 관리와 빈 스코프 아키텍처 설계에서 한 가지 더 신경 써야 할 사항은 상태 관리다. 크게는 사용자 로그인 세션 관리부터, 작게는 하나의 단위 작업이지만 여러 페이지에 걸쳐 진행되는 위저드 기능까지 애플리케이션은 하나의 HTTP 요청의 범위를 넘어서 유지해야 하는 상태정보가 있다.

상태를 저장, 유지하는 데 어떤 방식을 사용할지 결정하는 일은 매우 중요하다. 스프링은 기본적으로 상태가 유지되지 않는 빈과 오브젝트를 사용하는 것을 권장한다. 반면에 웹 클라이언트에 폼 정보를 출력하고 이를 수정하는 등의 작업을 위해서는 HTTP 세션을 적극 활용하기도 한다.

스프링에서는 싱글톤 외에도 다른 스코프를 갖는 빈을 간단히 만들 수 있다. 빈의 스코프를 잘 활용하면 스프링이 관리하는 빈이면서 사용자별로 또는 단위 작업별로 독립적으로 생성되고 유지되는 오브젝트를 만들어 상태를 저장하고 이를 DI를 통해 서비스 빈에서 사용하게 만들 수 있다.

서드파티 프레임워크, 라이브러리 적용

스프링은 거의 대부분의 자바 표준 기술과 함께 사용될 수 있다. 기본적으로는 J2EE 1.4와 JavaEE 5.0을 지원한다. 따라서 스프링으로 만든 애플리케이션은 JSP, JSF, EJB, JNDI, JTA, JCA, JAX-WS, JMS, JavaMail, JPA와 같은 JavaEE의 세부 기술과 함께 사용될 수 있다.

표준 기술 외에도 많이 사용되는 오픈소스 프레임워크, 라이브러리나 상용 제품도 스프링과 함께 사용할 수 있다. 스프링이 직접 지원하는 오픈소스 ORM의 대표 제품으로는 하이버네이트와 iBatis 그리고 EclipseLink, OpenJPA와 같은 오픈소스 JPA가 있고, 웹 프레임워크로는 스트럿츠 1/2, WebWork, Tapestry, Tiles 등을 꼽을 수 있다. 그 외에도 다양한 OXM 라이브러리를 지원하고, 메시징 서버와 웹 서비스 기술 등을 지원한다.

스프링이 지원하는 기술이란?
  1. 해당 기술을 스프링의 DI 패턴을 따라 사용할 수 있다.
    • 프레임워크나 라이브러리의 핵심 클래스를 빈으로 등록할 수 있게 지원해주는 것이라고 생각해도 좋다. 코드를 이용해 초기화해야만 사용할 수 있는 기능을 빈을 등록하는 것만으로 바로 사용할 수 있다. 프레임워크의 핵심 오브젝트를 빈의 형태로 등록해둘 수 있다면 프로퍼티를 이용해 세부 설정을 조정할 수도 있고, DI를 통해 다른 오브젝트에서 손쉽게 활용할 수도 있다. 또 스프링이 제공하는 추상화 서비스를 통해 다른 리소스에 투명하게 접근할 수도 있다.
  2. 스프링의 서비스 추상화가 적용됐다.
    • 비슷한 기능을 제공하는 기술에 대한 일관된 접근 방법을 정의해줌으로써, 서드파티 프레임워크를 적용할 수 있을 뿐만 아니라 필요에 따라 호환 가능한 기술로 손쉽게 교체해서 사용할 수 있다.
  3. 스프링이 지지하는 프로그래밍 모델을 적용했다.
    • 스프링의 액세스 지원 기능을 사용하면 데이터 액세스 기술의 종류에 상관없이 일관된 예외 계층구조를 따라서 예외가 던져진다. 이를 통해, 서비스 계층의 비즈니스 로직을 담은 코드가 데이터 액세스 계층의 기술에 종속되지 않도록 만들어준다.
  4. 템플릿/콜백이 지원된다.
    • 스프링은 JDBC, JMS, JCA를 비롯한 20여 가지 기술을 지원하는 템플릿/콜백을 제공한다. 이런 기술은 그대로 사용하면 반복적으로 등장하는 판에 박힌 코드 때문에 전체 코드가 지저분해지고 이해하기 힘들고 추상화하기도 어려운 구조가 돼버린다. 스프링은 이런 기술을 간편하게 사용할 수 있도록 템플릿/콜백 기능을 제공한다. 대부분의 템플릿 클래스는 빈으로 등록해서 필요한 빈에서 DI 받아 사용할 수 있다.

정리

  • 스프링은 어떤 플랫폼에서도 사용될 수 있지만, 기본적으로는 자바 엔터프라이즈 플랫폼(JavaEE)에 최적화되어 있다. HTTP를 통해 접근하는 웹 클라이언트와 백엔드 DB를 사용하는 애플리케이션에 적합하다.
  • 스프링 개발의 생산성을 증대시키고 품질을 높이려면 SpringIDE 플러그인이나 STS 같은 적절한 툴의 지원이 필요하다.
  • 스프링은 의존 라이브러리가 방대하기 때문에 라이브러리 관리와 의존관계를 관리하는 데 많은 노력을 기울여야 한다. 가능하면 스프링이 의존관계 정보를 제공해주는 Maven이나 Ivy 같은 빌드 툴을 사용해 의존 라이브러리를 관리하는 것이 바람직하다.
  • 스프링 애플리케이션은 역할에 따라 3계층으로 구분되고, 다시 기술의 추상도에 따라 세분화되는 계층형 아키텍처를 사용하는 것이 좋다.
  • 아키텍처는 애플리케이션이 다루는 정보의 관점에서 데이터 중심과 오브젝트 중심으로 구분할 수 있다.
  • 스프링에 가장 잘 어울리는 아키텍처는 오브젝트 중심의 아키텍처다.
  • 스프링이 직접 지원하지 않는 서드파티 기술도 스프링 스타일의 접근 방식을 따라서 사용할 수 있도록 준비해둬야 한다.

출처 : https://github.com/Masssidev/toby-vol1