
: 스프링 부트를 활용한 애플리케이션 개발 실무
📝 목차
2장. 개발에 앞서 알면 좋은 기초 지식
2-1. 서버 간 통신
2-2. 스프링 부트의 동작 방식
2-3. 레이어드 아키텍쳐
2-4. 디자인 패턴
- 디자인 패턴의 종류
- 생성 패턴
- 구조 패턴
- 행위 패턴
2-5. REST API
- REST란?
- REST API란?
- REST의 특징
- REST의 URI 설계 규칙
서비스 단위로 개발 = 단일 서비스 아키텍처
문제점 ➡️ 서버를 업데이트 하거나 유지보수 할 때마다 서비스가 중단
해결 방법 ➡️ 마이크로서비스 아키텍처 (MSA; Microservice Architecture)
: 서비스 규모를 작게 나누어 구성한 아키텍처 = 기능별로 나눠서 개발
⬇️ 단일 서비스 아키텍처 vs 마이크로서비스 아키텍처

각 서비스 간에 통신해야 하는 경우가 발생
이런 상황에서의 통신 ➙ 서버간 통신
: 한 서버가 다른 서버에게 통신을 요청하는 것
💻클라이언트 ↔️ 💻 서버
다양한 통신 방식을 적용할 수 있지만 가장 많이 사용하는 방식
⭐ HTTP/HTTPS방식
스프링 부트에서 spring-boot-start-web모듈을 사용하면, 기본적으로 톰캣(Tomcat)을 사용하는 스프링 MVC구조를 기반으로 동작!
톰캣(Tomcat) = WAS 역할 + 서블릿 컨테이너 역할
: 클라이언트의 요청을 처리하고 결과를 반환하는 자바 웹 프로그래밍 기술
서블릿 ➡️ 서블릿 컨테이너 (Servlet Container)에서 관리
서블릿 컨테이너 : 서블릿 인스턴스를 생성, 관리하는 역할을 수행하는 주체
⬇️ 일반적인 웹 요청이 들어왔을 때의 스프링부트의 동작 구조

(1) DispatcherServlet으로 요청이 들어오면,
DispatcherServlet은 핸들러 매핑을 통해 요청 URI에 매핑된 핸들러를 탐색
(핸들러 = Controller)
(2) 핸들러 어댑터로 컨트롤러를 호출
(3) 핸들러 어댑터에 컨트롤러의 응답이 돌아오면,
ModelAndView로 응답을 가공해 반환
(4) 뷰 형식으로 리턴하는 컨트롤러를 사용할 때는,
뷰 리졸버를 통해 뷰를 받아 리턴
❓ 핸들러 매핑 (Handler Mapping)
: 요청 정보를 기준으로 어떤 컨트롤러를 사용할지 선정하는 인터페이스
여러 구현체를 가진다.
⬇️ 대표적인 구현체 클래스
1️⃣ BeanNameUrlHandlerMapping
- 빈 이름을 URL로 사용하는 매핑 전략
- 빈을 정의할 때 슬래시("/") 들어가면 매핑 대상
- 예시) @Bean("/hello")
2️⃣ ControllerClassNameHandlerMapping
- URL과 일치하는 클래스 이름을 갖는 빈을 컨트롤러로 사용하는 전략
- 이름 중 Controller를 제외하고 앞부분에 작성된 suffix를 소문자로 매핑
3️⃣ SimpleUrlHandlerMapping
- URL 패턴에 매핑된 컨트롤러를 사용하는 전략
4️⃣ DefaultAnnotationHandlerMapping
- 어노테이션으로 URL과 컨트롤러를 매핑하는 방법
뷰 리졸버는 뷰의 렌더링 역할을 담당하는 뷰 객체를 반환
⬇️ 뷰를 사용하는 DispatcherServlet의 동작 방식

이 책에서 다룰 애플리케이션은,
REST 형식의 @ResponseBody를 사용
= 뷰 리졸버를 호출❌➙ MessageConverter를 거쳐 JSON 형식으로 변환해서 응답
MessageConverters
: 요청과 응답에 대해 Body값을 변환하는 역할을 수행
⬇️ @RestController를 사용하는 DispatcherServlet의 동작 방식

: 애플리케이션의 컴포넌트를 유사 관심사 기준으로 레이어로 묶어 수평적으로 구성한 구조
일반적으로 레이어드 아키텍쳐라 하면 3계층 또는 4계층 구성을 의미
3계층과 4계층의 차이는 인프라(데이터베이스) 레이어의 추가 여부로 결정 된다.
⬇️ 일반적인 레이어드 아키텍처 (3계층)

