[Spring] SpringFramework의 특징

Minit88·2023년 3월 31일
0

Spring

목록 보기
2/16
post-thumbnail

Lab_01 : SpringFramework 특징

1. POJO(Plain Old Java Object)


위 Spring 삼각형 하나로 Spring의 핵심 개념들을 모두 표현 하고 있다고 해도 과언이 아니다.

POJO는 Spring에서 사용하는 핵심 개념들에 둘러 싸여져 있는 모습이다. 이는 POJO라는 것을 IoC/DI, AOP,PSA를 통해서 달성할 수 있는 것을 의미한다.

POJO 프로그래밍으로 작성한 코드라고 불리기 위한 조건

  • Java나 Java의 스펙에 정의된 것 이외에는 다른 기술이나 규약에 얽매이지 않아야 한다. ex) getter , setter을 가지고 코드를 구현하는 경우
    • 특정 기술을 상속해서 코드를 작성하게 되면 나중에 애플리케이션의 요구사항이 변경되서 다른 기술로 변경하려면 본래 클래스를 명시적으로 사용했던 부분을 전부 다 일일이 제거하거나 수정해야 한다.
  • 특정 환경에 종속적이지 않아야 한다.
    • 애플리케이션 코드에서 사용하고 있는 API를 걷어내고 수정을 해야하는 상황 또는 애플리케이션을 전부 뜯어 고쳐야될지도 모르는 상황에 직면 가능함.

위 조건을 만족하는 나머지가 모두 POJO인 것은 아니다 .

진정한 POJO란 객체지향적인 원리에 충실하면서, 환경과 기술에 종속되지 않고 필요에 따라 재활용될 수 있는 방식으로 설계된 오브젝트를 말한다.

POJO 프로그래밍이 필요한 이유

  • 특정 환경이나 기술에 종속적이지 않으면 재사용 가능하고, 확장 가능한 유연한 코드를 작성할 수 있다.
  • 저수준 레벨의 기술과 환경에 종송적인 코드를 애플리케이션 코드에서 제거함으로써 코드가 깔끔해진다.
  • 코드가 깔끔해지기 때문에 디버깅에도 상대적으로 쉽다
  • 특정 기술이나 환경에 종속적이지 않아 테스트가 단순해짐
  • 객체지향적인 설계를 제한없이 적용할 수 있다.

POJO와 Spring의 관계

Spring은 POJO 프로그래밍을 지향하는 Framework임과 세가지 기술을 지원하고 있다.

  • IoC/DI,AOP,PSA

IoC(Inversion of Control)

IoC는 제어의 역전으로 Spring 삼각형을 이루는 기능 중 하나이다.

IoC란?

Library는 애플리케이션 흐름의 주도권이 개발자에게 있고, Framework은 애플리케이션 흐름의 주도권이 Framework에 있다.

여기서 말하는 애플리케이션 흐름의 주도권이 뒤바뀐 것을 제어의 역전 즉, IoC이다.

IoC를 이해하기 위해 샘플 코드를 보면

Java 콘솔 애플리케이션의 일반적인 제어권

public class Example2_10 {
    public static void main(String[] args) {
        System.out.println("Hello IoC!");
    }
}

일반적으로 위와 같은 Java콘솔 애플리케이션을 실행하려면 main() 메서드가 있어야 한다. 코드에서는 main() 메서드가 호출되고 난 다음에 System 클래스를 통해서 static 멤버 변수인 out의 println()을 호출한다.

즉, 개발자가 작성한 코드를 순차적으로 실행하는게 일반적인 애플리케이션 제어 흐름이다.

Java 웹 애플리케이션에서 IoC가 적용되는 예

위 그림은 서블릿 컨테이너의 서블릿 호출 예이다.

웹에서 동작하는 애플리케이션의 경우 클라이언트가 외부에서 접속해서 사용하는 서비스이기 때문에 main() 메서드가 종료되지 않아야 한다.
그런데, 서블릿 컨테이너에는 서블릿 사양에 맞게 작성된 서블릿 클래스만 존재하지 별도의 main() 메서드가 존재하지 않는다.

main() 메서드처럼 애플리케이션이 시작되는 지점을 엔트리 포인트(Entry Point)라고도 부른다

서블릿 컨테이너 경우, 클라이언트의 요청이 들어올 때마다 서블릿 컨테이너 내의 컨테이너 로직인 service()가 서블릿을 직접 실행시켜 주기 때문에 main() 메서드가 필요없다.

이 경우에는 서블릿 컨테이너가 서블릿을 제어하고 있기 때문에 애플리케이션의 주도권은 서블릿 컨테이너에 있다. 바로 서블릿과 웹 애플리케이션 간에 IoC(제어의 역전) 개념이 적용되어 있다.

Spring 에서는 IoC 개념이 DI를 통해 적용되어 있다.

DI(Dependency Injection)

의존성 주입이란?

객체지향 프로그래밍에서 의존성이라고 하면 대부분 객체 간의 의존성을 의미한다.

의존성을 예시로 들면, A,B 두 클래스가 있다고 하고, A 클래스가 B 클래스의 메소드 기능을 사용할 때 'A클래스는 B클래스에 의존한다' 라고 할 수 있다.

