Spring MVC API 계층

InSeok·2022년 9월 9일
0

TIL

목록 보기
29/51

Spring MVC API 계층

목차


  1. Spring MVC
  2. **Spring MVC의 동작 방식과 구성 요소**
  3. 핸들러 메서드
  4. RestClient

배운 내용


Spring MVC

  • 서블릿(Servlet) API를 기반으로 클라이언트의 요청을 처리하는 모듈
  • 웹프레임워크의 한 종류

서블릿(Servlet)

  • 클라이언트의 요청을 처리하도록 특정 규약에 맞추어서 Java 코드로 작성하는 클래스 파일

**Model**

  • 작업의 처리 결과 데이터
  • 비즈니스 로직(Business Logic) : 요청 사항을 처리하기 위해 Java 코드로 구현한 것

**View**

  • Model 데이터를 이용해서 웹브라우저 같은 클라이언트 애플리케이션의 화면에 보여지는 리소스(Resource)를 제공하는 역할
    • HTML 페이지의 출력
      • HTML 페이지를 직접 렌더링해서 클라이언트 측에 전송하는 방식
      • HTML 페이지 출력 기술 : Thymeleaf, FreeMarker, JSP + JSTL,
    • PDF, Excel 등의 문서 형태로 출력
    • XML, JSON 등 특정 형식의 포맷으로의 변환
      • Model 데이터를 특정 프로토콜 형태로 변환해서 변환된 데이터를 클라이언트 측에 전송하는 방식
      • 특정 형식의 데이터만 전송하고, 프런트엔드 측에서 이 데이터를 기반으로 HTML 페이지를 만드는 방식

**Controller**

  • 클라이언트 측의 요청을 직접적으로 전달 받는 엔드포인트(Endpoint)로써 Model과 View의 중간에서 상호 작용을 해주는 역할
    • 클라이언트 측의 요청을 전달 받아서 비즈니스 로직을 거친 후에 Model 데이터가 만들어지면, 이 Model 데이터를 View로 전달

JSON(JavaScript Object Notation)

  • 클라이언트 애플리케이션과 서버 애플리케이션이 주고 받는 데이터 형식
  • JSON의 기본 포맷
    • {”속성” : ”값”} 형태

**Spring MVC의 동작 방식과 구성 요소**

(1) 먼저 클라이언트가 요청을 전송하면 DispatcherServlet이라는 클래스에 요청이 전달됩니다.

(2) DispatcherServlet클라이언트의 요청을 처리할 Controller에 대한 검색을 HandlerMapping 인터페이스에게 요청합니다.

(3) HandlerMapping클라이언트 요청과 매핑되는 핸들러 객체를 다시 DispatcherServlet에게 리턴해줍니다.

(4) 요청을 처리할 Controller 클래스를 찾았으니 이제는 실제로 클라이언트 요청을 처리할 Handler 메서드를 찾아서 호출해야 합니다. DispatcherServlet은 Handler 메서드를 직접 호출하지 않고, HandlerAdpater에게 Handler 메서드 호출을 위임합니다.

(5) HandlerAdapter는 DispatcherServlet으로부터 전달 받은 Controller 정보를 기반으로 해당 Controller의 Handler 메서드를 호출합니다.

이제 전체 처리 흐름의 반환점을 돌았습니다. 이제부터는 반대로 되돌아 갑니다. ^^

(6) Controller의 Handler 메서드는 비즈니스 로직 처리 후 리턴 받은 Model 데이터를 HandlerAdapter에게 전달합니다.

(7) HandlerAdapter는 전달받은 Model 데이터와 View 정보를 다시 DispatcherServlet에게 전달합니다.

(8) DispatcherServlet은 전달 받은 View 정보를 다시 ViewResolver에게 전달해서 View 검색을 요청합니다.

(9) ViewResolver는 View 정보에 해당하는 View를 찾아서 View를 다시 리턴해줍니다.

(10) DispatcherServlet은 ViewResolver로부터 전달 받은 View 객체를 통해 Model 데이터를 넘겨주면서 클라이언트에게 전달할 응답 데이터 생성을 요청합니다.

(11) View는 응답 데이터를 생성해서 다시 DispatcherServlet에게 전달합니다.

(12) DispatcherServletView로부터 전달 받은 응답 데이터를 최종적으로 클라이언트에게 전달

**Controller 클래스 설계 및 구조 생성**

**패키지 구조 생성**

