본문 바로가기

백엔드 학습 과정/Section 3 [Spring MVC, JDBC, JPA, RestDo

#1. Spring MVC [API 계층]

[애플리케이션 아키텍처]

애플리케이션 : PC/스마트폰/노트북과 같은 클라이언트에서 사용하는 소프트웨어의 종류로

클라이언트로부터 전달받은 요청을 처리하는 서버 애플리케이션.

REST API 기반 웹 애플리케이션 계층

[API 계층]

클라이언트의 요청을 받아들이는 계층

 

[Service 계층] ** 핵심 계층 **

[API 계층]에서 클라이언트로부터 전달받은 요청을 비즈니스 로직으로 처리하는 계층.

 

[데이터 액세스 계층] 

1. [Service 계층]에서 처리된 데이터를 DB등의 데이터 저장소에 저장하기 위한 계층.

2. 클라이언트로부터 전달받은 요청을 비즈니스 로직으로 처리하는 과정에서

    데이터와 관련된 기능/작업이 필요할 때 전달되는 계층.

 

1. API 계층 [Spring MVC 아키텍처]

Spring 의 모듈 중에는 웹 계층을 담당하는 몇 가지 모듈이 있는데,

서블릿 API를 기반으로 클라이언트 처리하는 모듈이 Spring Web MVC이며

줄여서Spring MVC라고도 부르며 웹 프레임워크의 한 종류이므로, Spring MVC 프레임워크 라고도 부른다.

 

- Model -

Spring MVC 기반의 웹 애플리케이션은 클라이언트로부터 요청을 전달 받고,

그 요청에 대한 작업을 처리하고, 처리한 작업의 결과 데이터를 클라이언트에게 응답으로 돌려주는데,

클라이언트에게 응답으로 돌려주는 작업의 처리 결과 데이터를 Model 이라고 한다.

 

- View -

Model 데이터를 이용해서 웹 브라우저 같은 클라이언트 애플리케이션의 화면에 보여지는 리소스를 제공한다.

Spring MVC는 다양한 View 기술이 포함되어 있는데, View의 형태는 아래와 같이 나눌 수 있다.

 

1. HTML 페이지의 출력

클라이언트 애플리케이션에 보여지는 HTML 페이지를 직접 렌더링해서 클라이언트 측에 전송하는 방식

기본적인 HTML 태그로 구성된 페이지에 Model 데이터를 채우고, 최종 HTML 페이지를 만들어 전송 // SSR 렌더링

 

2. PDF, Excel 등의 문서 형태로 출력

Model 데이터를 가공해서 PDF 문서나 Excel 문서를 만들어서 클라이언트 측에 전송하는 방식.

문서 내에서 데이터가 동적으로 변경되어야 하는 경우 사용할 수 있다.

 

3. XML, JSON 등 특정 형식의 포맷으로 변환 

Model 데이터를 특정 프로토콜 형태로 변환해서 변환된 데이터를 클라이언트 측에 전송하는 방식.

특정 형식의 데이터(JSON)만 전송하고, 프론트엔드 측에서 이 데이터를 기반으로 HTML 페이지를 만드는 방식.

 

- Controller -

클라이언트 요청을 직접적으로 전달 받는 엔드 포인트로써 Model과 View 중간에서 상호작용 역할을 한다.

클라이언트 요청을 받아 비즈니스 로직을 거친 후 Model 데이터가 만들어지면 View로 전달하는 역할

 

- Spring MVC의 동작 방식 // Model, View, Controller 간의 흐름.

1. 클라이언트가 요청 데이터 전송

2. Controller가 엔드 포인트로써 요청 데이터 수신하고 핸들러 메서드로 요청 처리를 분류함.

3. [Service 계층] 에서 요청 데이터를 비즈니스 로직으로 처리

4. Model 데이터 생성

5. [Service 계층] 에서 Controller에게 Model 데이터 전달

6. Controller가 View에게 Model 데이터 전달

7. View가 응답 데이터를 생성.

 

 

 

[애플리케이션 설계 순서]

1. 애플리케이션의 주 목적 설정.

만들고자 하는 애플리케이션이 어떤 목적을 가지고 있는 것인지 파악하기.

 

2. 애플리케이션 기능 구현을 위한 요구 사항 파악.

클라이언트로부터 발생할 요청들, 요청들을 처리하기 위해 필요한 기능들을 파악한다.

REST API 기반의 애플리케이션은 클라이언트에게 전달받은 요청에 제공해야 될 기능을 리소스(Resource)로 분류하며,

분류한 리소스별로 Controller 클래스를 설계한다.

[예시]

ex) 커피주문 애플리케이션