⭐ 프레젠테이션 계층 (Presentation)
• 애플리케이션의 최상단 계층으로, 클라이언트의 요청을 해석하고 응답하는 역할
• UI나 API를 제공
• 프레젠테이션 계층은 별도의 비즈니스 로직을 포함하고 있지 않으므로,
비즈니스 계층으로 요청 위임하고 받은 결과를 응답하는 역할만 수행
⭐ 비즈니스 계층 (Business)
• 애플리케이션이 제공하는 기능을 정의하고
세부 작업을 수행하는 도메인 객체를 통해 업무를 위임하는 역할을 수행
• DDD(Domain-Drive-Design) 기반의 아키텍처에서는
비즈니스 로직에 도메인이 포함되기도 하고, 별도로 도메인 계층을 두기도 함
⭐ 데이터 접근 계층 (Data Access)
• 데이터베이스에 접근하는 일련의 작업을 수행
레이어 아키텍처는 하나의 애플리케이션에도 적용되지만
애플리케이션 간의 관계를 설명하는 데도 사용할 수 있다.
< 레이어드 아키텍처 기반 설계 특징 >
각 레이어는 가장 가까운 하위 레이어의 의존성을 주입받는다.
각 레이어는 관심사에 따라 묶여 있고, 다른 레이어의 역활을 침범하지 않는다.
각 컴포넌트의 역할이 명확하므로 코드 가독성과 기능 구현에 유리
코드의 확장성이 좋아짐
각 레이어가 독립적으로 작성
➙ 각 레이어들 간의 의존성을 낮춰 단위테스트에 용이
스프링 부트는 별도의 설정 없이 spring-boot-starter-web의 의존성을 사용할 때는 기본적으로 스프링MVC 구조를 띠게 된다.
⬇️ 레이어드 아키텍처를 스프링에 적용

Spring MVC는 Model-View-Controller의 구조로,
View, Controller : 프레젠테이션 계층 영역
Model : 비즈니스 계층, 데이터 접근 계층 영역
비즈니스 계층에 서비스를 배치
: 엔티티와 같은 도메인의 객채의 비즈니스 로직을 조합
데이터 접근 계층에 DAO(Spring Data JPA에서는 Repository)를 배치
: 도메인을 관리
⭐ 프레젠테이션 계층 (Presentation) = 유저 인터페이스(UI) 계층이라고도 함
• 클라이언트와의 접점
• 클라이언트로부터 데이터와 함께 요청을 받고 처리 결과를 응답으로 전달하는 역할
⭐ 비즈니스 계층 (Business) = 서비스(Service) 계층이라고도 함
• 핵심 비즈니스 로직을 구현하는 영역
• 트랜잭션 처리나 유효성 검사 등의 작업도 수행
⭐ 데이터 접근 계층 (Data Access) = 영속(Persistence) 계층이라고도 함
• 데이터베이스에 접근해야 하는 작업을 수행
• DAO라는 컴포넌트는 Spring Data JPA에서는 DAO 역할을 리포지토리가 수행
➙ 리포지토리로 대체 가능
: 소프트웨어를 설계할 때 자주 발생하는 문제들을 해결하기 위해 고안된 해결책
GoF 디자인 패턴 (GoF; Gang of Four)
디자인 패턴을 구체화해서 정리한 대표적인 분류 방식