**기능 기반 패키지 구조(package-by-feature)**

  • 애플리케이션에서 구현해야 하는 기능을 기준으로 패키지를 구성
  • 패키지 안에는 하나의 기능을 완성하기 위한 계층별(API 계층, 서비스 계층, 데이터 액세스 계층)클래스들이 모여있다.
  • REST API 기반의 애플리케이션에서는 일반적으로 애플리케이션이 제공해야 될 기능을 리소스(Resource, 자원)로 분류 → 리소스에 해당하는 Controller 클래스를 작성하면 된다.

**계층 기반 패키지 구조(package-by-layer)**

  • 클래스들을 계층별로 묶어서 관리하는 구조

**엔트리포인트(Entrypoint) 클래스 작성**

  • main() 메서드가 포함된 애플리케이션의 엔트리포인트(Entrypoint, 애플리케이션 시작점)를 작성

@SpringBootApplication

  • 자동 구성 활성화
  • 패키지 내에서 @Component가 붙은 클래스를 검색한 후(scan), Spring Bean 으로 등록하는 기능을 활성화
  • @Configuration이 붙은 클래스를 자동으로 찾아주고, 추가적으로 Spring Bean을 등록하는 기능을 활성화

SpringApplication.run(Section3Week1Application.class, args);

  • Spring 애플리케이션을 부트스트랩하고, 실행하는 역할

부트스트랩(Bootstrap)

  • 애플리케이션이 실행되기 전에 여러가지 설정 작업을 수행하여 실행 가능한 애플리케이션으로 만드는 단계

**Controller 구조 작성**

@RestController

  • 특정 클래스에 @RestController를 추가하면 해당 클래스가 REST API의 리소스(자원, Resource)를 처리하기 위한 API 엔드포인트로 동작함을 정의
  • Spring Bean으로 등록해줌

@RequestMapping

  • 클라이언트의 요청과 클라이언트 요청을 처리하는 핸들러 메서드(Handler Method)를 매핑
    해주는 역할
  • Controller 클래스 레벨에 추가하여 클래스 전체에 사용되는 공통 URL(Base URL) 설정
  • 일반적으로 클래스 레벨에는 @RequestMapping 애너테이션을 사용하고, 메서드 레벨에서는 단축표현을 사용한다.
    • 단축표현
      • @GetMapping, @PostMapping, @PatchMapping, @DeleteMapping 등

**핸들러 메서드(Handler Method)**

produces 애트리뷰트

  • produces애트리뷰트(Attribute)는 응답 데이터를 어떤 미디어 타입으로 클라이언트에게 전송할 지를 설정

@PostMapping

클라이언트의 요청 데이터(request body)를 서버에 생성할 때 사용하는 애너테이션

@RequestParam

  • 핸들러 메서드의 파라미터 종류 중 하나

  • 요청 데이터를 쿼리 파라미터(Query Parmeter 또는 Query String), 폼 데이터(form-data),

    x-www-form-urlencoded형식으로 전송하면 이를 서버 쪽에서 전달 받을 때 사용하는 애너테이션

쿼리 파라미터(Query Parameter 또는 QueryString)

@GetMapping

  • 클라이언트가 서버에 리소스를 조회할 때 사용하는 애너테이션
  • {member-id}
    • 회원 식별자를 의미하며 클라이언트가 요청을 보낼 때 URI로 어떤 값을 지정하느냐에 따라서 동적으로 바뀌는 값

@PathVariable

  • @PathVariable의 괄호 안에 입력한 문자열 값은 @GetMapping("/{member-id}")
    의 중괄호({ }) 안의 문자열과 동일해야 합니다. → “member-id”

식별자(Identifier)

  • 어떤 데이터를 식별할 수 있는 고유값

ResponseEntity 적용

  • Map 객체를 리턴하게 되면 내부적으로 ‘이 데이터는 JSON 형식의 응답 데이터로 변환해야 되는구나’라고 이해하고 JSON 형식으로 자동 변환
  • return new ResponseEntity<>(map, HttpStatus.CREATED);
    • ResponseEntity 객체를 생성하면서 생성자 파라미터로 응답데이터(map)과 HttpStatus.CREATED Http 응답 상태를 함께 전달

HTTP 헤더

  • HTTP 헤더(Header)는 HTTP 메시지(Messages)의 구성 요소 중 하나로써 클라이언트의 요청이나 서버의 응답에 포함되어 부가적인 정보를 HTTP 메시지에 포함할 수 있다.
  • HTTP Request 헤더(Header) 정보 얻기
    • @RequestHeader 애너테이션을 이용해서 개별 헤더 정보 및 전체 헤더 정보를 얻을 수 있다.
    • HttpServletRequest 또는 HttpEntity 객체로 헤더 정보를 얻을 수 있다.
  • HTTP Response 헤더(Header) 정보 추가
    • ResponseEntityHttpHeaders를 이용해 헤더 정보를 추가할 수 있다.
    • HttpServletResponse 객체를 이용해 헤더 정보를 추가할 수 있다.

