스프링 프레임워크 기본개념

김주언·2022년 11월 5일
0

Spring

목록 보기
1/15
post-thumbnail

스프링의 핵심 개념

  • DI
  • IoC
  • AOP & AOP Proxy
  • AOP in Spring

1. 스프링 주요 구성 요소

  • IoC / DI
  • AOP
  • PSA

POJO

Plain Old Java Object
처음에 javax.ejb 인터페이스를 상속받지 않은, 무거운 EJB와는 반대로 경량의 자바 객체를 지칭하는 용어
POJO 대표적인 예로, JavaBean을 들 수 있는데, JavaBean은 기본 생성자와 멤버 필드에 접근할 수 있는 getter/setter 메소드를 가진 serializable(직렬화가 가능한)한 객체를 의미. POJO를 이용한 디자인이 널리 쓰임에 따라 POJO를 기본으로 하는 스프링이나 하이버네이트와 같은 프레임워크에서도 생겨남. 요즘에는 POJO는 (EJB 뿐만 아니라) 별도로 종속되지 않는 자바 객체를 통칭하여 의미한다.

PSA

Portable Service Abstractions - (쉬운) 서비스 추상화
성격이 비슷한 여러 종류의 기술을 추상화하고 이를 일관된 방법으로 사용할 수 있도록 지원. 
트랜잭션 서비스 추상화 : 여러 가지의 DB를 사용한다고 하면 Global Transaction 방식을 사용. 자바는 JDBC 외에 이런 글로벌 트랜잭션을 지원하는 트랜잭션 매니져를 지원하기 위한 API인 JTA(Java Transaction Api)를 제공. 높은 응집도와 낮은 결합도를 준수.


2. DI

Dependecy Injection, 의존성 주입

의존성 주입이라는 것이 스프링을 통해서 특별히 생겨난 개념이 아니고, 의존성 주입을 잘 지원해 주는 것이 스프링 프레임워크인 것임

의존성?

: 하나의 객체가 다른 객체 없이 제대로 된 역할을 할 수 없다는 것.
예를 들어, 레스토랑이라면 서버가 없어도 장사는 가능하지만, 셰프가 없으면 장사가 안댐
이처럼 하나의 객체가 다른 객체의 상태에 따라 영향을 받는 것을 의미한다.
A객체가 B 객체 없이 동작이 불가능한 경우 'A가 B에게 의존적이다' 라고 한다.

주입?

: 외부에서 밀어넣는 것
예를 들어, 레스토랑에 필요한 식재료를 직접 가서 사는지, 아니면 외부에서 배달을 받는지.
즉 필요한 객체를 얻기 위해 주체가 능동적인지 수동적인지에 대한 문제

의존성 + 주입

: 어떤 객체에게 필요한 객체를 외부에서 밀어넣는 것
왜 외부에서 밀어넣을까? ↓

예시

일체형

  • Composition : HAS-A 관계
  • A가 B를 생성자에서 생성하는 관계

분리 / 도킹(부착)형

  • Association 관계
  • A 객체는 다른 곳에서 만들어진 B 객체를 사용한다. (부품을 사용하는 것처럼)

A를 스마트폰, B를 배터리리라 하면,
일체형 스마트폰 (아이폰)은 바로 전원을 켜도 되지만,
배터리 탈부착 형태의 스마트폰 (갤럭시S)은 여기서는 배터리를 넣고, 전원을 넣어야 함.

일체형은 A라는 객체의 내부 프로세스에 대해 신경 쓸 필요가 없으며, 분리형은 A와 B를 개별적으로 세팅해 주어야 함. 단, 분리형은 내가 원하는 것(다른 배터리)으로 바꾸어 부착할 수 있음. 이것을 DI의 개념이라 보면 됨.

분리형으로 개발 시 각 객체간의 결합도를 낮출 수 있으며, DI의 목적이 결합도를 낮추는 것!

결합도를 낮춰야 개발 시 편리하고 추후 유지보수가 편리하다!

2.1 DI 종류

  1. Setter Injection
  2. Construction Injection
 // Setter Injection 
 B b = new B();
 A a = new A();
 a.setB(b);
 
//Construction Injection
 B b = new B();
 A a = new A(b);

위의 코드는 객체 지향 프로그래밍의 기본 개념이다. 단지 스프링은 이러한 과정을 동적으로 자동화해주는 것이다.


3. 스프링에서의 DI

어떠한 제품 A를 만든다고 가정하자.

