REST API - Response 확인하는 3가지 방법

제훈·2024년 8월 26일

Spring

목록 보기
15/18

Response 확인하는 3가지 방법

  1. IntelliJ http 파일
  2. PostMan
  3. Swagger

3가지 방법이 있다.

간단하게 RestController 파일을 만들어서 확인해보자.

ResponseController

@RestController
@RequestMapping("/response")
public class ResponseRestController {

    @GetMapping("/hello")
    public String helloWorld() {
        return "hello world";
    }

    @GetMapping("random")
    public int getRandomNumber() {
        return (int)(Math.random() * 10) + 1;
    }

    @GetMapping("message")
    public Message getMessage() {
        return new Message(200, "메시지를 응답합니다.");
    }
    
    @GetMapping("jsonTest")
    public List<Map<String, Object>> getJsonTest() {
        List<Map<String, Object>> list = new ArrayList<>();
        Map<String, Object> map = new HashMap<>();
        map.put("test1", new Message(200, "성공 1"));
        map.put("test2", new Message(200, "성공 2"));

        Map<String, Object> map2 = new HashMap<>();
        map2.put("nextUrl", "http://localhost:8080/hello");

        list.add(map);
        list.add(map2);

        return list;
    }
}

Message 클래스

public class Message {
    private int httpStatusCode;
    private String message;
	
    // 기본 생성자, 매개변수를 가진 생성자, getter, setter, toString()
}

일단 인텔리제이에서 확인하는 방법부터 알아보자.

IntelliJ http 파일

get.http 파일

### GET request hello
GET localhost:8080/response/hello

### GET request random
GET localhost:8080/response/random

### GET request message
GET localhost:8080/response/message

### GET request jsontest
GET localhost:8080/response/jsonTest

위와 같은 형태로 확인이 가능하다.

random은 1~10까지 잘 출력이 될 것이고, message도 지정해둔 message가 잘 보일 것이다.

마지막 것만 같이 확인해보자.


PostMan

똑같이 다운로드만 받고 활용하면 된다.


Swagger

스웨거는 dependency가 일단 build.gradle에 추가돼야 한다.

    // https://mvnrepository.com/artifact/org.springdoc/springdoc-openapi-starter-webmvc-ui
    implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.3.0'

위 사진처럼 적용이 되면 확인 가능한데,

http://localhost:8080/swagger-ui/index.html

SwaggerConfig에서 설정파일로 지정해둔 뒤 위의 URL로 이동하면 확인 가능할 것이다.

@OpenAPIDefinition(
        info = @Info(title = "Lecture API 명세서",
                description = "수업용 API 명세서",
                version = "v1"))
@Configuration
public class SwaggerConfig {

}


이미지 파일도 추가해보자.

ResponseRestController 에 추가

    @GetMapping(value = "image", produces = MediaType.IMAGE_JPEG_VALUE)
    public byte[] getImage() throws IOException {
        return getClass().getResourceAsStream("/static/images.jpg").readAllBytes();
    }

get.http에 추가

### GET request image
GET localhost:8080/response/image

출력 결과


Response Entity로 반환해보기

Response Entity : HttpRequest를 응답하기 위해 httpEntity를 상속받아 HttpStatus, HttpHeaders, HttpBody를 정의하여 사용되는 클래스이다. (필수는 아니지만 관례상 많이 사용)

User들을 Response Entity로 기본 생성자를 활용해 여러 정보를 임의로 담아 리스트에 담은 채로 반환하려고 한다.

UserDTO

public class UserDTO {
    private int userCode;
    private String id;
    private String pwd;
    private String name;
    private java.util.Date enrollAt;
    
    // 기본 생성자, 매개변수가 있는 생성자, getter, setter. toString()
}

Http 상태코드와 메세지, 결과를 담고 있을 ResponseMessage

public class ResponseMessage {
    private int httpStatusCode;
    private String message;
    private Map<String, Object> result;
    
    // 기본 생성자, 매개변수가 있는 생성자, getter, setter. toString()
}

직접 만들어서 반환하기

ResponseEntityTestController

@RestController
@RequestMapping("/entity")
public class ResponseEntityTestController {

    private List<UserDTO> users;
    public ResponseEntityTestController() {
        this.users = new ArrayList<>();

        users.add(new UserDTO(1, "user01", "pass01", "홍길동", new java.util.Date()));
        users.add(new UserDTO(2, "user02", "pass02", "유관순", new java.util.Date()));
        users.add(new UserDTO(3, "user03", "pass03", "이순신", new java.util.Date()));
    }

    @GetMapping("users")
    public ResponseEntity<ResponseMessage> findAllUsers() {
        HttpHeaders headers = new HttpHeaders();

        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));

        Map<String, Object> responseMap = new HashMap<>();
        responseMap.put("users", users);

        ResponseMessage responseMessage = new ResponseMessage(200, "조회성공", responseMap);

        return new ResponseEntity<>(responseMessage, headers, HttpStatus.OK);
    }
}

이렇게 컨트롤러에서 기본 생성자로 user들을 만든 뒤 Message 타입으로 된 ResponseEntity를 만들고, user들을 담아서 조회가 되는지 확인할 것이다.

