Spring Web Layer


오늘은 Spring Web Layer에 대해 알아보자.

스프링-웹-앱-아키텍처

위 사진을 보면 Web, Service, Repository, DTOs, Domain Model이 존재하는데 각 Layer계층 속 controller, service, 등이 포함되어 있고 프로젝트를 구성할 당시 각 레이어에 목적에 맞게 나누어 개발을 진행한다

스프링 웹 아키텍처와 관련하여 아래 레퍼런스 문서를 살펴보면 가장 크게 두가지 원칙을 따르는 것이 기본으로 소개한다.

 

1. 관심사 분리(SoC(Separation of concerns)) 원칙

 

  • 참고문서 - (https://en.wikipedia.org/wiki/Separation_of_concerns)
  • 관심분리라는 원칙을 간단하게 알고넘어가자면 각 부분(클래스 혹은 기능)이 별도의 관심사를 다루도록 컴퓨터 프로그램을 섹션분리하기 위한 설계원칙이다.
  • 여기서 관심사란 무엇일까? 를 한번 생각해보자. 관심사는 쉽게 말해 행동이라고 정의하고 이해하면 조금 더 이해하기 쉬웠던 것 같다.
    public void First(Object o) {
      log.info("First Function Call");
      System.out.println("My Parameter : " + o.toString());
      // Logic ...
    }
    public void Second(Object o) {
      log.info("Second Function Call");
      System.out.println("My Parameter : " + o.toString());
      //Logic ...
    }
    공통된 코드(관심사)를 확인할 수 있을 텐데 이러한 관심사들을 적절하게 나누는 것을 의미한다.
    public void printInfo(String functionName, Object o) {
      log.info("{} Function Call", functionName);
      System.out.println("My paramter : " + o.toString());
    }
    
    public void first(Object o) {
      printInfo("First", o);
      // Logic ...
    }
    public void second(Object o) {
      printInfo("Second", o);
      //Logic ...
    }
    이렇게 공통된 관심을 하나의 함수로 구현하여 분리했다
  • 위 코드의 로그와 프린트 부분을 하나의 함수로 바꾸어 구현한다면 다음과 같이 구현할 수 있다.
  • 아래 코드를 확인해 보자

위 사항을 조금 더 Spring입장으로 바라본다면 횡단 관심사(Cross-cutting concerns)라고 부르고 이 횡단관심사는 핵심로직이 아닌 위와 같이 로그, 프린트, 파라미터객체, 트랜잭션 등 을 의미한다.

이런 횡단관심사는 다시 또 AOP를 통해 횡단 관심사 분리를 할 수 있으니 AOP에 대한 설명을 한번 더 확인해 보면 좋을 것 같다.

 

2. KISS(Keep It Simple Stupid) 원칙

 

참고문서 - (https://en.wikipedia.org/wiki/KISS_principle)

 

  • 키스원칙이라 불리며 KISS는 "Keep it simple, stupid", "keep it short and simple", "keep it short and sweet" 의미이다
  • 간단하게 말하자면 코드를 단순하게 만드는 것이 좋고 불필요하게 장황하거나 복잡해지는 것을 피하라는 의미로 이해하면 좋겠다.

본론으로 돌아와서 위 두 가지를 간단하게 요약하자면 한 가지 기능만을 작동하도록 함수를 구현하되 단순하게 코드를 구성하라는 의미가 된다.

이러한 원칙을 따르며 각 레이어에 대한 특징을 살펴보자.

  1. Web Layer
    • 가장 앞단으로써 Spring MVC의 동작과정 속 DispatcherServlet처럼 클라이언트의 요청을 가장 처음으로 응답받는 곳이다. 그래서 이 WebLayer가 포함하고 있는 요소들도 Controller를 포함한 예외나필터가 포함되어 있다.
    • 또한 클라이언트의 첫 요청이기에 인증 및 권한 관련 부분도 여기에 해당한다.
  2. Service Layer
    • Web Layer보다 아래 속하며, 트랜잭션 경계 역할을 수행한다 또 서비스계층의 공용 API를 제공하고 권한부여등의 기능을 담당한다 쉽게 말해 WebLayer단에서 필요한 작은 기능단위들을 구현되어 있는 Layer라고 생각하면 좋을 것 같다.
  3. Repository Layer
    • 웹 애플리케이션의 최 하위계층으로 사용되는 데이터의 저장소와 통신을 담당합니다 쉽게 말해 데이터베이스와 통신역할을 수행한다.
  4. DTOs
    • DTO들의 집합을 의미한 것이고 DTO(Data Transfer Object)는 데이터 전송을 목적으로 하는 객체다
    • 이 객체는 애플리케이션 계층 간 데이터를 전달하는 용으로 사용된다.
  5. Domain Model
    • 도메인 모델은 다시 3가지로 나눌 수 있다
      1. 도메인 서비스
        • 도메인 서비스는 쉽게 말해 비즈니스로직이라 말하는 로직적인 관점들이 포함된 작업을 제공하는 비저장 클래스이다.
      2. 엔티티
        • 엔티티는 전체 수명주기동안 변경되지 않고 유지되는 개체이다.
      3. 개체
        • 개체는 속성이나 사물 등을 설명하며 고유 ID나 수명 주기가 없다

 

각 레이어 중 웹 레이어는 데이터 전송 개체만 처리해야 하고 서비스계층은 DTO를 매개변수로 사용해야 한다.

 

또 레포지토리계층은 엔티티를 매개변수로 사용해야 하며 각 계층에서의 구현을 통해 적절한 계층의 요소를 사용하는 것에 익숙해진다면 지금 설명하는 것들이 이해하는데 큰 도움이 될 거라 생각된다.

 

마지막으로 DTO사용이 필수적인지에 대한 질문에 따른 답변을 확인해 보자

 

실제로 구현시에 엔티티를 그냥 컨트롤러에서 반환하는 식으로도 구현을 진행할 수 있는데 이러한 DTO가 반드시 사용해야 하는 건지 의문을 가질 수 있다. 실제로 나도 VO와 DTO가 많이 헷갈리기도 했고...

그러나 위 사진을 자세히 보게 된다면 Public, Private으로 표현된 부분이 이 의문에 대한 시원한 답변이라 생각한다.

 

말 그대로 엔티티, 도메인모델들은 클라이언트입장에서는 감춰지고 보이지 않아야 하며 이 모델들 역시나 클라이언트 친화적으로 생성된 것이 아니기에 DTO를 통해 도메인을 숨기며 맞춤형 DTO로 제공할 수 있다는 점에서 사용한다

 

그리고 DTO를 변경하지 않는 한 도메인 모델의 변화에도 상관없이 제공될 수 있기에 운영, 유지보수 측면에서 장점이라 생각이 들었다.

 

 

오늘은 이것으로 Spring Web Layer에 대하여 알아보았다.

 

 

Reference

  1. https://www.petrikainulainen.net/software-development/design/understanding-spring-web-application-architecture-the-classic-w ay/
  2. https://velog.io/@smallcherry/Spring-스프링-웹-계층-Spring-Web-Layer
  3. https://jiwondev.tistory.com/122

'Spring, Spring Boot' 카테고리의 다른 글

Spring MVC 동작과정  (0) 2023.01.11
SOLID 객체지향 설계의 5가지 원칙  (0) 2022.05.13
Spring AOP 정리  (0) 2022.01.01
Spring 어노테이션(Annotation) 정리  (0) 2021.12.28

Spring MVC동작과정


Spring MVC는 어떤 순서로 동작할까?

이를 설명하기에 앞서 MVC라는 것이 무엇인지 모르는 분들을 위해 간략하게 설명하고 넘어가고자 한다.

MVC(Model, View, Controller)를 뜻하는 소프트웨어 설계 디자인패턴 중 하나다.

MVC-Design-Pattern

[이미지 출처] (https://hanamon.kr/mvc%EB%9E%80-mvc-design-pattern/)

위 그림과 같이 각 목적에 맞게역할을 나누어 개발함으로써 운영, 관리 측면에서 효율적이고 디버깅이나 가독성이 증가하게 된다.

 

실제로 우리가 옷장에 옷을 정리할때 그리고 주방에 식기류를 정리할 때 등 옷장, 주방 등의 공간을 나누어 해당 공간에 맞게 물건을 정리하는 것처럼 Controller, View, Model 역할에 맞게 소스코드를 정리해 두어 나중에 더 찾기 쉽고 관리하기 편해진다.

 

본론으로 돌아와 Spring MVC는 그럼 어떤형태를 가지고 있을까?

위 MVC 디자인패턴의 구조를 그대로 "Spring으로 가지고온다면 어떤 형태 일까?"를 생각해 보자

img

[이미지출처] (https://velog.io/@solchan/Spring-Spring-MVC%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80)

다음과 같은 형태로 구성되어 있다 잘 보면 처음 설명했던 MVC 중 Model이 무엇인지 모를 수 있는데 Service가 Model의 역할을 한다고 보면 된다.

 

스프링 공식문서에도 이 Spring MVC에 대해 자세한 설명이 나와있으니 한번 참고해 보면 좋을 것 같다.

[공식문서] (https://docs.spring.io/spring-framework/docs/current/reference/html/index.html)

 

위 그림을 자세하게 살펴본다면 처음으로 Client의 요청은 DispatcherServlet과 만나게 된다.DispatcherServlet은 클라이언트의 여러 요청에 맞는 공유 알고리즘을 제공하며 다양한 요청에 맞는 응답을 제공한다.

 

정리하자면 HTTP Protocol을 통해 들어오는 클라이언트의 여러 가지 요청을 제일 앞단에서 받아 적합한 컨트롤러에게 위임하는 프론트 컨트롤러(Front Controller)로 이해하고 넘어가자. (DispatcherServlet하나만 가지고 게시글 한 개를 쓸 만큼의 내용이 많기 때문에 지금은 간단하게만 이해하고 넘어간다)

 

 

이처럼 이 DispatcherServlet이 Spring MVC pattern에서 함께 사용된다.

 

이후 HandlerMapping과 ControllerAdapter(HandlerAdapter)를 알아보자.

 

이 HandlerMapping은 위 DispatcherServlet을 설명하던 중 여러 요청에 따라 특정 컨트롤러를 찾아서 알맞은 응답을 반환해 준다 라는 말 중 "특정 컨트롤러를 찾는"부분에 해당한다.

 

이 HandlerMapping이 선택한 Controller를 가지고 맞는 BLO(비즈니스로직)을 HandlerAdapter가 호출하며 요청에 맞는 로직이 작동하는 방식이다.

 

마지막으로 ViewResolver를 통해 결과를 보여줄 화면에 해당하는 View를 가지고 DispatcherServlet이 응답 결과를 생성한다.

 

 

이 하나의 과정이 Spring MVC가 동작하는 방식이며 단순히 글만 보고서는 완벽하게 이해가 안 될 수 있으니 동작과정 속 키워드를 한 번씩 검색해 보길 바란다.(DispatcherServlet, HandlerMapping, HandlerAdapter, ViewResolver 등)

오늘은 Spring MVC의 동작과정에 대하여 알아보았다.

Reference

  1. https://docs.spring.io/spring-framework/docs/current/reference/html/index.html
  2. https://mangkyu.tistory.com/18
  3. https://velog.io/@hsw0194/Spring-MVC-HandlerMapping의-동작방식-이해하기-1편

'Spring, Spring Boot' 카테고리의 다른 글

Spring Web Layer  (0) 2023.01.12
SOLID 객체지향 설계의 5가지 원칙  (0) 2022.05.13
Spring AOP 정리  (0) 2022.01.01
Spring 어노테이션(Annotation) 정리  (0) 2021.12.28

객체 지향 설계의 5가지 원칙(SOLID)


로버트 마틴이 좋은 객체 지향 설계의 5가지 원칙을 정리

  • 프로그래머가 시간이 지나도 유지 보수확장이 쉬운 시스템을 만들고자 할 때 이 원칙들을 함께 적용할 수 있다.
  • 이 5가지 원칙은 애자일(Agile) 소프트웨어 개발 과 적응적소프트웨어 개발의 전반적 전략의 일부다.

  • SRP : 단일 책임 원칙 (Single responsibility principle)

    • 단일 책임 원칙이란 OOP적인 관점에서 생각을 해보았을 때 한 클래스의 변경사항이 발생해도 다른 클래스 혹은 코드상의 다른쪽의 변경점이 적다면 단일 책임 원칙이 잘 지켜지고 있다고 생각해볼 수 있다. 즉 상속관계를 예를 들었을 경우 부모클래스의 정보 수정만으로 상속받은 자식클래스 혹은 자식클래스와 비슷한 서브 기능들의 정보가 알아서 전부 변경될 경우이다.
  • OCP : 개방-폐쇄 원칙(Open/closed principle)

    • 개방, 폐쇄 원칙은 "소프트웨어 요소는 확장에는 열려 있으나 변경에는 닫혀 있어야 한다" 라고 명시되어있다 이렇게 읽어보면 한번에 이해하기 쉽지 않은데 다형성을 생각해보면 쉽게 이해할 수 있다.

    • public class TempService{
        ParentRepository temp = new TempRepository();
        ParentRepository temp = new TempRepository2();
      
      }
    • 변경이 없다는 것은 코드의 변경이 없다는 말이고, 다형성을 사용하고 있으나 OCP가 지켜지지 않고 있다.

    • 클라이언트는 역할만 보고 구현체가 변경되더라도 상관이 없다 위 코드는 ParentRepository는 동일하지만 할당되는 객체는 변경해서 사용하고 있다.

  • LSP : 리스코프 치환 원칙 (Liskov substitution principle)

    • "프로그램의 객체는 프로그램의 정확성을 깨뜨리지 않으면서 하위 타입의 인스턴스를 바꿀 수 있어야 한다." 여기서 말하는 정확성이란 한 가지 기능에 대한 의미를 뜻한다 예를들어 상위 인터페이스의 메소드 중 jump라는 기능을 상속받은 하위클래스 2개가 인스턴스를 생성했다고하자(2개의 하위클래스는 각각 다른 도메인이다) 다람쥐, 캥거루 라는 2개의 하위인스턴스는 jump라는 함수를 실행했는데 여기서 캥거루는 일반적인 jump의 기능을 했지만 다람쥐는 jump를 실행했음에도 바닥을 기어가는 결과가 나온다면 리스코프 치환 원칙의 정확성이 깨지기 때문에 LSP원칙 위반이다.
  • ISP : 인터페이스 분리 원칙 (Interface segregation principle)

    • “특정 클라이언트를 위한 인터페이스 여러 개가 범용 인터페이스 하나보다 낫다.” 여기서 자동차 인터페이스를 운전 인터페이스와 정비 인터페이스로 분리했다고 가정하자. 그리고 사용자클라이언트는 운전자 클라이언트와 정비사 클라이언트로 분리한다. 만약 정비 인터페이스에서 수정이 일어났다고 하면 운전자 클라이언트에는 영향이 없겠으나, 범용적인 자동차 인터페이스로 사용하고 있었다면 이를 사용하던 운전자, 정비사 클라이언트 모두 수정이 필요했을 것이다. 예시를 통해 인터페이스가 특정 클라이언트를 위해 생성된다면 더 명확해지며 대체가능성이 높아진다.
  • DIP : 의존관계 역전 원칙 (Dependency inversion principle)

    • 프로그래머는 “추상화에 의존해야지, 구체화에 의존하면 안된다.” 의존성 주입은 이 원칙을 따르는 방법 중 하나다. 즉 구현클래스에 의존하지 말고 인터페이스에 의존하라는 뜻이다

Reference

'Spring, Spring Boot' 카테고리의 다른 글

Spring Web Layer  (0) 2023.01.12
Spring MVC 동작과정  (0) 2023.01.11
Spring AOP 정리  (0) 2022.01.01
Spring 어노테이션(Annotation) 정리  (0) 2021.12.28

Spring AOP

AOP란?

  • Aspect Oriented Programming: 관점 지향 프로그래밍
  • OOP 와 분리된 개념이 아니라, OOP에 기초를 두는 프로그래밍 방식
  • 하나의 프로그램을 관점(혹은 관심사)라는 논리적인 다위로 분리하여 관리하는 개념
  • 로깅, 감사, 선언적 트랜젝션, 보안, 캐싱 등 다양한 곳에서 사용된다.
  • 낮은 결합도에 높은 응집도는 기본으로 가지며, DI는 낮은 결합도를 위한 것이라면 AOP는 높은 응집도를 위한 것이다.
  • 엔터프라이즈 어플리케이션들은 보통 핵심 비즈니스 로직은 몇 줄 안되고 주로 로깅이나 예외, 트랜잭션 처리 같은 부가 코드가 대부분이다. 즉 비지니스 메소드의 복잡도는 증가하며 메소드들 마다 매번 반복해야하는 경우가 생긴다.
  • 이를 해결하기 위해서는 단순복사 붙여넣기만으로는 코드중복이 많아지며 유지보수가 힘들어지기 때문에 AOP를 통해 부가적인 공통 코드들을 효율적으로 관리해야한다.
  • 위 내용을 다르게 말하면 기존 OOP에서 공통 관심 기능을 여러 모듈에서 적용하며 발생하는 중복코드 양산의 한계를 극복하기위해 AOP가 탄생했다고 볼 수 있다.
  • 또 이러한 AOP는 흩어진 Aspect들을 모아서 모듈화 하는 기법이다.
    • *Aspect란?
    • 객체지향 언어의 클래스와 비슷한 개념이며 그 자체로 어플리케이션의 도메인 로직을 담은 핵심 기능은 아니지만, 많은 오브젝트의 걸쳐서 필요한 부가기능을 추상화 해놓은 것이다.
  • AOP에서 중요한 점으로는 관심 분리(Separation of Concerns) 가 있습니다.
    • 로깅, 예외, 트랜잭션 처리같은 코드들은 횡단 관심(Crosscutting Concerns) 라고하며, 핵심 비즈니스 로직은 핵심 관심(Core Concerns)라고 합니다.

AOP 용어와 개념

  • AOP는 핵심 로직에서 공통관심기능을 호출하지 않고 위빙(Weaving)이라는 작업을 통해 공통 관심 기능코드를 추가합니다.
  • 이런 위빙을 하기위해서는 언디에, 언제 추가해야할지 알아야 하며 Pointcut(어디에), Advice(언제)라고 합니다.
  • Joint Point : 모듈이 삽입되어 동작하게 되는 특정 위치(메서드 호출 등), 클라이언트가 호출하는 모든 비즈니스 메소드, 모든 메소드를 조이포인트로 생각하면 되고, 이 중에서 포인트컷이 결정된다.
  • Point Cut : 다양한 Joint Point 중에 어떤 것을 사용할지 선택, 즉 필터링된 Joint Point를 의미한다. 하나의 @Aspect class 안에 여러 개의 포인트컷을 선언할 수도 있습니다.
  • //포인트컷 선언의 예 @Pointcut("excution(* hello(...))") // 포인트컷 파라미터는 없으며 표현식으로 정의 "excution ~" private void all() { }
  • Advice : Joint Point에 삽입되어 동작할 수 있는 코드, 어드바이스는 횡단 관심에 해당하는 공통 기능의 코드를 의미하며 독립된 클래스의 메서드로 작성된다. 언제 동작할지는 스프링 설정에서 결정한다.
  • Advice도 Pointcut과 마찬가지로 하나 이상을 정의할 수 있고, Advice의 Annotation에는 이에 적용할 Point cut을 명시해야 한다.
    • @AspectJ에서 5가지의 Advice
      • before : 메서드 호출 전에 동작하는 advice
      • after : 예외 발생 여부와 관계없이 호출된 메서드의 동작이 완료되면 동작하는 Advice
      • after-returning : 예외 없이 호출된 메서드의 동작이 완료되면 동작하는 Advice
      • after-throwing : 호출된 메서드의 동작이 완료되면 동작하는 Advice
      • around : 메서드 호출 전과 후에 동작하는 Advice
  • /* *포인트컷에 이름을 부여해서 따로 정의하는 대신 어드바이스 메소드 어노테이션에 포인트컷 표현식을 넣어서 *적용하는 방법도 있다. */ @Around("excution(* *(...))") public Onject printParametersAAndReturnVal(ProceedingJointPoint pjp) throws Throwable{ return pjp; }
  • //어드바이스 정의 예 @Around("all()") // all() 메소드가 호출되기 전 과정을 모두 담을 수 있다. public Object aroundExample(ProceedingJointPoint pjp) throws Throwable{ //proceed 메서드는 클라이언트가 보낸 파라미터를 그대로 사용해서 타깃 오브젝트의 메소드를 호출하고 그 결과를 돌려줌 Object ret = pjp.proceed(); return ret; }
  • Weaving : Advice를 핵심 로직 코드에 적용하는 것, 위빙을 통해 비지니스 메소드를 수정하지 않고 횡단 관심에 해당하는 기능을 추가하거나 변경 가능.
  • Aspect : Point Cut + Advice, Aspect는 포인트컷과 어드바이스의 결합 => 어떤 포인트컷 메서드에 어떤 어드바이스 메소드를 실행할지 결정한다. 
  • Reference

'Spring, Spring Boot' 카테고리의 다른 글

Spring Web Layer  (0) 2023.01.12
Spring MVC 동작과정  (0) 2023.01.11
SOLID 객체지향 설계의 5가지 원칙  (0) 2022.05.13
Spring 어노테이션(Annotation) 정리  (0) 2021.12.28

+ Recent posts