의존성의 주입은 생성자를 통해서 어떤 클래스의 객체를 전달 받는 것을 '의존성 주입' 이라고 한다. 즉, 생성자의 파라미터로 객체를 전달하는 것을 외부에서 객체를 주입한다라고 표현이 된다.
[그림] 의존성 주입 예시코드

의존성 주입시 느슨한 결합의 필요성


[그림] 느슨한 결합이 이루어지지 않은 경우

목록 조회 API로 Stub을 제공하기 위해 MenuServiceStub 클래스를 사용한다. 자세히 보면 MenuController (MenueServiceStub menuService) 에서 MenuServiceStub을 이용하려 하는데 MenuController 와 CafeClient에서 MenuService를 사용하고 있어 MenuServieSturb 클래스로 바꾸어 사용하고 있음을 알 수 있다.

이 클래스를 사용할 대상이 수십, 수백군데가 되게 되면 불필요하게 바꿔야 하는 상황이 일어나게 된다.

이를 방지하기 위해 느슨한 결합을 이용한다.

느슨한 결합은 인터페이스를 통해서 구현이 가능하다.

MenuServiceStub가 MenuServie 인터페이스를 구현함과 동시에 MenuController은 MenuService를 사용하고 있어 클래스 변경없이 MenuService를 사용할 수 있게 된다.

즉, 인터페이스를 통해서 객체간의 결합을 느슨하게 변경해줄 수 있게 된다.

AOP(Aspect Oriented Programming)

AOP란 관심지향 프로그래밍이다.

AOP에서 Aspect는 부모들이 가지고 있는 아기의 건강 같은 관심사와 마찬가지로 애플리케이션에 필요한 기능 중에서 공통적으로 적용되는 공통 기능에 대한 관심과 관련이 있다.

공통 관심 사항과 핵심 관심 사항

  • 애플리케이션을 개발하다보면 애플리케이션 전반에 걸쳐 공통적으로 사용되는 기능들이 있기 마련인데, 이러한 공통 기능들에 대한 관심사를 바로 공통 관심 사항(Cross-cutting concern)이라고 한다.
  • 커피 전문점의 주인이 고객에게 제공하는 커피 메뉴를 구성하기 위해 커피 종류를 등록하는 것과 고객이 마시고 싶은 커피를 주문하는 기능은 애플리케이션의 핵심 관심 사항에 해당된다.

PSA(Portable Service Abstraction)

PSA는 클라이언트가 추상화 된 상위 클래스를 일관되게 바라보며 하위 클래스의 기능을 사용하는 것이 바로 일관된 서비스 추상화(PSA)의 기본 개념이다

PSA를 이해하기 위해 예시를 들면,

미취학 아동을 관리하는 애플리케이션을 설계하면서 아이 클래스를 일반화(추상화)한다라고 하면

아이의 일반적인 속성으로는 이름,키,몸무게,혈액형,나이 등이 있고,

아이가 동작할 수 있는 동작으로는 웃다,울다,자다,먹다 등이 있다.

이렇게 추출한 아이의 일반적인 특징을 클래스로 작성하면
로 표현이 되고, 아이의 연령대 별로 해당 메소드를 기능들을 사용 다시 말해, 상위 클래스(Child)에서 하위 클래스(연령 별 기능 구현) 로 확장해 기능을 사용하기 위해

하위 클래스는 아래와 같이 나타낼 수 있고,

/ NewBornBaby.java(신생아)
public class NewBornBaby extends Child {
    @Override
    protected void smile() {
        System.out.println("신생아는 가끔 웃어요");
    }

    @Override
    protected void cry() {
        System.out.println("신생아는 자주 울어요");
    }

    @Override
    protected void sleep() {
        System.out.println("신생아는 거의 하루 종일 자요");
    }

    @Override
    protected void eat() {
        System.out.println("신생아는 분유만 먹어요");
    }
}

// Infant.java(2개월 ~ 1살)
public class Infant extends Child {
    @Override
    protected void smile() {
        System.out.println("영아는 많이 웃어요");
    }

    @Override
    protected void cry() {
        System.out.println("영아는 종종 울어요");
    }

    @Override
    protected void sleep() {
        System.out.println("영아부터는 밤에 잠을 자기 시작해요");
    }

    @Override
    protected void eat() {
        System.out.println("영아부터는 이유식을 시작해요");
    }
}

// Toddler.java(1살 ~ 4살)
public class Toddler extends Child {
    @Override
    protected void smile() {
        System.out.println("유아는 웃길 때 웃어요");
    }

    @Override
    protected void cry() {
        System.out.println("유아는 화가나면 울어요");
    }

    @Override
    protected void sleep() {
        System.out.println("유아는 낮잠을 건너뛰고 밤잠만 자요");
    }

    @Override
    protected void eat() {
        System.out.println("유아는 딱딱한 걸 먹기 시작해요");
    }
}

위의 하위 클래스를,

위 코드처럼 연령별로 사용할 수 있게 된다.
즉, 일관된 방식으로 해당 서비스의 기능을 사용할 수 있게 된다.

이처럼 애플리케이션에서 특정 서비스를 이용할 때, 서비스의 기능을 접근하는 방식 자체를 일관되게 유지하면서 기술 자체를 유연하게 사용할 수 있도록 하는 것을 PSA(일관된 서비스 추상화)라고 한다.

profile
" To be BE "

0개의 댓글

관련 채용 정보