Home Spring Boot Guide - 3
Post
Cancel

Spring Boot Guide - 3

Spring Guide 시리즈는 스프링부트 핵심 가이드 - 스프링 부트를 활용한 애플리케이션 개발 실무 책을 통해 학습 및 정리한 내용을 담고 있습니다.

해당 시리즈를 통해 스프링 부트를 학습해보기 위해서는 어느 정도의 기반 지식이 필요하다. 레이어드 아키텍처, 디자인 패턴, REST API에 대해 간략하게 정리해보고 가능하다면 추후에 자세히 정리해보자.


레이어드 아키텍처 (Layered Architecture)

레이어드 아키텍처는 애플리케이션의 컴포넌트들을 보다 직관적으로 관심사가 유사한 것들끼리 묶어서 수평하게 작성한 구조를 의미한다. 그럼 이런 레이어(계층)는 몇개의 층으로 구성을 해야하느냐? 그건 우리가 어떻게 설계하느냐에 따라 수가 달라진다. 일반적인 경우에는 3~4 Layer 를 구성한다. 그럼 3계층인 경우에는 구조가 어떠한지 살펴보자.

flowchart TD
    A[프레젠테이션 계층] --- B[비즈니스 계층] --- C[데이터 접근 계층]
    
    A[프레젠테이션 계층] --- COMP1
    B[비즈니스 계층] --- COMP2
    C[데이터 접근 계층] --- COMP3
    subgraph COMP1
        direction LR
        D(컴포넌트) --- E(컴포넌트) --- F(컴포넌트)
    end

    subgraph COMP2
        direction LR
        G(컴포넌트) --- H(컴포넌트) --- I(컴포넌트)
    end

    subgraph COMP3
        direction LR
        J(컴포넌트) --- K(컴포넌트) --- L(컴포넌트)
    end

각 계층에 대한 간단한 설명

여기서 언급하는 프레젠테이션, 비즈니스, 데이터 접근 계층들에 대해서 간략하게 정리하면 아래와 같다.

프레젠테이션 계층
최상단 계층으로, 클라이언트의 요청을 해석하고 응답하는 역할. 별도의 비즈니즈 로직을 포함하지 않는다.
비즈니스 계층
제공하고자 하는 기능을 정의하고, 도메인 객체를 통해 업무를 위임하는 역할
데이터 접근 계층
데이터베이스에 직접 접근하는 모든 작업을 수행하는 역할

특징

이러한 계층형 구조를 적용하면 레이어마다 바로 아래의 레이어만 의존 주입을 하게 된다. 또 각각의 레이어들은 이미 자신들의 관심과 역할에 따라 분리가 되어 있는 상태이기 때문에 다른 레이어들을 방해하거나 침범할 수 없게 된다. 이는 우리가 프로젝트를 설계하고 개발할 때, 역할이 보다 명시적이기 때문에 가독성 측면에서 유리하기도 하고 기능 구현에 효율도 높여주게 되는 것이다. 나아가 테스트를 진행할 때에도, 독립적인 레이어들에 대해서 단위 테스트 하기에도 용이해진다는 장점이 있다.

Express, Prisma를 사용했던 프로젝트에서도 해당 아키텍처를 적용했었는데, 가장 크게 느껴졌던 장점은 무엇보다 협업 시에 팀원들이 각 코드들이 어떤 역할을 가지는지 명확하게 이해할 수 있어 유지보수가 굉장히 편했다는 것이다. 이후 Spring과 비슷한 아키텍처를 가져간 Node.js 계열의 NestJS 또한 기본적으로 관심사에 따라 레이어를 나누어 설계하는 것이 기본이다. 이쯤 생각해보니 NestJSSpring을 많이 따라잡으려 노력했던 것 같다.

spring-boot-starter-web을 사용하는 Spring Boot에서는 기본적으로 Spring MVC 구조를 가지게 된다.