필요한 기능 : 커피 정보 , 고객 , 주문

Controller 클래스 : Coffee Class, Member Class, Order Class 

 

3. 프로젝트 Java 패키지 구조 정하기.

A. 기능 기반 패키지 구조 // Spring Boot 권장

애플리케이션 패키지를 애플리케이션에서 구현해야 하는 기능을 기준으로 패키지를 구성한 것

B. 계층 기반 패키지 구조 

패키지를 하나의 계층으로 보고 클래스들을 계층별로 묶어서 관리하는 구조

 

4. 엔트리 클래스 작성하기.

Spring Boot 기반의 애플리케이션이 정상적으로 실행되기 위해서는 

가장 먼저 해야 할 일은 main() 메서드가 포함된 main 클래스(엔트리 포인트)를 작성하는 것.

 

A. @SpringBootApplication = 메인 클래스 애너테이션

@Configuration annoted 객체들을 자동으로 찾고, Spring Bean에 등록하는 기능을 활성화 한다.

 

B. main() 메서드 내에 SpringApplication.run(main클래스명.class, args); 코드 작성

Spring 애플리케이션을 실행 전 여러 설정 작업을 통해 실행 가능한 애플리케이션으로 만드는 과정.

 

 

5. Controller 클래스 구조 작성

A. @RestController // Controller 클래스 레벨 애노테이션.

해당 애너테이션이 추가된 클래스는 REST API의 리소스를 처리하기 위한 API 엔드포인트(Controller) 임을 나타낸다.

또한 @RestController annoted 클래스는 애플리케이션 로딩 시, Spring Bean으로 등록해준다.

 

B. @RequestMapping("URI") // Controller 클래스 레벨 애노테이션

클라이언트의 요청을 전달할 클래스 전체에 사용되는 공통 URI 설정하는 애너테이션.

ex) @RequestMapping(value = "/v1/members", produces = {Media.Type.APPLICATION_JSON_VALUE})

URI, 데이터 전달 양식 타입

 

C. @Validated // Controller 클래스 레벨 애너테이션

1. 각 기능별로 전달된 데이터들이 유효한 상태인지 점검하는 @Valid 애너테이션을 허용한다는 의미의 애너테이션

2. 유효성 검증을 위한 필요 조건을 받아 처리하는 DTO 객체를 허용한다는 의미.

 

6. Controller 클래스에 핸들러 메서드 작성

핸들러 메서드 : Controller 클래스에 있는 메서드로써 클라이언트의 요청을 처리하기 위해 필요한 기능을 위한 메서드.

 

1. 핸들러 메서드를 작성하기 전, 각 기능별로 필요한 데이터(변수)를 파악한다. 

Ex) 회원정보 : String name, String email, String phone

 

2. 파악한 필요 기능을 처리하기 위한 핸들러 메서드를 생성하고,

각 메서드(post,get,patch/put,delete)에는 다음과 같은 HTTP 요청 메소드와 동일한 애너테이션이 필요하다.

 

@PostMapping : 클라이언트의 요청 데이터를 서버에 생성할 때 사용하는 애너테이션.

 

@GetMapping{"/ "} : 클라이언트가 서버에 리소스를 조회할 때 사용하는 애너테이션.

{"/ "}는 조회하기 위한 기준 URI이며, 안에 들어가는 기능별로 필요한 데이터 변수명에 따라 동적으로 바뀐다.

Controller 클래스 @RequestMapping에 설정된 URI와 @GetMapping의 URI가 합쳐진 URI가 최종 형태가 된다.

    @PathVariable(" ") : 메서드 파라미터 애너테이션으로 ()은 @GetMapping{" "} 안의 변수명과 동일해야한다.

 

@PatchMapping("/{}") : 클라이언트가 서버에 등록된 리소스를 일부 변경할 때 사용하는 애너테이션

{}안에 들어가는 기능별로 필요한 데이터 변수명에 따라 동적으로 바뀐다.

 