일체형 프로그램의 경우 아래의 단계를 거친다.

  1. 제품 A1을 만들기 위해서 부품 A1이 필요하다.

  2. 제품 A1은 내부에서 부품 A1을 생성하기 시작한다.

    → 그런데?! 부품 A1을 만들려고 하니까 부품 A1은 또 부품 B1이 필요하다..! 부품 A1은 부품 B1을 만들기 시작함

    → 아니 또 그런데?! 부품 B1을 만드려고 보니 또 부품 C1이 필요하네..? 또 만든다...

    → 부품 B1이 부품 C1을 만들었다.

  3. 부품 B1에 부품 C1을 넣어서 B1을 완성한다.

  4. 부품 A1에 부품 B1을 넣어서 A1을 완성한다.

  5. 제품 A1에 부품 A1을 넣어서 제품 A1을 완성했다.

하하... 곤란하다

조립형 프로그램의 경우 아래의 단계를 거친다

  1. 제품 A2를 만들기 위해서는 부품 A2가 필요하다. 근데 부품 A2를 만들기 위해서는 또 부품 B2가 필요하고, 부품 B2를 만드려니 부품 C2가 필요하다.
    → 근데 누가 C2를 만들어놨네? B2는 그냥 갖다쓰기만 한다. B2가 완성된다.

    → 부품 A2는 완성되어있는 B2를 가져다 쓴다. 부품 A2가 완성됐다

  2. 제품 A2는 완성되어 있는 A2를 그냥 갖다 쓴다

개꿀이다

즉, 조립형의 경우 작은 부품부터 시작하여 큰 부품으로 이동하며 조립을 한다.
이를 Inversion of Control, IoC라고 한다. (제어의 역전)

기본적인 완제품 제작 순서와는 다르게 작은 부품부터 큰 부품으로, 제품을 만드는 순서가 역순 (Inversion of Control).그래서 IoC라는 이름이 붙었으며, 이러한 일련의 작업을 스프링은 컨테이너라는 곳에 담아서 처리하여 스프링을 IoC컨테이너라 함.

스프링은 완성품을 만드는 것보다 부품을 모아서 조립하는 것을 도와줌.
즉, 이러한 DI 구조를 개발자가 좀 더 쉽고, 간편하게 사용할 수 있도록 지원해 주는 프레임워크 중의 하나가 스프링.

스프링에서 DI란,
부품들을 생성하고, 제품을 조립해주는 공정과정을 대신해주는 라이브러리 역할자

  • 개발 핵심 처리 루틴의 수정 없이 제품(객체)를 다른 제품(객체)로 쉽게 대체하여 생성 가능하도록 하는 역할을 함.

  • 명세서에 따라서 자동적으로 부품을 활용하여 제품을 조립.

  • 생성하기 원하는 객체를 명세서(XML)에 기술하고, 그 부품과 의존성(Dependency)들을 보관하는 일을 처리. 그러한 데이터를 보관하는 공간을 컨테이너라 함. (IoC 컨테이너 = 스프링에서는 ApplicationContext)

스프링은 ApplicationContext라는 존재가 필요한 객체들을 생성하고, 필요한 객체들을 주입해주는 역할은 해 준다. 따라서 스프링을 사용하면 기존의 프로그래밍과 달리 객체와 객체를 분리하여 생성하고, 이러한 객체들을 엮어주는 작업(wiring)을 하는 형태로 개발을 진행한다.


3.1 DI 구현

스프링에서는 객체의 생성과 조립에 대한 내용이 JAVA 소스 코드상으로 존재하지 않고, 별도의 텍스트 파일 (XML 설정 파일)에 분리되어 존재한다.

즉 JAVA소스의 컴파일 없이 XML 변경만으로 객체의 생성과 조립을 관리할 수 있는 것

JAVA로 DI 구현하는 경우

Record record = new SprRecord();
RecordView view = new SprRecordView();
view.setRecord(record); // Injection 
view.input();
view.print();

실제 값을 view에 바로 주입하는 것이 아닌 setRecord() 함수를 호출하여 주입함.

스프링으로 DI 구현하는 경우 = XML을 사용하는 경우

XML (스프링 DI) : 객체 생성 시, 패키지명을 포함한 풀 클래스 네임 작성.
XML에 작성된 명세서를 보고, IoC컨테이너가 각 객체를 생성하고, 값을 주입해줌.
여기서 ApplicationContext 가 IoC컨테이너 역할을 함.