user.http 파일에 만들어서 GET 요청을 보냈을 때의 response도 확인해보았다.


빌더를 활용한 메소드 체이닝 방식 사용하기

위의 직접 만들어주는 것보다 더 많이 사용하는 방식인 메소드 체이닝 방식을 활용해보자.

Controller에 추가

	@GetMapping("users/{userCode}")
    public ResponseEntity<ResponseMessage> findUserByNo(@PathVariable int userCode) {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));

        /* 설명. 요청 리소스(회원 번호와 일치하는 회원 한 명)를 추출하는 부분 */
        UserDTO foundUser = users.stream().filter(user -> user.getUserCode() == userCode).collect(Collectors.toList()).get(0);

        Map<String, Object> responseMap = new HashMap<>();

        responseMap.put("user", foundUser);

        return ResponseEntity
                .ok()
                .headers(headers)
                .body(new ResponseMessage(200, "조회 성공", responseMap));
    }

http 파일에 추가

### GET request users -> userCode = 2
GET localhost:8080/entity/users/2

결과


json body에 입력된 데이터로 POST 요청

json body에 입력된 데이터로 POST 요청을 해볼 것이다.

기존의 @RequestParam과 달리 json 문자열이 핸들러 메소드로 넘어올 때는 @RequestBody를 붙이고, json 문자열에는 각 프로퍼티 별로 받을 수도 있다.

하지만, 하나의 타입으로 다 받을 때는 커맨드 객체 (여기는 UserDTO)를 활용해야 하고, 커맨드 객체는 json 문자열의 프로퍼티 명과 일치해야 한다.

그래서 http 파일에도 post 요청을 만들면서 테스트용 데이터를 만들자.

http 파일에 추가

### Send POST request with json body
POST localhost:8080/entity/users
Content-Type: application/json

{
  "id": "user04",
  "pwd": "pass04",
  "name": "신사임당",
  "enrollAt": "2024-08-27T00:20:39.165+00:00"
}

컨트롤러에 추가

    @PostMapping("/users")
    public ResponseEntity<?> registUser(@RequestBody UserDTO newUser) {
        // ? -> 반환하는게 없어서 타입 지정을 하고 싶지 않을 때 사용
        int lastUserNo = users.get(users.size() - 1).getUserCode();
        newUser.setUserCode(lastUserNo + 1);

        users.add(newUser);

        return ResponseEntity
                .created(URI.create("/entity/users/" + users.get(users.size() - 1).getId()))
                .build();
    }

soft delete라는 가정으로 users의 사이즈를 사용해서 마지막 userCode를 알아낸 뒤, 새롭게 추가해줬다.

ResponseEntity 에서는 created를 통해 Response Header에 Location이라는 속성으로 생성된 리소스를 찾아갈 경로를 제시할 수 있다.

userCode = 4 로 조회해보기

잘 된 것을 볼 수 있다.


json body에 입력된 데이터로 PUT 요청

http 파일에 추가

### Send PUT request
PUT localhost:8080/entity/users/4
Content-Type: application/json

{
  "id": "user04",
  "pwd": "pass04",
  "name": "신사임니당"
}

Controller에 추가

    @PutMapping("users/{userCode}")
    public ResponseEntity<?> modifyUser(@RequestBody UserDTO modifyUser, @PathVariable int userCode) {
        UserDTO foundUser = users.stream().filter(userDTO -> userDTO.getUserCode() == userCode)
                .collect(Collectors.toList())
                .get(0);

        foundUser.setId(modifyUser.getId());
        foundUser.setName(modifyUser.getName());
        foundUser.setPwd(modifyUser.getPwd());

        return ResponseEntity
                .created(URI.create("/entity/users/" + userCode))
                .build();
    }

기본 생성자에서 실행할 때마다 매번 3번까지만 만들어줘서 위의 POST 요청으로 4번을 추가해준 뒤 실행하거나, 아니면 PathVariable 부분을 1~3 으로 바꿔주면 된다.

전체 조회로 수정된 것 확인하기 (일부만 캡처)


삭제 요청

Delete api는 Hard delete이다. 그래서 이렇게 기본 생성자에서 데이터를 만드는 것 이외에는 사용하지 않는 것이 좋은 것으로 알고 있는데 한 번 더 공부를 해서 이후에 다뤄보겠다.

http 파일에 추가

### DELETE request users
DELETE localhost:8080/entity/users/1

Controller에 추가

    @DeleteMapping("users/{userCode}")
    public ResponseEntity<?> deleteUser(@PathVariable int userCode) {
        UserDTO foundUser = users.stream().filter(userDTO -> userDTO.getUserCode() == userCode)
                .collect(Collectors.toList())
                .get(0);

        users.remove(foundUser);

        return ResponseEntity
                .noContent()
                .build();
    }

출력은 생략하겠다 잘 되는 것을 알 수 있을 것이다.


프로젝트 준비로 인해 시간을 많이 보내야할 것 같아서 교육을 들을 때는 한동안 블로그 글은 작성하기 힘들지만, 그 공백을 Real MySQL8.0을 읽고 작성해 채워보려고 한다.

profile
백엔드 개발자 꿈나무

0개의 댓글