@DeleteMapping("/{}") : 클라이언트가 서버에 등록된 리소스를 삭제할 때 사용하는 애너테이션

{}안에 들어가는 기능별로 필요한 데이터 변수명에 따라 동적으로 바뀐다.

 

7. [핸들러 메서드의 반환 객체(응답 데이터)에 ResponseEntity 객체 적용]

핸들러 메서드는 객체를 반환하는 형태로 응답을 전달하도록 구성되어 있는데

이 객체를 반환할 때 반환객체의 타입을 ResponseEntity라는 타입으로 통일하여 지정한다.

[ResponseEntity]

HttpEntity의 확장 클래스로써, HttpReqeust에 대한 응답 데이터를 포함하는 클래스이다.

(HttpStatus, HttpHeaders, HttpBody를 포함)

 

 

8. [핸들러 메서드의 파라미터에 DTO 객체 적용하기]

DTO (Data Transfer Object) : 데이터의 유효성 검증

클라이언트의 요청을 하나의 객체로 전달받는 역할을 하는 객체. 주 목적은 비용이 많이 드는 HTTP 요청의 수를 줄이기.

애플리케이션의 목적을 위해 필요한 기능을 파악하여 Controller 클래스를 생성하는데,

각 Controller 클래스별로 필요한 데이터들을 DTO 라는 클래스로 묶어서 관리하며 핸들러 메서드의 파라미터로 주입.

DTO 적용하기 전 기존의 핸들러 메서드
DTO 객체를 핸들러 메서드 파라미터에 적용

 

 

[DTO 클래스 생성 및 적용 하기]

1. Controller 클래스의 Request Body가 필요한 핸들러 HTTP POST, PATCH/PUT 메서드를 DTO 클래스 생성.

= DTO 클래스 생성 ONLY FOR @PostMapping, @PatchMapping 애너테이션이 붙은 핸들러 메서드.

 

2. 생성한 DTO 클래스에 @PostMapping, @PatchMapping 핸들러 메서드에 필요한 데이터들을 필드에 선언.

 

3. DTO 클래스에 선언된 멤버 변수들에 대해 @Getter, @Setter 애너테이션 적용.

 

4. 각 변수별로 유효성 검증이 필요한 애너테이션 및 조건을 적용. // @Email, @name, @Pattern

 

[공백만 구성되지 않을 경우]

@NotSpace(message = "공백만으로 구성되지 않아야 한다.")

 

[영문(대소문자 모두 ok)만 가능하며, 워드 사이에 한칸의 공백만 포함될 수 있다.]

@Pattern (regexp = "^([A-Za-z])+(\\s?[a-zA-Z])*$",

message = "영문(대소문자 구분 x)만 가능하며, 워드 사이에 한칸의 공백만 포함될 수 있다.")

 

[숫자의 범위]

@Min(N)

@Max(N)

@Range(min=N, max=M)

 

>> 유효성 검증 애너테이션 사용하기 전 하기 코드 추가해야한다.

 

5. DTO를 생성한 핸들러 메서드의 파라미터로 @RequestBody DTO 객체 주입하기

 

6. DTO 핸들러 메서드를 주입받는 Controller 클래스에 @Validated 애너테이션 붙이기.

 

7. 파라미터로 @PathVariable("변수-명") 변수타입 변수명, @ReqeustBody DTO객체 객체명 주입한다. 

 

8. 핸들러 메서드 동작문에 DTO객체명.set변수명(변수명); 리턴값 설정.

A. @GetMapping, @DeleteMapping

return new ResponseEntity<> (HttpStatus.OK); 작성.

 

B. @PostMapping, @PatchMapping

return new ResponseEntity<> (DTO객체명, HttpStatus.OK); 작성.

 

 

@RequestBody 애너테이션 // 핸들러메서드 파라미터 dto객체 레벨 애너테이션 

JSON 형식의 클라이언트의 RequestBody를 dto객체로 변환시키는 역할

 

@ResponseBody 애너테이션 // 핸들러메서드 파라미터 dto객체 레벨 애너테이션 

JSON 형식의 RequestBody를 클라이언트에게 전달하기 위해 DTO객체를 Response Body로 변환시키는 역할.

< 반환 타입이 ResponseEntity 객체일 경우에는 @ResponseBody 불필요 >