flowchart TD
    subgraph 프레젠테이션 계층
        direction TB
        A(클라이언트) <--> B(Dispatcher Servlet)

        B(Dispatcher Servlet) <--> REST

        subgraph REST
        direction TB
            C(핸들러 매핑) --> D(RestController)
            D(RestController) --> E(MessageConverter)
            E(MessageConverter) --> F(Response HTTP)
        end
    end

    D <--> G

    subgraph 비즈니스 계층
        direction TB
        G(서비스)
    end

    G <--> H

    subgraph 데이터 접근 계층
        direction TB
        H(DAO)
    end

    I[/데이터베이스\] <--> H
    

위의 모습이 스프링에 레이어드 아키텍처를 적용한 모습이다. MVC의 의미를 알 필요가 있는데, 단순하게 Model-View-Controller을 줄인 것이다. DAO에 대해서도 궁금할 수 있는데, 이는 나중에 언급될 내용이다. 미리 감을 잡아보자면 Spring Data JPARepository가 담당하는 부분이라고 말할 수 있겠다.

일반적인 레이어드 아키텍처의 계층별 역할과 스프링의 레이어드 아키텍처 계층별 역할은 거의 비슷하다.


디자인 패턴 (GoF)

나는 공부하면서, GoF가 대체 뭐길래 그렇게 언급되는지 궁금했다. 근데 그냥 이런 디자인 패턴을 체계화한 4명의 사람을 Gang Of Four라고 불렀고 이를 줄여 말하니 GoF가 된 것이다. 큰 의미가 없어서 조금 당황했다. 각설하고, 이러한 디자인 패턴은 우리가 앞으로 어플리케이션을 작성할 때 직면할 수 있는 여러 문제들은 대부분 유사성을 띄기에 해결 방법도 비슷해 동일하게 적용시킬 수 있다는 의미를 가지고 있다.

이러한 디자인 패턴은 커뮤니케이션에서 가장 효율적일 것이라고 생각한다.

팀원과의 소통을 예로 들어보자.

1
2
3
A: "프로그램 전역에서 Hello라는 클래스를 바로 얻어서 사용하기로 하고, 
불필요한 메모리 낭비가 일어날 수도 있으니까 접근제한자를 잘 설정하고 어쩌구 저쩌구..."
B: ???

A와 B가 프로젝트 기간 내내 비슷하게 대화한다면 상세히 설명받고 이해할 수는 있겠지만, 당장이라도 프로젝트를 마치고 싶은 B는 금방 피로해질 것이다. 나는 디자인 패턴을 깊게는 아니더라도 어느정도 알고 있다면 이런 대화를 깔끔하게 마무리할 수 있다고 생각한 것이다.

1
2
A: "얘는 전역 접근도 가능하게 하고, 메모리 낭비도 줄일 겸 싱글톤 패턴을 적용해보자."
B: "OK NICE" 

디자인 패턴이 항상 정답일 수는 없다. 특정 문제에 직면했을 때, 최적의 패턴을 잘 골라서 적용시키는 것이 좋다.


디자인 패턴의 종류

디자인 패턴에는 다양한 종류가 있다. 정말 다양하다. 크게 분류하자면 아래와 같이 분류할 수 있다.

flowchart LR
    생성패턴 --- 구조패턴 --- 행위패턴

각각의 패턴은 아래와 같이 설명할 수 있다.

생성패턴
말 그대로 객체의 생성과 관련된 패턴
구조패턴
객체를 조합하여 더 큰 구조를 만들어내는 패턴
행위패턴
클래스 사이에서의 어떤 알고리즘이나 책임을 분배하는 일에 관련된 패턴

그리고 이 3가지 패턴 내에 세부적으로 적게는 5개 많게는 11개까지 있다. 내부에는 우리가 한번쯤 들어봤을 팩토리 패턴, 싱글톤 패턴, 옵저버 패턴, 프록시 패턴 등이 존재한다. 이 디자인 패턴에 대해서는 추후에 정리해보도록 하자.


REST API

많이 중요한 REST API이다. 현재 대중적으로 가장 많이 사용되는 어플리케이션 인터페이스라고 할 수 있기 때문이다. 이 친구가 있기에 클라이언트가 서버에 접근하여 리소스를 조작할 수 있다.