: 객체 생성에 사용되는 패턴 , 객체를 수정해도 호출부가 영향을 받지 않게 함
- 추상 팩토리 (Abstract Factory)
: 구체적인 클래스를 지정하지 않고
상황에 맞는 객체를 생성하기 위한 인터페이스를 제공하는 패턴
- 빌더 (Builder)
: 객체의 생성과 표현을 분리해 객체를 생성하는 패턴
- 팩토리 메서드 (Factory Method)
: 객체 생성을 서브클래스로 분리해서 위임하는 패턴
- 프로토타입 (Prototype)
: 원본 객체를 복사해 객체를 생성하는 패턴
- 싱글턴 (Singleton)
: 한 클래스마다 인스턴스를 하나마 생성해서 인스턴스가 하나임을 보장하고
어느 곳에서도 접근할 수 있게 제공하는 패턴
: 객체를 조합해서 더 큰 구조를 만드는 패턴
- 어댑터(Adapter)
: 클래스의 인터페이스를 의도하는 인터페이스로 변환하는 패턴
- 브리지 (Bridge)
: 추상화와 구현을 분리해서 각각 독립적으로 변형케 하는 패턴
- 컴포지트 (Composite)
: 여러 객체로 구성된 복합 객체와 단일 객체를 클라이언트에서 구별 없이 다루는 패턴
- 데코레이터 (Decorator)
: 객체의 결합을 통해 기능을 동적으로 유연하게 확장할 수 있게 하는 패턴
- 퍼사드 (Facade)
: 서브시스템의 인터페이스 집합들에 하나의 통합된 인터페이스를 제공하는 패턴
- 플라이웨이트 (Flyweight)
: 특정 클래스의 인스턴스 한 개를 가지고
여러 개의 '가상 인스턴스'를 제공할 때 사용하는 패턴
- 프락시 (Proxy)
: 특정 객체를 직접 참조하지 않고
해당 객체를 대행(프락시)하는 객체를 통해 접근하는 패턴
: 객체 간의 알고리즘이나 책임 분배에 관한 패턴
객체 하나로는 수행할 수 없는 작업을 여러 객체를 이용해 작업을 분배한다.
결합도 최소화를 고려할 필요가 있다.
- 책임 연쇄 (Chain of Responsibility)
: 요청 처리 객체를 집합으로 만들어 결합을 느슨하게 만드는 패턴
- 커맨드 (Command)
: 실행될 기능을 캡슐화해서 주어진 여러 기능을 실행하도록 클래스를 설계하는 패턴
- 인터프리터 (Interpreter)
: 주어진 언어의 문법을 위한 표현 수단을 정의하고
해당 언어로 구성된 문장을 해석하는 패턴
- 이터레이터 (Iterator)
: 내부 구조를 노출하지 않으면서,
해당 객체의 집합 원소에 순차적으로 접근하는 방법을 제공하는 패턴
- 미디에이터 (Mediator)
: 한 집합에 속한 객체들의 상호작용을 캡슐화하는 객체를 정의한 패턴
- 메멘토 (Memento)
: 객체의 상태 정보를 저장하고 필요에 따라 상태를 복원하는 패턴
- 옵저버 (Observer)
: (객체의 상태 변화를 관찰하는 관찰자들) 옵저버 목록을 객체에 등록해
상태가 변할 때마다 객체가 직접 옵저버에게 통지하게 하는 패턴
- 스테이트 (State)
: 상태에 따라 객체가 행동을 변하게 하는 패턴
- 스트래티지 (Strategy)
: 행동을 클래스로 캡슐화해서 동적으로 행동을 바꿀 수 있게 하는 패턴
- 템플릿 메서드 (Template Method)
: 일정 작업을 처리하는 부분을 서브클래스로 캡슐화해서 전체 수행 구조는 바꾸지 않으면서
특정 단계만 변경해서 수행하는 패턴
- 비지터 (Visitor)
: 실제 로직을 가지고 있는 객체(visitor)가
로직을 적용할 객체(element)를 방문하여 실행하는 패턴
: 대중적으로 가장 많이 사용되는 애플리케이션 인터페이스
이 인터페이스를 통해 클라이언트는 서버에 접근하고 자원을 조작할 수 있다.
REST (Representational State Transfer)
: 분산 하이퍼미디어 시스템 아키텍처의 한 형식
주고 받는 자원에 이름을 규정하고,
URI에 명시해 HTTP 메서드를 통해 해당 자원의 상태를 주고받는 것
API (Application Programming Interface)
: 애플리케이션에서 제공하는 인터페이스
API를 통해 서버 또는 프로그램 사이를 연결할 수 있다.
REST API
: REST아키텍처를 따르는 시스템/애플리케이션 인터페이스
REST 아키텍처를 구현하는 웹서비스를 'RESTful하다' 라고 표현
유니폼 인터페이스 (일관된 인터페이스)
: HTTP 표준 전송 규약을 따르기 떄문에 어떤 언어로 만들어졌느냐와 상관 ❌
플랫폼 및 기술에 종속되지 않고 호환성이 좋다.
무상태성 (stateless)
: 서버에 상태 정보를 따로 보관하거나 관리하지 않는다.
서버가 불필요한 정보를 관리하지 ❌
➡️ 비즈니스 로직의 자유도가 높고 설계가 단순하다.
캐시 가능성
: HTTP의 캐싱 기능을 적용할 수 있다.
이 기능을 사용하면,
서버의 트랜잭션 부하가 줄어 효율적이며 사용자 입장에서 성능이 개선된다.
레이어 시스템 (Layered System)
: 네트워크 상의 여러 계층으로 구성될 수 있다.
클라이언트 - 서버 아키텍처
: REST서버는 API를 제공 & 클라이언트는 사용자 정보를 관리 ➡️ 분리 설계
서로에 대한 의존성을 낮추는 기능
URI의 마지막에는 '/'를 포함하지 않는다.
언더바(_)는 사용하지 않는다. 대신 하이픈(-)을 이용한다.
: 하이픈은 리소르의 이름이 길어지면 사용한다.
URI에는 행위(동사)가 아닌 결과(명사)를 포함한다.
: 행위는 HTTP 매서드로 표현할 수 있어야 한다.
URI는 소문자로 작성해야 한다.
파일의 확장자는 URI에 포함하지 않는다.
스프링 부트는 자동 설정을 지원하기 떄문에 편리하지만,
심도 있는 개발을 위해서 스프링 모듈만으로 개발 진행해보기
: 비즈니스 로직을 어디서 담당할지 결정하고 설계하는게 좋다.
비즈니스 로직은 도메인 계층에서 담당하는 것이 일반적