전 게시물은 Spring 프로젝트 생성에 관한 내용을 작성했다.
코드프레소 Java 웹 개발 체험단 활동 중 이번엔 REST API, Bean, DI(의존성 주입) 강의를 수강하여 이에 관한 포스팅을 하려한다.
계층형 아키텍처 패턴
- 웹 서비스 개발에 주로 사용되는 패턴
- SW를 서로 다른 역할을 하는 3~4개 계층으로 구분
- Presentation Layer
- Application Layer
- Business Layer
- Data Access Layer
- 계층 간에 호출을 하고 데이터를 주고 받으며 협력하며 전체 웹 서비스 구성
Presentation Layer의 역할
- Client로부터 요청을 받아 Application Layer에 처리를 위임
- Application Layer의 결과를 최종 Client로 전달
Application Layer의 역할
- Presentation Layer로부터 받은 결과를 특정 목적을 위해 다양한 비즈니스 로직을 처리한다.
Data Access Layer의 역할
- DB에 접근하여 데이터를 저장하거나 조회하는 역할 (CRUD)
Spring Controller
- 계층형 아키텍처의 Presentation Layer에 해당
- Client의 요청을 받는다.
- Application Layer에 요청에 대한 처리를 위임
- Client에 최종 응답을 하는 역할
- view: Client가 요청에 대한 응답의 결과로 보게 되는 웹 페이지
- data: Client가 요청에 대한 응답으로 받는 데이터
Controller 코드
- Spring Controller를 구현하기 위해서는 3개의 기본 Annotation이 사용된다.
- @Controller와 @RestController: Controller역할을 하는 클래스를 지정, 클래스 상단에 명시
- @RequestMapping: 특정 Request를 처리하는 메소드를 지정, 클래스 또는 메소드 상단에 명시
Annotation 이란
- Java 소스코드에 추가적인 정보를 제공하는 방법
- @로 시작하며 클래스, 메소드, 멤버변수, 파라미터 등에 부착 가능
3가지 유형의 Annotation
- 자바 컴파일러에게 정보를 제공
- SW 툴에 의해 사용되어 코드 생성이나 추가 작업을 진행
- Run time 시 특정 동작을 추가적으로 실행
@Controller와 @RestController의 차이
- 대부분의 요청을 받아서 처리하고 응답을 하는 작업을 한다.
- 응답하는 형태가 다르다.
- Controller는 view를 응답 (html 파일 등)
- RestController: data를 응답 (문자열, Json, xml 등)
@RequestMapping
- RequestMapping이 붙어있는 메소드는 Client의 특정 요청이 왔을 때 Spring Framework에 의해 호출된다.
- RequestMapping이 붙어있는 메소드가 여러 개일 때는 어떤 메소드가 호출될까??
RequestMapping에 value값에 따라 결정된다.
/path에 따라 return되는 값을 Spring Framework가 호출하는 것이다.
URI (Uniform Resource Identifier)
- URL (Uniform Resource Identifier)과 유사한 개념
- 특정한 자원에 접근하기 위함 이름 또는 주소
- 자원: 웹 페이지, 이미지, 영상 등등
- Spring Controller의 메소드들은 URI에 따라 호출이 결정된다.
- 기본 도메인에 이어지는 '/path'들에 의해 결정
ex) localhost:8080/user, localhost:8080/post - RequestMapping Annotation에 URI Path정보를 명시
ex) @RequestMapping(value = "/user")
URI의 활용
- URI는 요청하는 자원의 종류에 따라 이름을 정한다.
- URI는 계층 관계로 표현이 가능하다. '/' 로 계층을 구분
- 단일 웹 어플리케이션 내에서 URI는 중복될 수 없다.
- 네이밍 규약
소문자를 사용
요청하는 자원에 대한 명사 형태로 작성
두단어 이상 연결될 경우 '-'을 사용
의미있는 이름으로 일관성 있게 작성
특정 Controller클래스에 @RequestMapping 활용
- 각각의 메소드를 호출하기 위해 Class 내에 공통적인 Path를 사용하여 메소드 상단에 Mapping을 사용하면 표현할 수 있다.
- /user/paid
paid 메소드 상단에 RequestMapping 어노테이션 사용 - /user/enterprise
enterprise 메소드 상단에 RequestMapping 어노테이션 사용 - /user/administrator
administrator 메소드 상단에 RequestMapping 어노테이션 사용
API (Application Programming Interface)
- Interface란 두 개체 간의 정보를 공유하기 위한 방법(규약)
- 컴퓨터 간의 정보를 공유하기 위한 방법
- 함수나 메소드를 호출하는 형식의 API
- HTTP등의 기술로 네트워크를 통한 원격 자원을 호출하는 API
HTTP API vs REST API
- HTTP(S)를 활용하여 원격의 데이터를 공유하기 위한 API - HTTP API
- 웹 상에서 효율적으로 데이터 공유하기 위한 아키텍처 스타일 - REST API
- 다양한 조건이 만족되어야 하며, 실무에서 모든 조건을 만족하여 구현하기 어렵다. - REST API
- HTTP API와 REST API는 실무에서 혼용하여 사용
@RequestMapping(value = "/user/paid")
public String getPaidUser(){
return "Im a paid user.";
}
@RequestMapping(value = "/user/enterprise")
public String getEnterpriseUser(){
return "Im a enterprise user.";
}
해당 링크를 접속하면 문자열이 paidUser의 문자열이 반환된 것을 확인할 수 있다.
마찬가지로 해당 링크를 접속하면 enterpriseUser의 문자열이 반환된 것을 확인할 수 있다.
만약 User라는 것이 중복이 될때 클래스 내부에 다 중복이 된다면, 클래스 상단에 @RequestMapping(value = "/user") 에노테이션을 작성하여 사용한다.
결과는 똑같이 실행이 될 것이다.
Request 파라미터
- Client가 Server에 요청을 할 때 추가적으로 전송하는 데이터
- 스프링은 Request 파라미터를 메소드의 파라미터에 저장
Query String
- URI와 파라미터의 영역을 구분하여 사용
- URI에 이어지는 '?'뒤에 key1=value&key2=value2&.. 형태로 작성
- key가 파라미터의 이름, value가 파라미터의 값
- 메소드 파라미터에 @RequestParam 에노테이션 사용
- name 요소는 Query String에 key에 매핑됨
Path Parameter
- URI의 일부로 파라미터 값을 사용한다.
- @RequestMapping value URI에 { }로 Path Param 임을 표시
- 메소드 파라미터에 @PathVariable 에노테이션 사용
- 선택적 데이터의 경우에는 Path Param을 잘 사용하지 않음
특정 자원을 요청하는 경우 Path Param을, 정렬이나 추가 필터링을 위한 데이터는 Query String을 사용한다.
필수 테이터는 Path Param으로 선택적 데이터는 Query String 사용
Path Param이 포함된 URI는 Client가 영향을 받기 때문에 변경 비용 높음
Query String은 상대적으로 편하게 확장 가능하다.
실행하고 이와 같이 링크를 접속하면 return된 문자열을 실행한다.
URI에 있는 category와 id가 리턴값에 들어가 페이지에 작성된다.
이번엔 name value를 빼고 required = false를 하고 재실행하면
링크에 category를 빼고 접속했더니 null 값으로 실행되는 것을 볼 수 있다.
즉, required에 true, false값으로 데이터를 필수적 여부를 결정지을 수 있다.
이번엔 defaultValue로 it를 주어 실행했더니
기본값이 설정되어 null이 아닌 it로 출력되었다.
이번엔 PathVariable 실습으로 RequestMapping 값을 바꿔 실행한다.
/user/입력할 문자타입값/id/입력할 id 으로 URI를 접속한다.
그럼 위와 같은 값이 return 값이 출력된다.
RestController의 응답
신규 클래스 생성
- com.codepresso.controllerexercise.dto.UserDto
- 모든 멤버 변수 초기화 하는 생성자 추가
- 모든 멤버 변수에 대한 getter메소드 추가
객체를 반환하면 JSON 형식의 데이터가 응답된다.
JSON(JavaScript Object Notation)
- JSON는 데이터를 교환하는 데에 사용
- 기존의 방법(XML) 보다 가벼움
- XML에 비해 상대적으로 사람이 읽고 이해하기가 쉽다.
JSON 문법
- JSON 객체가 가장 기본 단위로 "key":value 데이터를 포함
- JSON 객체의 시작과 끝은 중활호 { }를 사용
- key는 큰 따옴표 " " 묶음
- value에는 다양한 형태의 데이터 타입 가능
- 다수의 "key":value는 , 로 구분
- 문자열, 숫자, boolean, null
- JSON 객체, JSON 배열
JSON 응답 데이터
- 웹 개발 시 가장 일반적으로 사용하는 응답 데이터 포맷
- 프론트엔드에서는 JSON 형식의 데이터를 응답받아 화면을 구성
- 각 REST API 별로 어떤 JSON 데이터를 응답할 것인지 사전에 정한다.
- 프론트엔드와 백엔드 모두 정해진 JSON 데이터에 맞게 구현
JSON 응답 예제
SpecialtyDto 클래스 생성
- com.codepresso.controllerexercise.dto.SpecialtyDto
- UserDto의 specialties 멤버 변수를 List<SpecialtyDto>로 변경
JSON 응답 예제로 바뀐 것을 확인할 수 있다.
HTTP
- Hyper Text를 컴퓨터가 주고 받기 위한 규약
- 컴퓨터 간의 데이터를 주고 받기 위해서는 명확한 약속이 필요
- IETF, W3C 등의 국제 표준 단체에서 HTTP에 대한 표준을 정하여 배포
- 모든 브라우저에 웹 서버 등은 HTTP 표준에 따라 개발되고 통신
HTTP Method
- HTTP 규약 중 하나로, 특정 자원에 대해 수행하는 행동의 종류를 명시 (자원의 생성, 조회, 수정, 삭제, 일부 수정 등)
- HTTP Method를 사용하면 단일 URI로 다양한 행동을 정의 가능
- GET Method로 자원을 삭제해도 에러가 발생하지는 않음
- 그러나 Best Practice에 맞게 설계하는 것이 권장된다.
주로 사용되는 HTTP Method
- GET (자원의 조회)
- POST (자원의 생성)
- PUT (자원의 수정)
- DELETE (자원의 삭제)
HTTP Method의 구현
- @RequestMapping의 요소로 Method를 명시
- 요청된 HTTP Method에 따라 해당 Controller의 Java메소드를 호출
- 각 Java 메소드에서는 HTTP Method에 해당하는 처리를 수행하도록 설계하는 것이 권장된다.
Request Data
- Client가 서버에 요청 시 전달하는 추가적은 Data
- 우리가 알고 있는 2가지 방식의 데이터 전달방식
- 크기가 큰 데이터를 보내기 위해서는 다른 방식이 필요
Request Body
- 일반적으로 데이터를 저장 및 수정하는 POST, PUT Method에서 사용된다.
- GET, DELETE는 Query String, Path Param이 주로 사용
- Request Body에 다양한 포맷의 데이터 전송 가능
- JSON 데이터 형식이 주로 사용된다.
- Client에서는 JSON 데이터를 전송하고, Spring에서는 JSON 데이터를 Java 객체 파라미터로 저장
@RestController
@RequestMapping(value = "/post")
public class PostController {
@RequestMapping(method = GET)
public String getPost(){
return "GET /post";
}
@RequestMapping(method = POST)
public String savePost(){
return "POST /post";
}
@RequestMapping(method = PUT)
public String updatePost(){
return "PUT /post";
}
@RequestMapping(method = DELETE)
public String deletePost(){
return "DELETE /post";
}
}
이와 같이 controller 패키지에 PostController 클래스를 생성하여 코드를 작성하였다.
/post라는 URI가 각각 4개의 HTTP 메소드들이 어떻게 작동되는 지 확인해보자.
한 개의 예시로 GET 메소드를 Postman에서 실행해보았다.
Body에 JSON 내용을 확인하니 return 값을 받은 String 문자열이 잘 실행된다.
마찬가지로 POST, PUT, DELETE도 잘 실행될 것이다.
이러한 4개의 REST API를 HTTP 메소드에 따라 생성
@GetMapping
public String getPost(){
return "GET /post";
}
@PostMapping
public String savePost(){
return "POST /post";
}
@PutMapping
public String updatePost(){
return "PUT /post";
}
@DeleteMapping
public String deletePost(){
return "DELETE /post";
}
이번엔 코드를 수정해서 RequestMapping을 각 HTTP 메소드 매핑에 맞게 수정해보자.
동일하게 동작하는 지 확인해본다.
package com.codepresso.controllerexercise.dto;
public class PostDto {
Long id;
String title;
String content;
String username;
public PostDto(Long id, String title, String content, String username) {
this.id = id;
this.title = title;
this.content = content;
this.username = username;
}
public Long getId() {
return id;
}
public String getTitle() {
return title;
}
public String getContent() {
return content;
}
public String getUsername() {
return username;
}
}
이번에는 dto 패키지 내에 PostController 클래스를 생성하여 실습해보자.
PostDto는 Client로부터 데이터를 전달받을 때 사용한다.
@PostMapping
public String savePost(@ResponseBody PostDto postDto){
System.out.println(postDto.getId());
System.out.println(postDto.getTitle());
System.out.println(postDto.getContent());
System.out.println(postDto.getUsername());
return "POST /post";
}
그리고 PostController에서 PostMapping 부분을 이와 같이 수정해보고 실행한다.
RequestBody라는 에노테이션을 사용하여 HTTP 메소드를 받을 수 있는 직접 Postman에서 실행해본다.
그러면 이와 같이 정상적으로 작동하고 코드에서 출력문을 작성했었는데 콘솔 창에서 JSON 데이터를 출력하니 Postman에서 작성한 내용이 출력되었다.
API 문서화
- API는 정보를 주고 받기 위한 방법/규약
- API를 사용하기 위해서는 사용 방법을 알아야 한다.
- API 문서는 API를 사용하는 방법을 명세한 문서
REST API 문서화
- 프론트엔드에서 호출하기 위한 REST API의 정보가 명세된 문서
- 백엔드 개발자 주도로 프론트엔드 개발자가 함께 설계
- 프론트엔드 개발자는 약속된 REST API 문서에 의존하여 프론트엔드를 개발 (매우 중요!!)
- 프론트엔드 등 Client에서 호출하고 활용하는 데 어려움이 없도록 상세하게 작성되어야 한다.
REST API 문서가 담고 있어야 하는 정보
- REST API 설명
- URI
- HTTP Method
- Request 파라미터 (필수 파라미터, 선택 파라미터)
- Response 데이터 (필수 응답 데이터와 선택 응답 데이터)
- 가능한 에러 코드 및 대응 방법 (HTTP 에러 코드 등)
- 호출 예시
REST API 문서 예시
- 카카오톡 API
- 인스타그램 API
- swagger
REST API 문서의 활용
- 프론트엔드 개발자와 백엔드 개발자 모두 REST API 문서를 읽고 이해할 수 있어야 한다.
- 백엔드 개발자는 주최하에 프론트엔드 등의 Client를 위해 REST API문서를 작성할 수 있어야 한다.
- REST API문서가 잘 작성될 수록 Communication 비용이 줄어든다.
REST API 문서는 정말 프로젝트하면서 중요하다고 느꼈다. Client 즉, 프론트엔드 개발자가 문서를 읽고 조율하여 개발을 하는데 저번 프로젝트를 진행하면서 한 두개 씩 빠뜨려서 소통이 안되는 현상이 발생되고 양쪽 다 고생하였다...
이번 개념은 정말 중요하고 어떻게 개발해야 하는지 코드프레소를 통해 다시금 느꼈다.
코드프레소 URL: https://www.codepresso.kr/
프리미엄 IT 교육 서비스 - 코드프레소
www.codepresso.kr
'Spring' 카테고리의 다른 글
[Spring boot] @ManyToMany를 사용하면 안 되는 이유 (2) | 2022.10.12 |
---|---|
JPA vs MyBatis 비교 (0) | 2022.03.25 |
[Spring] MyBatis 연동 및 API 테스트 (3) | 2022.02.11 |
[Spring] Spring Service, Bean, 의존성 주입 (0) | 2022.02.07 |
[Spring Boot] Spring 웹 개발 입문 (Spring 프로젝트 생성) (0) | 2022.01.27 |