프로그래밍에서 특정 운영 체제를 위한 응용 프로그램 표준 구조를 구현하는
Class
와Library
모음
Library
: 자주 사용되는 Logic을 재사용하기 편하도록 정리한 일련의 코드 뭉치 Class
: 객체 Object
를 정의하는 설계도Field
: 객체의 상태를 나타내며, 클래스의 구성단위Variable
Method
: 객체의 행동을 나타내며, 클래스의 구성단위
Java Platform
을 위한 Open Source Application Framework
EnterPrised Application
을 개발하기 위한 모든 기능을 종합적으로 지원하는 경량화된 솔루션
Plugin
을 결합하며 확장성을 넓히고, Project 구조 개발 방식이 훨씬 유연
LightWeight Container
: 경량 컨테이너
결론부터 얘기하자면, 컨테이너란 사용자가 작성한 코드의 처리 과정을 위임받은 독립적인 존재이다.
즉, 컨테이너는 적절한 설정이 되어 있다면, 누구의 도움 없이도 작성된 코드를 스스로 참조한 뒤에, 자동으로 객체의 생성 / 소멸을 컨트롤해준다.
정확하게 말하자면, 프로그램을 이용하는 "사용자의 호출에 의해 컨테이너가 동작하는 구조" 를 의미한다.
WAS
: Web Application Service 역시 컨테이너의 예이다.
Spring에서 제공하는 컨테이너는 2가지 유형이 있다.
BeanFactory
BeanFactory
를 상속하는 ApplictionContext
Spring 설정 파일인 ApplicationContext.xml에 등록된 Bean
객체를 생성하고 관리하는 가장 기본적인 컨테이너 기능만 제공한다.
컨테이너가 구동될 때 객체를 생성하는 것이 아니라 Client로부터 요청이 있을 경우에만 객체를 생성하는 Lazy loading방식으로 동작한다.
이는 BeanFactory를 확장한 컨테이너이다. Transaction 관리나 Message 기반의 다국어 처리 등 다양한 기능이 추가적으로 지원된다.
컨테이너가 구동되는 시점에
Bean
에 등록되어 있는 Class들을 객체화하는 즉시 로딩 방식으로 동작한다.
대표적으로 이 ApplicationContext를 구현한 Class는 GenericXmlApplicationContext
이다.
Life Cycle
을 관리하며, Spring으로부터 필요한 객체를 얻어올 수 있다.
POJO
: Plain Old Java Object 방식의 Framework
POJO
는 Java 언어 사양 외 어떠한 제한에도 묶이지 않는 Java Object라 할 수 있다.Spring Framework 이전의 경우, 원하는 EnterPrise 기술이 있다면, 직접적으로 사용하는 객체를 설계했다. 그러나 이러한 개발 방식으로 특정 기술 / 환경에 종속되어 의존하게 된 Java Code는 가독성이 떨어져 유지 보수에 어려움을 겪었다. 또한, 특정 기술의 Class를 상속 / 의존하게 되어 확장성 역시 매우 떨어지게 되었다. 다시 말하면, 객체지향의 성격을 띄는 Java가 객체지향 설계의 장점을 잃어버린 것이다.
즉, 본래 Java의 장점을 살릴 수 있는
오래된
방식의순수한
Java 객체 개념이 등장하게 되었다.
Spring을 개발해본 사람들은 Hibernate
를 접해본 적 있을 것이다. POJO
의 정의에 따르면, 특정 기술에 종속되지 않아야 한다. Spring이 POJO를 유지하면서 Hibernate를 사용할 수 있는 이유는 무엇일까?
바로, Spring에서 정한 표준 Interface 때문이다. ORM
이라는 기술을 사용하기 위해 JPA
표준 Interface를 정해두었다.
객체-관계 매핑
ORM
: Object Relational Mapping
객체와 관계형 데이터베이스의 데이터를 자동으로 Mapping해주는 것을 말한다.
Class
를 사용하고, 관계형 데이터베이스는 Table
을 사용한다.ORM
을 통해 객체 간의 관계를 바탕으로 SQL을 자동으로 생성하여 불일치를 해결한다.JE22 Framework
와 달리 구현을 위해 특정 Interface를 구현 / Class를 상속받을 필요가 없다.제어 반전
IoC
: Inversion Of Control 지원
컨테이너는 우리가 작성한 코드의 컨트롤 - 즉, 객체의 생성과 소멸 - 을 대신 해준다.
IoC 역시, 언제 호출될지 모르는 코드를 마음껏 칠 수 있도록 한다.
IoC
제어 반전은 사용자가 작성한 프로그램이 재사용 라이브러리의 흐름 제어를 받게 되는 소프트웨어 디자인 패턴이다.
일반적인 프로그래밍에서, 흐름은 사용자가 작성한 프로그램이 외부의 라이브러리 코드를 호출함으로써 이용한다. 그렇지만 제어 반전의 경우, 외부 라이브러리의 코드가 사용자가 작성한 코드를 호출한다
정리하면, IoC
란 추상화 원칙 중 한 가지로, 실행에 필요한 객체의 생성 / 사용 등 제어 권한을 Framework에게 위임함으로써, Client가 신경써야 할 부분을 줄이는 전략이다.
여기까지 이해가 되었다면, 의문이 생기는 것이 정상이다. 도대체! Framework가 나의 코드를 어떻게! 호출할 수 있을까?
제어 반전의 가장 쉬운 접근 방식은 Framework의 event, delegate에 나의 Method를 등록하는 것이다.
또 다른 접근 방식은 Framework에 정의되어 있는 Interface,
Abstract
추상타입을 나의 Method에서 구현 / 상속한 뒤 넘겨주는 것이다. 이 방식은 객체를 Framework에게 주입하는 것이며, 뒤에서 설명할 의존성 주입이다.
의존성 주입
DI
: Dependency Injection 지원
Spring에서 선언되어 관리되고 있는 Instance를
Bean
이라 부른다.
Spring에서 이와 같이 선언된 Bean
을 의존성 주입 DI
방식으로 관리하고 있다.
의존성을 주입하는 방식은 다음과 같다.
Spring Controller에 등록된 Bean을 사용하기 위해서는, Container에 등록된 Bean의 참조 값을 받아와서 사용한다.
Spring Controller 혹은 IoC Container에 등록된 Bean들은 개발자가 프로그램 실행 도중 변경 불가능하므로 일관성있는 Instance를 사용할 수 있게 된다.
DI란 간단하게 표현하면, 미리 찜해둠으로 나타낼 수 있겠다. 웃기는 표현을 사용하자면, 마치 받아먹을 사람은 생각도 않는데, 먼저 말부터 꺼내놓는 파렴치한 코딩방식이다.
DI 방식으로 코드를 작성하게 되면, 현재 사용하고 있는 객체의 Method가 어떻게 작성되었는지, 그 Class가 기능을 잘 구현했는지조차도 알 필요가 없다.
그저, Class의 기능을 추상적으로 묶어둔 Interface만 갖다쓰면 된다. 나머지는 Spring에서 찜해놓은 걸 자동으로 연결시켜줄테니,,
빠른 이해를 돕기 위해, 다음의 예시를 살펴보자.
StrategyPatternService
Class를 보면, 객체 sp
는 Interface 객체인 StrategyPattern
으로 선언되었으며, StrategyPattern
의 Method인 dependency_injection()
를 호출하였다.
즉, 객체 생성 과정에서 sp
에 StrategyPatternImpl
의 dependency_injection()
라는 Method를 호출해버렸다는 것이다.
정리하면, DI 방식을 사용함으로써, Inteface의 Method만 이용하더라도 구현부는 나중에 주입을 통해 해결할 수 있으므로 획기적인 분업과 동시에 구현 Class를 쉽게 교체할 수 있다는 장점을 얻었다.
관점 지향 프로그래밍
AOP
Aspect-Oriented Programming 지원
AOP
는 문제를 바라보는 관점을 기준으로 프로그래밍하는 기법이다."관점 지향"이란 쉽게 말해, 어떤 로직을 기준으로 핵심적인 관점, 부가적인 관점으로 나누어서 보고 그 관점을 기준으로 각각 모듈화하는 것이다.
모듈화란, 어떤 공통된 로직이나 기능을 하나의 단위로 묶는 것을 말한다.
AOP
에서 각 관점을 기준으로 로직을 모듈화한다는 것은 결국, 코드들을 부분적으로 나누어 모듈화한다는 의미이다. 이 때, 코드에서 다른 부분에 계속해서 반복해서 사용하는 코드를 발견할 수 있는데, 이것을 흩어진 관심사 Crosscutting Concerns
라고 부른다.
즉, 흩어진 관심사를 Aspect로 모듈화하고, 핵심적인 비즈니스 로직에서 분리하여 재사용하겠다는 것이 AOP의 취지이다.
Spring에서, 프록시 패턴 기반의 AOP 구현체, 프록시 객체를 사용하는 이유는 접근 제어 / 부가 기능을 추가하기 위해서이다.
AOP
는 Spring Bean에만 적용 가능하며, 모든 AOP 기능을 제공하는 것이 아닌, Spring IoC와 연동하여 Enterprise Application 간에서 발생하는 흔한 문제에 대한 해결책을 지원하는 것이 주된 목적이다.
Aspect
: 위에서 설명한 흩어진 관심사를 모듈화 한 것. 주로 부가기능을 모듈화함.Target
: Aspect를 적용하는 곳 (Class, Method .. )Advice
: 실질적으로 어떤 일을 해야할 지에 대한 것, 실질적인 부가기능을 담은 구현체JointPoint
: Advice가 적용될 위치, 끼어들 수 있는 지점. 메서드 진입 지점, 생성자 호출 시점, 필드에서 값을 꺼내올 때 등 다양한 시점에 적용가능PointCut
: JointPoint의 상세한 스펙을 정의한 것. 'A란 메서드의 진입 시점에 호출할 것'과 같이 더욱 구체적으로 Advice가 실행될 지점을 정할 수 있음Transaction
이나 Logging
, Security
와 같이 여러 Module에서 공통적으로 사용하는 기능의 경우, 분리하여 관리 가능하다.영속성 관련 다양한 API 지원
Persistence
는 데이터를 생성한 프로그램의 실행이 종료되더라도 사라지지 않는 데이터의 특성을 의미한다.높은 확장성
Scalability