티스토리 뷰

728x90
반응형

 

 

 

지난 글에서 컨트롤러 클래스를 작성하며 두 가지 개선할 부분을 지적했다.

 

  • 수작업으로 JSON 문자열을 만들어 주는 부분 - 오타가 나기 쉽고 코드와 그 작성 시간이 길어진다.
  • @RequestParam 애너테이션을 사용한 요청 파라미터 수신 - 파라미터가 많아질수록 코드와 그 작성 시간이 길어진다.

2022.08.22 - [개발/Spring] - [Spring]Spring MVC - Controller 클래스에 핸들러 메서드(Handler Method) 구현

 

[Spring]Spring MVC - Controller 클래스에 핸들러 메서드(Handler Method) 구현

지난 글에서 스프링 MVC의 실제적인 구현을 위해 패키지 구조와 컨트롤러 클래스를 설계했다. 컨트롤러 클래스를 다시 불러오면 아래와 같다. MemberController package com.gnidinger.member; import org.springf..

gnidinger.tistory.com

이번 글에선 마지막으로 작성했던 MemberController를 가져와 리스트의 첫 번째 항목을 개선해 보자.

// 개선 이전 코드

package com.gnidinger.member;

import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping(value = "/v1/members", produces = {MediaType.APPLICATION_JSON_VALUE})
public class MemberController {
    @PostMapping
    public String postMember(@RequestParam("email") String email,
                             @RequestParam("name") String name,
                             @RequestParam("phone") String phone) {
        System.out.println("# email: " + email);
        System.out.println("# name: " + name);
        System.out.println("# phone: " + phone);

        String response =
                "{\"" +
                        "email\":\""+email+"\"," +
                        "\"name\":\""+name+"\",\"" +
                        "phone\":\"" + phone+
                        "\"}";
        return response;
    }

    @GetMapping("/{member-id}")
    public String getMember(@PathVariable("member-id")long memberId) {
        System.out.println("# memberId: " + memberId);

        // not implementation
        return null;
    }

    @GetMapping
    public String getMembers() {
        System.out.println("# get Members");

        // not implementation
        return null;
    }
}

수작업으로 JSON 문자열을 만들어 주는 부분을 개선하기 위해 ResponseEntity를 사용하는데,

 

먼저 ResponseEntity 클래스에 대해 짧게 알아보고 가자.

 


  • ResponseEntity

    • HttpEntity - HTTP 요청(Request)과 응답(Response)에 해당하는 HttpHeaderHttpBody를 포함하는 클래스
    • ResponseEntity - HttpEntity 클래스를 상속받아 HttpHeaders, HttpBody, HttpStatus를 포함
    • 주로 Controller 클래스의 핸들러 메서드(Handler Method)에서 요청 처리에 대한 응답을 구성하는 데 사용
public class HttpEntity<T> {
	private final HttpHeaders headers;
	@Nullable
	private final T body;
}
public class ResponseEntity<T> extends HttpEntity<T> {

	private final Object status;

	public ResponseEntity(HttpStatus status) {
		this(null, null, status);
	}

	public ResponseEntity(@Nullable T body, HttpStatus status) {
		this(body, null, status);
	}
    // ...
}

계속해서 ResponseEntity와 Map을 이용해 개선된 코드를 보자.

package com.gnidinger.member;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("/v1/members") // (1) produces 설정 제거
public class MemberController {
    @PostMapping
    public ResponseEntity postMember(@RequestParam("email") String email,
                                     @RequestParam("name") String name,
                                     @RequestParam("phone") String phone) {
        // (2) JSON 문자열 수작업을 Map 객체로 대체
        Map<String, String> map = new HashMap<>();
        map.put("email", email);
        map.put("name", name);
        map.put("phone", phone);

        // (3) 리턴 값을 ResponseEntity 객체로 변경
        return new ResponseEntity<>(map, HttpStatus.CREATED);
    }

    @GetMapping("/{member-id}")
    public ResponseEntity getMember(@PathVariable("member-id") long memberId) {
        System.out.println("# memberId: " + memberId);

        // not implementation

        // (4) 리턴 값을 ResponseEntity 객체로 변경
        return new ResponseEntity<>(HttpStatus.OK);
    }

    @GetMapping
    public ResponseEntity getMembers() {
        System.out.println("# get Members");

        // not implementation

        // (5) 리턴 값을 ResponseEntity 객체로 변경
        return new ResponseEntity<>(HttpStatus.OK);
    }
}
  • (1), (2) - produces 속성 생략 및 JSON 문자열 수작업이 Map 객체로 대체

    • Map 객체를 리턴하게 되면 스프링 MVC 내부에서 JSON 형식으로 자동 변환
    • 따라서 @RequestMapping 부분의 produces 속성 생략 가능
  • (3) 리턴 값으로 JSON 문자열(String)을 리턴하던 부분이 ResponseEntity 객체 리턴으로 변경

    • new ResponseEntity<>(map, HttpStatus.CREATED); 와 같이 응답 데이터뿐 아니라 응답 상태까지 전달
    • HTTP 응답 상태를 명시적으로 전달함으로써 클라이언트의 요청을 서버가 어떻게 처리했는지 확인 가능
  • (4), (5) 나머지 핸들러 메서드 역시 ResponseEntity 객체를 리턴하는 것으로 변경 및 응답 상태도 전달하도록 수정

개선 후 동일한 요청을 보냈을 때 응답 상태가 ‘200 OK’에서 ‘201 Created’로 바뀐 것을 확인할 수 있다.

 

이어서 CoffeeController 클래스와 OrderController 클래스를 개선하면 아래와 같이 된다.

package com.gnidinger.coffee;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("/v1/coffees")
public class CoffeeController {
    @PostMapping
    public ResponseEntity postCoffee(@RequestParam("engName") String engName,
                                     @RequestParam("korName") String korName,
                                     @RequestParam("price") String price) {

        Map<String, String> map = new HashMap<>();
        map.put("engName", engName);
        map.put("korName", korName);
        map.put("price", price);

        return new ResponseEntity<>(map, HttpStatus.CREATED);
    }

    @GetMapping("/{coffee-id}")
    public ResponseEntity getCoffee(@PathVariable("coffee-id") long coffeeId) {
        System.out.println("# coffeeId: " + coffeeId);

        // not implementation

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

    @GetMapping
    public ResponseEntity getCoffees() {
        System.out.println("# get Coffees");

        // not implementation

        return new ResponseEntity<>(HttpStatus.OK);
    }
}
package com.gnidinger.order;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("/v1/orders")
public class OrderController {
    @PostMapping
    public ResponseEntity postOrder(@RequestParam("memberId") long memberId,
                                     @RequestParam("coffeeId") long coffeeId) {

        Map<Object, Object> map = new HashMap<>();
        map.put("memberId", memberId);
        map.put("coffeeId", coffeeId);

        return new ResponseEntity<>(map, HttpStatus.CREATED);
    }

    @GetMapping("/{order-id}")
    public ResponseEntity getOrder(@PathVariable("order-id") long orderId) {
        System.out.println("# orderId: " + orderId);

        // not implementation

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

    @GetMapping
    public ResponseEntity getOrders() {
        System.out.println("# get Orders");

        // not implementation

        return new ResponseEntity<>(HttpStatus.OK);
    }
}
반응형
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/09   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
글 보관함