**Rest Client**

  • Rest API 서버에 HTTP 요청을 보낼 수 있는 클라이언트 툴 또는 라이브러리(PostMan)
  • 어떤 서버가 HTTP 통신을 통해서 다른 서버의 리소스를 이용한다면 그 때만큼은 클라이언트의 역할을 한다

**RestTemplate**

  • Spring에서 제공하는 원격지에 있는 다른 Backend서버에 Http 요청을 보낼 수 있는 Rest Client API
  • Rest 엔드 포인트 지정, 헤더 설정, 파라미터 및 body 설정을 한 줄의 코드로 손쉽게 전송가능

RestTemplate을 사용할 수 있는 기능 예

  • 결제 서비스
  • 카카오톡 등의 메시징 서비스
  • Google Map 등의 지도 서비스
  • 공공 데이터 포털, 카카오, 네이버 등에서 제공하는 Open API

**DTO(Data Transfer Object)**

**DTO가 필요한 이유**

  1. **DTO 클래스를 이용한 코드의 간결성**
    • DTO 클래스가 요청 데이터를 하나의 객체로 전달 받는 역할을 수행
  2. **데이터 유효성(Validation) 검증의 단순화**
    • 유효성 검증 로직을 DTO 클래스로 빼내어 핸들러 메서드의 간결함을 유지
  3. HTTP 요청의 수를 줄이기 위함

DTO 클래스 생성

  • 주의해야 할 부분 : 멤버 변수 이외에 각 멤버 변수에 해당하는 getter 메서드가 있어야 한다
  • getter 메서드가 없으면 Response Body에 해당 멤버 변수의 값이 포함되지 않는다.

@RequestBody

  • JSON 형식의 Request BodyMemberPostDto 클래스의 객체로 변환을 시켜주는 역할

클라이언트 쪽에서 전송하는 Request Body가 JSON 형식이어야 한다

@ResponseBody

  • DTO 클래스의 객체를 JSON 형식의 Response Body로 변환하는 역할
  • @ResponseBody애너테이션이 붙거나 핸들러 메서드의 리턴 값이 ResponseEntity일 경우, 내부적으로 HttpMessageConverter가 동작하게 되어 응답 객체( DTO 클래스 객체)를 JSON 형식으로 바꿔준다.

단점

  • Controller 클래스가 늘어남에 따라 DTO 클래스가 두 배(ex. xxxxPostDto + xxxxPatchDto)씩 늘어남

  • JSON 직렬화(Serialization): Java 객체 → JSON

  • JSON 역직렬화(Deserialization): JSON → Java 객체

**DTO 유효성 검증(Validation)**

  • 프런트엔드 쪽에서 1차적으로 유효성 검사를 진행했다고 하더라도 서버 쪽에서 한번 더 유효성 검사를 진행해야 된다
  • DTO 클래스의 각 멤버 변수에 유효성 검증을 위한 애너테이션을 추가함으로써 , 핸들러 메서드에 별도의 유효성 검증을 추가하지 않고, 깔끔하게 유효성 검증 로직이 분리
  • 유효성 검증 로직이 실행되게 하기 위해서는 핸들러 메서드의 DTO 클래스에 @Valid애너테이션을 추가

@NotBlank

  • null 값이나 공백(””), 스페이스(” “) 같은 값들을 모두 허용하지 않음

@Email

  • 유효한 이메일 주소인지를 검증

@Pattern

  • 정규표현식(Reqular Expression)에 매치되는지 검증

**쿼리 파라미터 및 @Pathvariable에 대한 유효성 검증**

@Validated

  • 애너테이션을 사용하면 쿼리 파라미터(Query Parameter 또는 Query String) 및 @Pathvariable
    에 대한 유효성 검증을 진행할 수 있다.
  • 유효성 검증이 정상적으로 수행되려면 클래스 레벨@Validated애너테이션을 반드시 붙여주어야 한다

@Min(1)

  • 1 이상의 숫자일 경우에만 유효성 검증에 통과

**Custom Validator를 사용한 유효성 검증**

  • 정규 표현식(Regular Expression)은 성능적인 면에서 때로는 비싼 비용을 치뤄야 될 가능성이있다.
profile
백엔드 개발자

0개의 댓글