REST가 뭐지?

RESTRepresentational State Transfer의 줄임말이다. Transfer가 붙었으니 무언갈 주고 받는 모습을 생각할 수 있는데, 그게 맞다. 다만 자원(리소스)에 초점을 맞추어 해당 자원에 이름을 정하고 URI에 명시하여 HTTP 메서드와 함께 그 자원의 상태를 주고 받는 것이다. 처음 REST를 이해하려고 하다보면 자원이 뭐고, 상태를 주고 받는 것이 무엇인지 와닿지 않을 수 있는데 이는 직접 REST API를 구현하다보면 자연스레 이해할 수 있을 것이라고 생각한다.

지금은 그냥 자원에 초점을 맞추어 자원의 상태를 주고 받는 시스템 아키텍처 중의 하나이다 라고 이해하는 것이 가장 편할 것 같다.

그럼 REST API는?

API가 붙은 것뿐이다. APIApplication Programming Interface의 줄임말로 어플리케이션에서 제공해주는 인터페이스이다. 이 인터페이스를 이용하여 서버나 프로그램에 연결할 수 있다. REST APIAPI 앞에 REST가 붙으면서 방금 설명한 아키텍처를 따르겠다 라는 특징이 붙은 것이다. 그리고 이 REST 아키텍처를 잘 구현해낸 웹 서비스를 RESTful하다고 말할 수 있다.

REST 아키텍처의 특징

유니폼 인터페이스
유니폼 인터페이스는 일관된이라는 특징을 가지고 있다. 기본적으로 REST 서버는 HTTP를 따르고 있어서, 그 어떤 프로그래밍 언어, 플랫폼에 종속되지 않고 모두 호환할 수 있다는 말이다.
무상태성
서버는 클라이언트에서 보낸 요청에 대한 세션, 쿠키 등의 정보를 별도로 보관하지 않는다. 그래서 A라는 클라이언트가 여러 요청을 보낸다고 한들 다 독립적인 요청으로 인식하게 된다. 이러한 무상태성 덕분에 서버에서 별도로 정보를 관리하지 않아서 비즈니스 로직의 자유도를 높이고 자칫 복잡해질 설계 또한 단순하게 만들어준다.
캐시 가능성
유니폼 인터페이스를 설명하면서 REST 서버는 HTTP 를 따른다고 언급했는데, HTTP는 캐싱 기능이 존재한다. HTTP에 대한 내용도 추후에 정리해보자. 여튼, 덕분에 REST도 캐싱 기능을 이용하여 Modified이지 않은 데이터들에 대해 트랜잭션을 줄여 서버측 효율을 높일 수 있고, 사용자의 입장에서는 불필요한 데이터 로드를 기다릴 필요가 없어 사용자 경험도 향상시킬 수 있다.

REST URI를 설계하는 규칙

RESTful 하도록 URI를 설계하는 데에는 규칙이 존재한다.

  • URI 마지막에 / 를 포함하지 말자.

O : http://example.com/user

X : http://example.com/user/

  • _를 사용하지 말자. 띄어쓰기가 꼭 필요하다면 -를 이용하자.

O : http://example.com/user-name

X : http://example.com/user_name

  • 행위말고 결과를 적자, 동사가 아닌 명사를 적자.

O : http://example.com/user/12631

X : http://example.com/find-user/12631

  • 소문자로 작성하자.
    대문자 사용은 가능한 피하는 것이 좋다. 모두가 그런 것은 아니지만, 일부 웹 서버 OS에서 대소문자를 구분하여 인식할 수도 있다.
  • 파일의 확장자는 포함하지 말자.
    앞에서 언급된 HTTP에는 Accept 라는 헤더가 있는데, 그곳에 파일의 확장자를 명시하는 것이 좋다.
This post is licensed under CC BY 4.0 by the author.
Contents

Spring Boot Guide - 2

Spring Boot Guide - 4