반응형
1. 서버 간 통신
- 마이크로서비스 아키텍처에서 한 서버가 다른 서버에 통신을 요청하는 것을 의미
-> 한 대는 서버/다른 한 대는 클라이언트가 됨 - 가장 많이 사용되는 방식은 HTTP/HTTPS 방식(TCP/IP, SOAP 방식도 있음)
*마이크로서비스 아키텍처(MSA: Microservice Architecture)
- 서비스 규모를 작게 나누어 구성한 아키텍처
-> 애플리케이션 하나에 여러 기능을 넣지 않고, 블로그 프로젝트/카페 프로젝트/메일 프로젝트 등으로 나누어 개발 - 사용자가 블로그 기능을 사용하기 위해 로그인 기능을 거치려면 두 기능 간 통신이 필요
2. 스프링 부트의 동작 방식
* 핸들러 매핑이란?
- 요청 정보를 기준으로 어떤 컨트롤러를 사용할지 선정하는 인터페이스
- 핸들러 매핑 인터페이스는 여러 구현체를 가지며, 대표적인 구현체 클래스는 다음과 같음
BeanNameUrlHandlerMapping | - 빈 이름을 URL로 사용하는 매핑 전략 - 빈을 정의할 때 슬래시(‘/’)가 들어가면 매핑 대상 -> 예) @Bean(“/hello”) |
ControllerClassNameHandlerMapping | - URL과 일치하는 클래스 이름을 갖는 빈을 컨트롤러로 사용하는 전략 - 이름 중 Controller를 제외하고 앞 부분에 작성된 suffix를 소문자로 매핑 |
SimpleUrlHandlerMapping | - URL 패턴에 매핑된 컨트롤러를 사용하는 전 |
DefaultAnnotationHandlerMapping | - 어노테이션으로 URL과 컨트롤러를 매핑하는 방법 |
**스프링 부트의 동작 방식 이해
- spring-boot-starter-web 모듈을 사용하면 기본적으로 톰캣(Tomcat)을 사용하는 스프링 MVC 구조를 기반으로 동작
- 서블릿(Servlet): 클라이언트 요청을 처리하고 결과를 반환하는 자바 웹 프로그래밍 기술
-> 서블릿 컨테이너(Servlet Contriner)
: 스프링 부트에서 서블릿 객체를 생성/초기화/호출/종료하는 생명주기를 싱글톤 패턴으로 관리, 멀티 스레딩 지원 - 스프링에서는 DispatcherServlet이 서블릿 역할을 수행함
- (1) DispatcherServlet 으로 요청(HttpServletRequest)이 들어오면 DispatcherServlet은 핸들러 매핑(Handler Mapping)을 통해 요청 URL에 매핑된 핸들러를 탐색[여기서 핸들러는 컨트롤러(Controller)를 의미]
- (2) 핸들러 어댑터(HandlerAdapter)로 컨트롤러를 호출
- (3) 핸들러 어댑터에 컨트롤러의 응답이 돌아오면 ModelAndView로 응답을 가공해 반환
- (4) 뷰 형식으로 리턴하는 컨트롤러를 사용할 때는 뷰 리졸버(View Resolver)를 통해 뷰(View)를 받아 리턴
스프링의 동작 구조 이미지(출처: https://djcho.github.io/springboot/spring-boot-chapter2-2/)
- DispatcherServlet이 뷰를 사용하는 경우 동작 방식은 다음과 같음
-> 뷰 리졸버에서 뷰의 렌더링 역할을 담당하는 뷰 객체 반환
- DispatcherServlet이 뷰를 사용하는 경우 동작 방식은 다음과 같음
- 이 책의 스프링 부트에서는 @RestController를 사용하는 DispatcherServlet의 동작 방식을 사용
1) 메인 클래스 실행
- @SpringBootApplication 어노테이션이 붙은 메인 클래스를 통해 실행
- 내부적으로 @Configuration, @EnableAutoConfiguration, @ComponentScan 세 가지 어노테이션이 포함되어 있어 설정과 컴포넌트 검색을 자동으로 처리
2) SpringApplication 객체 초기화
- SpringApplication.run() 메서드가 호출되어 애플리케이션 컨텍스트를 초기화하고, 필요한 설정을 로딩
- 환경 설정(properties, YAML 등)도 이 단계에서 읽힘
3) 내장 톰캣(Web Server) 시작
- 별도로 톰캣을 설치하지 않아도 되고, 실행 시 자동으로 웹 서버가 구동
4) 자동 구성(Auto Configuration)
- @EnableAutoConfiguration 덕분에, 애플리케이션의 의존성 기반으로 필요한 설정을 자동으로 적용
- 예: spring-boot-starter-web을 포함하면 DispatcherServlet 등이 자동으로 설정
5) Bean 등록 및 의존성 주입(DI)
- @Component, @Service, @Repository, @Controller 등을 통해 Bean이 등록
- @Autowired 등을 통해 필요한 Bean 주입
6) 요청 처리 및 응답
- 클라이언트 요청이 들어오면 DispatcherServlet이 이를 처리하고, 적절한 Controller로 전달
- Controller → Service → Repository 순으로 처리된 결과를 클라이언트에게 응답
3. 레이어드 아키텍처(Layered Architecture)
- 애플리케이션의 컴포넌트를, 유사 관심사를 기준으로 레이어로 묶어 수평적으로 구성한 구조
- 일반적으로 3/4계층을 사용하나, 설계에 따라 용어와 계층에 수가 달라지는 것
- 하나의 애플리케이션에도 적용되지만, 애플리케이션 간의 관계를 설명하는 데도 사용
- 특징
- 각 레이어는 가장 가까운 하위 레이어의 의존성을 주입받음
- 각 레이어는 관심사에 따라 묶여 있으며, 다른 레이어의 역할을 침범하지 않음
- 각 컴포넌트의 역할이 명확하므로 코드의 가독성과 기능 구현에 유리하
- 코드의 확장성이 좋아짐
- 각 레이어가 독립적으로 작성되면, 다른 레이어와의 의존성을 낮춰 단위 테스트에 용이
* 스프링 부트의 레이어드 아키텍처
(1) 프레젠테이션 계층(UI/User Interface/유저 인터페이스 계층)
- 애플리케이션의 최상단 계층으로, 클라이언트의 요청을 해석하고 응답하는 역할(클라이언트와의 접점)
- 클라이언트로부터 데이터와 함께 요청을 받고, 처리 결과를 응답으로 전달
(2) 비즈니스 계층(Service/서비스 계층)
- 애플리케이션이 제공하는 기능을 정의하고, 세부 작업을 수행하는 도메인 객체를 통해 업무를 위임하는 역할을 수행
- DDD(Domain-Driven-Design) 기반 아키텍처에서는 비즈니스 로직에 도메인이 포함되기도 하고,
별도로 도메인 계층을 두기도 함 - 핵심 비즈니스 로직 구현: 트랜잭션 처리나 유효성 검사 등의 작업도 수행
(3) 데이터 접근 계층(Persistence/영속 계층)
- 데이터베이스에 접근하는 일련의 작업 수행
- 보통 DAO가 수행하는데, Spring Data JPA에서는 DAO 역할을 리포지토리가 수행하므로 리포지토리로 대체
4. 디자인 패턴(Design Pattern)
- 객체지향 설계에서 반복적으로 나타나는 문제를 해결하기 위한 정형화된 설계 방법
- GoF(디자인 패턴을 구체화하고 체계화해서 분류한 4명의 인물) 디자인 패턴 분류 방식
유형 | 패턴 이름 | 설명 |
생성(Creational) 패턴 - 객체 생성에 사용되는 패턴 : 객체를 수정해도 호출부가 영향을 받지 않게 함 |
Singleton(싱글톤) | 하나의 인스턴스만 생성되도록 보장 |
Factory Method(팩토리 메서드) | 객체 생성 인터페이스를 정의하고 서브클래스가 인스턴스를 결정 | |
Abstract Factory(추상 팩토리) | 관련 객체를 생성할 수 있는 인터페이스를 제공 | |
Builder(빌더) | 복잡한 객체의 생성 과정을 단계적으로 분리 | |
Prototype(프로토타입) | 복제(clone)를 통해 객체 생성 | |
구조(Structural) 패턴 - 객체를 조합해서 더 큰 구조를 만드는 패턴 |
Adapter(어댑터) | 인터페이스 호환 문제를 해결해주는 중간 연결자 |
Bridge(브릿지) | 구현과 추상화를 분리하여 독립적으로 변경 가능 | |
Composite(컴포지트) | 객체들을 트리 구조로 구성하여 부분-전체 계층 표현 | |
Decorator(데코레이터) | 기존 객체에 새로운 기능을 동적으로 추가 | |
Facade(퍼사드) | 복잡한 서브시스템을 단순한 인터페이스로 제공 | |
Flyweight(플라이웨이트) | 메모리 사용을 줄이기 위해 동일한 객체를 공유 | |
Proxy(프록시) | 접근 제어를 위한 대리 객체 제공 | |
행위(Behavioral) 패턴 - 객체 간 알고리즘이나 책임 분배에 관한 패턴: 여러 객체를 이용해 작업 분배(결합도 최소화 고려해야 함) |
Observer(옵저버) | 한 객체의 상태 변화가 여러 객체에 전달됨 |
Strategy(전략) | 알고리즘을 캡슐화하고 동적으로 교체 가능 | |
Command(커맨드) | 요청을 객체로 캡슐화하여 사용자의 명령을 저장 및 실행 | |
State(상태) | 객체의 상태에 따라 행동이 변경되는 패턴 | |
Template Method(템플릿 메서드) | 알고리즘의 구조를 정의하고 일부 단계를 서브클래스가 구현 | |
Iterator(이터레이터) | 컬렉션의 내부 구조를 공개하지 않고 순회 | |
Mediator(미디에이터) | 객체 간 복잡한 상호작용을 캡슐화 | |
Chain of Responsibility(책임 연쇄) | 요청을 처리할 객체를 연결하여 책임 분산 | |
Visitor(비지터) | 요소에 새로운 기능을 추가하면서 구조 수정 없이 확장 가능 | |
Interpreter(인터프리터) | 언어 해석기를 구현하여 문법을 해석 |
5. REST API
- 가장 대중적으로 많이 사용되는 애플리케이션 인터페이스
-> 클라이언트는 서버에 접근하고 자원 조작 가능
1) REST (Representational State Transfer)
- 월드 와이드 웹(WWW)과 같은 분산 하이퍼미디어 시스템 아키텍처의 한 형식
- 주고받는 자원(resource)에 이름을 붙이고 URI에 명시해,
HTTP 메서드(GET, POST, PUT, DELETE)로 자원의 상태를 주고받음 - 주요 특징
무상태성(Stateless) | 요청 간에 서버는 클라이언트의 상태를 저장하지 않음 (세션 없음) |
캐시 가능성(Cacheable) | HTTP 캐시 기능을 적용하여 성능 향상 |
유니폼 인터페이스(일관된 인터페이스) | URI와 HTTP 메서드의 사용 규칙이 통일됨 -> HTTP 표준 전송 규약을 따르므로, 모든 프로그래밍 언어/플랫폼/기술과 호환 |
레이어 시스템(Layered System) | REST 서버는 네트워크 상 여러 계층으로 구성하여, 구조 확장에 용이 -> 서버 복잡도와는 관계없이, 클라이언트는 서버와 연결되는 포인트만 알면 됨 |
클라이언트-서버 아키텍처 | REST 서버는 API를 제공하고 클라이언트는 사용자 정보를 관리하는 구조로 설계 -> 클라이언트-서버 간 의존성 낮춤 |
2) REST API (Representational State Transfer Application Programming Interface)
- API: 애플리케이션에서 제공하는 인터페이스로, 서버 또는 프로그램 사이를 연결
- REST를 기반으로 만든 API를 의미하며, HTTP 프로토콜을 활용해 자원(Resource)에 접근하고 조작
-> REST 아키텍처를 따르는 시스템/애플리케이션 인터페이스를 의미하는 것! - REST 아키텍처를 구현하는 웹서비스를 'RESTful'하다고 표현
3) REST URI 설계 규칙
(1) 자원(Resource) 중심으로 설계
- URI는 명사로 표현하며, CRUD는 HTTP 메서드로 분리
- 예: /users, /products, /posts
(2) 동사 대신 HTTP Method 사용
- ❌ /getUsers, /createUser
- ✅ GET /users, POST /users
(3) 복수형 사용 권장
- ❌ /user, ✅ /users
(4) 계층 구조 표현
- /users/{userId}/orders → 특정 유저의 주문 목록
(5) 필터링, 정렬은 쿼리 파라미터 사용
- /products?category=books&sort=price_desc
(6) HTTP 상태 코드 활용
- 클라이언트가 결과를 명확히 알 수 있도록 적절한 상태 코드 반환
(7) URI 마지막에는 '/'를 사용하지 않고, 리소스의 이름이 길어지면 하이픈(-) 사용
(8) URI는 소문자로 작성하며, 파일의 확장자를 포함하지 않음
- HTTP에서 제공하는 Accept 헤더 사용
(9) URL에는 행위(동사)가 아닌 결과(명사)를 작성
- http://localhost.com/product/123
- 잘못된 예: http://localhost.com/delete-product/123
- 행위는 HTTP 메서드로 표현
반응형