XML (config.xml)

<bean id=“record” class=“di.SprRecord”></bean> // 빈 객체 생성 
<bean id=“view” class=“di.SprRecordView”> // 빈 객체 생성 
  <property name=“record” ref=“record”></property> // setRecord() 호출  
</bean> 

JAVA단

// XML을 파싱하여 컨테이너에 담는 작업 
ApplicationContext ctx = new ClassPathXmlApplicationContext(“config.xml”);
RecordView = (RecordView) ctx.getBean(“view”);
  • XML을 활용(스프링 DI)하는 경우는 VIEW에 대한 객체만을 요청했을 뿐, 실제 내부적인 사항은 JAVA코드 상에 드러나지 않음.
  • 새로운 클래스의 bean객체를 만들어 XML에 주입만 시켜줘도, 기존 소스 변경 없이 새로운 형태의 객체 적용이 가능함.

XML 예시

XML (스프링 DI) config.xml 
 
1)
<bean id=“record” name=“r1,r2 r3;r4” class=“di.SprRecord”>   
  <property name=“kor” value=“20”></property>
</bean>

2)
<bean id=“record” name=“r1,r2 r3;r4” class=“di.SprRecord”>   
  <constructor-arg value=“20”></constructor-arg>
</bean>

3)
<bean id=“record” name=“r1,r2 r3;r4” class=“di.SprRecord”>    
  <constructor-arg name=“kor” value=“20”></constructor-arg>
</bean>

4)
<bean id=“record”  name=“r1,r2 r3;r4” class=“di.SprRecord”    p:kor=“50” p:eng=“60” p:math=“70”>
  
5)
<bean id=“view” class=”di.SprRecordView”>    
  <property name=“record” ref=“record”></property>
</bean> 
  
  
id : 빈 객체 고유 이름 (접근 가능자)
name : 객체의 이름(별칭)
class : 생성할 클래스 
constructor-arg : 초기값 설정 (생성자 함수 사용)
property : 초기값 설정 (Setter함수 사용)
  1. 이름이 record인 빈 객체 생성 / 별명 4개 : r1,r2,r3,r4 / SprReocrd 클래스 객체 생성.
    초기값으로 kor 라는 프로퍼티에 20값 대입 (set함수가 존재해야 위와 같은 프로퍼티 설정이 가능).

  2. 이름이 record인 빈 객체 생성 / 생성자(인자가 하나인)를 통해서 값 대입 & 생성.

  3. 생성자 중에서 kor 값을 입력받는 생성자를 통해서 20값 대입하고, 생성.

  4. 3개의 인자를 받는 생성자를 통해 kor = 50, eng = 60, math = 70 대입 & 생성.

  5. 생성된 record 객체를 set함수를 통해 프로퍼티에 저장하고 SprRecordView를 생성.

값을 대입하는 경우에는 value, 참조(레퍼런스)를 대입하는 경우에는 ref 를 사용.



4. IoC

IoC 컨테이너 ( 스프링 컨테이너 )

어떠한 객체의 명세서를 작성하고, 스프링 라이브러리는 해당 명세대로 객체를 생성한다. 생성된 객체들과 디펜던시들을 보관하는 공간을 IoC 컨테이너라고 한다.

  • Bean
    스프링이 제어권을 갖고 직접 만들고 관계를 부여하는 오브젝트

  • Bean Factory
    빈의 생성과 관계 설정 제어를 담당하는 IoC 오브젝트이다.
    이를 좀 더 확장한 ApplicationContext를 주로 사용한다.

  • ApplicationContext ( = IoC 컨테이너 = 스프링 컨테이너 )
    DI를 위한 빈 팩토리에 엔터프라이즈 애플리케이션을 개발하는데 필요한 여러가지 컨테이너 기능을 추가한 것
    애플리케이션 컨텍스트는 그 자체로 IoC와 DI를 위한 빈 팩토리이면서 그 이상의 기능을 가진다.

  • 설정 정보 / 메타 정보
    구성 정보 또는 형상정보를 말한다. XML 파일

컨테이너가 본격적인 IoC 컨테이너로서 동작하려면 POJO 클래스와 설정 메타 정보가 필요하다. 즉 스프링 애플리케이션은 POJO 클래스와 설정 메타정보를 이용하여 IoC 컨테이너가 만들어주는 오브젝트의 조합이라고 볼 수 있다.



profile
학생 점심을 좀 차리시길 바랍니다

0개의 댓글