저번에는 REST API 설계하는 방법에 대해 배워보았다. 오늘은 실제로 코드로 작성하는 방법을 배워볼 예정이다.
- 언어 :
Java
- Framework :
Spring Boot
- IDE :
IntelliJ
- Test :
POSTMAN
- HTTP 통신 :
json
형태
오늘 살펴볼 프로젝트는 [가게 앞 웨이팅 등록 시스템]
프로젝트이다.
이 프로젝트는 MVC 패턴으로 구성되어 있으며, DB Framework는 MyBatis
로 되어 있다.
예시를 들 API는 사장님의 고유 번호로 테이블의 상태를 체크하는 API를 만들어 볼 예정이다.
일단 지난 글을 참고하여 REST API를 설계해보자. 설계한 후에, 하나씩 개발해보자.
📝 지난글 : [Spring] REST API를 설계해보자
현재는 사장님 고유 번호 (4)번을 GET
방식인 Query String으로 memberNumber = 4
로 전송하는 모습이다.
2번 사장님을 조회하고 싶다면, http:localhost:8080/desk?memberNumber=2
로 하면 되겠다.
실제 프로젝트에서는 JWT를 이용한 사용자 검증을 하는데, 여기서는 간단하게 작성하겠다.
응답 Json
에 다양한 내용을 넣을 수 있지만 나는 매우 간단하게 4가지만 넣었다.
code
: HTTP 상태 codehttpStatus
: 코드 상태에 따른 메세지message
: 현재 응답 내용 메세지data
: 실제 Client에게 반환할 데이터들
Response를 아래와 같이 세팅하기 위해서는 클래스로 생성해 준다.
code
: HTTP 상태 codehttpStatus
: 코드 상태에 따른 메세지message
: 현재 응답 내용 메세지data
: 실제 Client에게 반환할 데이터들
📂 project
> src
> main
> java
> package명
> DTO
RestResponse.java
생성한다
package com.waiting.waitingnow.DTO;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.http.HttpStatus;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class RestResponse<T> {
private Integer code;
private HttpStatus httpStatus;
private String message;
private T data;
}
lombok
이 없어서 오류 난다면, bulid.gradle
또는 maven
으로 추가하자
bulid.gradle
compileOnly 'org.projectlombok:lombok' annotationProcessor 'org.projectlombok:lombok'
maven
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.30</version> <scope>provided</scope> </dependency>
그럼 이제 거의 다 된거나 마찬가지이다.
📂 project
> src
> main
> java
> package명
> controller
DeskController.java
를 생성한다.
DeskControlller
에서는 클라이언트에서 요청이 들어오면 데이터를 반환하는 코드가 작성되어 있다.
Controller에서는 데이터만 넘겨주는 역할만 한다. 실제 조회하는 로직들은 service
나 DAO
에 작성되어 있는데, 이 부분은 각자 코딩해야한다.
package com.waiting.waitingnow.controller;
import com.waiting.waitingnow.DTO.RestResponse;
import com.waiting.waitingnow.service.DeskService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
public class DeskController {
private final DeskService deskService;
RestResponse<Object> restResponse = new RestResponse<>();
@Autowired
public DeskController(DeskService deskService) {
this.deskService = deskService;
}
/**
* Desk 조회하는 API
*
* @param memberNumber
* @return
* @throws Exception
*/
@ResponseBody
@RequestMapping(value = {"/desk"}, method = RequestMethod.GET)
public ResponseEntity deskSearch(@RequestParam("member-number") int memberNumber) throws Exception {
System.out.println("[desk 조회] memberNumber : " + memberNumber);
try {
List<SendDeskVO> desks = deskService.selectByMember(memberNumber);
restResponse = RestResponse.builder()
.code(HttpStatus.OK.value())
.httpStatus(HttpStatus.OK)
.message(memberNumber + "의 desk 조회")
.data(desks)
.build();
return new ResponseEntity<>(restResponse, restResponse.getHttpStatus());
}
// 일치하는 전화번호가 없을 때, NullpointerException 발생
catch (NullPointerException e) {
restResponse = RestResponse.builder()
.code(HttpStatus.NOT_FOUND.value())
.httpStatus(HttpStatus.NOT_FOUND)
.message(e.getMessage())
.build();
return new ResponseEntity<>(restResponse, restResponse.getHttpStatus());
}
}
}
@RestController //RestController 어노테이션 사용
public class DeskController {
//우리가 위에서 만든 응답 형태 (code, httpStatus, message, data)
RestResponse<Object> restResponse = new RestResponse<>();
// 의존성 주입 방식 : 생성자 주입 방식
private final DeskService deskService;
@Autowired
public DeskController(DeskService deskService) {
this.deskService = deskService;
}
우리가 제작한 restResponse
를 import하여 사용한다.
@ResponseBody
@RequestMapping(value = {"/desk"}, method = RequestMethod.GET) // API URI와 메소드를 지정
public ResponseEntity deskSearch(@RequestParam("member-number") int memberNumber) throws Exception {
System.out.println("[desk 조회] memberNumber : " + memberNumber);
만약 POST 방식이라면 method = RequestMethod.POST
로 하면 된다.
반환 타입은 ResponseEntity로 json형태
로 반환 할 것이다.
@RequestParam("member-number") int memberNumber
는 Param
으로 주어진 값이 memberNumber
에 저장된다.
현재 요청 URI가 localhost:8080/desk?member-number=4
인데, 그러면 자동으로 memberNumber 변수
에 4가 할당된다.
- Param 사용 (주로 GET 방식) : @RequestParam
- Body 사용 (주로 POST 방식) : @RequestBody
- Header 사용 : @RequestHeader
try {
List<SendDeskVO> desks = deskService.selectByMember(memberNumber);
restResponse = RestResponse.builder()
.code(HttpStatus.OK.value())
.httpStatus(HttpStatus.OK)
.message(memberNumber + "의 desk 조회")
.data(desks)
.build();
return new ResponseEntity<>(restResponse, restResponse.getHttpStatus());
}
deskService.selectByMember
를 호출하면 회원 번호에 따른 정보들을 반환 받게 된다.
SelectByMember
: 본인이 원하는 로직을 작성하면 된다.이때 일치하지 않은 회원 정보라면 deskService.selectByMember
에서 NullPointerException
을 반환한다. → 4번으로 이동
.code
는 HTTP 상태 코드이므로,
200
이면 HttpStatus.OK.value()
이고
404
라면 HttpStatus.NOT_FOUND.value()
이다.
조회한 데이터를 .data(desks)
에 담아 반환한다.
// 일치하는 회원번호가 없을 때, NullpointerException 발생
catch (NullPointerException e) {
restResponse = RestResponse.builder()
.code(HttpStatus.NOT_FOUND.value())
.httpStatus(HttpStatus.NOT_FOUND)
.message(e.getMessage())
.build();
return new ResponseEntity<>(restResponse, restResponse.getHttpStatus());
}
테스트를 위해서는 POSTMAN을 사용하면 좋다.
사용법은 구글에 검색해보자!~ Postman 사용법
서버를 먼저 실행시키고
POSTMAN으로 보내보자. GET
방식으로 파라미터를 넣어서 보냈다
응답을 보니, 생각 했던 대로 잘 왔다.
아래는 없는 회원번호로 요청을 보냈더니 이것도 잘 404를 띄워주었다.
혹시나 POST
방식으로 보낼때는 Body에 넣어 보내면 된다.
Body
> raw
> JSON
에 넣고 싶은 값들 넣어서 보내면 된다.