Back-End (Web)/Spring

[Spring] HTTP Message Body & TEXT

JABHACK 2024. 12. 18. 14:53

JSON

📌 데이터를 표현하기 위한 가볍고 간단한 텍스트 기반의 데이터 교환 형식입니다. 키-값 쌍으로 데이터를 구조화하며, 사람과 기계가 읽고 쓰기 쉽도록 설계되었습니다. 웹 애플리케이션과 서버 간의 데이터 교환에서 널리 사용됩니다.

  • Json은 @RestController 에서 가장 많이 사용되는 데이터 형식이다. 현재 대부분의 API는 Request, Response 모두 JSON 형태로 통신한다.
  • Json 형태로 Data를 전송할 때는 Request Header의 content-type이 꼭 application/json 이여야 한다.

 

JSON의 특징

  1. 가독성:
    • 간단한 문법으로 사람이 읽기 쉽습니다.
  2. 경량성:
    • XML에 비해 데이터 표현이 간결하여 네트워크 트래픽이 적습니다.
  3. 언어 독립성:
    • 대부분의 프로그래밍 언어에서 JSON을 쉽게 생성하고 파싱할 수 있습니다.
  4. 구조화된 데이터 표현:
    • 객체, 배열, 숫자, 문자열 등 다양한 데이터 타입을 지원합니다.

 

JSON의 데이터 타입

문자열 "hello" 큰따옴표로 묶인 텍스트.
숫자 123, 45.67 정수 및 실수 지원.
불리언 true, false 논리 값.
객체 { "key": "value" } 키-값 쌍의 집합.
배열 [1, 2, 3] 여러 값의 순서 있는 리스트.
null null 값이 없음.

 

JSON 처리 (Java 예제)

a. Java 객체 → JSON 변환

Spring Boot에서 Jackson 라이브러리를 사용하여 JSON 데이터를 처리할 수 있습니다.

import com.fasterxml.jackson.databind.ObjectMapper;

public class JsonExample {
    public static void main(String[] args) throws Exception {
        ObjectMapper objectMapper = new ObjectMapper();

        // 객체 생성
        User user = new User("John", 30);

        // 객체를 JSON으로 변환
        String json = objectMapper.writeValueAsString(user);
        System.out.println(json);
    }
}

class User {
    private String name;
    private int age;

    // Constructor, Getters, Setters
    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // Getters and Setters
}

 

JSON과 XML 비교

  JSON XML
가독성 간결하고 읽기 쉬움 태그가 많아 다소 복잡.
데이터 크기 작음 크기가 큼.
파싱 속도 빠름 느림.
데이터 표현 객체 및 배열을 자연스럽게 표현 객체와 배열 표현이 불편함.

 

 

JSON의 장점

  1. 간단하고 가볍다:
    • 데이터 표현이 직관적이고 XML에 비해 크기가 작음.
  2. 언어 독립적:
    • JavaScript뿐만 아니라 Python, Java, PHP 등 다양한 언어에서 지원.
  3. API 표준:
    • RESTful API에서 사실상의 표준 형식으로 사용.

 

JSON 요청

1. HttpServletRequest 사용

더보기
@Data
public class Tutor {
	private String name;
	private int age;
}

@RestController
public class JsonController {
	
	private ObjectMapper objectMapper = new ObjectMapper();

	@PostMapping("/v1/request-body-json")
	public void requestBodyJsonV1(
				HttpServletRequest request, 
				HttpServletResponse response
	) throws IOException {

		// request body message를 Read
		ServletInputStream inputStream = request.getInputStream();
		// UTF-8 형식의 String으로 변환한다.
		String requestBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);

		// String requestBody를 ObjectMapper를 사용하여 변환 "{\"name\":\"wonuk\", \"age\":10}"
		Tutor tutor = objectMapper.readValue(requestBody, Tutor.class);
		
		// 응답
		response.getWriter().write("tutor" + tutor);
	}
}
  • Postman
    • Content-Type 헤더 확인 : application/json

 

  • HttpServletRequest를 사용하여 HTTP Message Body 데이터를 Read하여 문자로 변환한다.
  • 문자로 만들어진 JSON을 Jackson 라이브러리의 objectMapper를 사용하여 Object로 변환

 

 

 

 

 

 

 

2. @RequestBody 사용

더보기
@RestController
public class JsonController {
	
	private ObjectMapper objectMapper = new ObjectMapper();

	@PostMapping("/v2/request-body-json")
  public String requesBodytJsonV2(@RequestBody String requestBody) throws IOException {

      Tutor tutor = objectMapper.readValue(requestBody, Tutor.class);

      return "tutor.getName() = " + tutor.getName() + "tutor.getAge() = " + tutor.getAge();
  }
    
}
Postman

@RequestBody를 사용하여 HTTP Request Body의 Data에 접근한다.

3. ObjectMapper 제거

더보기
@RestController
public class JsonController {
	
	@PostMapping("/v3/request-body-json")
	public String requestBodyJsonV3(@RequestBody Tutor tutor) {
		
		Tutor requestBodyTutor = tutor;

		return "tutor = " + requestBodyTutor;
	}
}
Postman

 

위 Controller가 동작하는 이유는 무엇인가요?
  • @RequestBody
    • @RequestBody 어노테이션을 사용하면 Object를 Mapping할 수 있다.
    • HttpEntity<>, @RequestBody를 사용하면 HTTPMessageConverter가 Request Body의 Data를 개발자가 원하는 String이나 Object로 변환해준다.
    • JSON to Object의 Mapping 또한 가능하다.
      • MappingJackson2HttpMessageConverter 의 역할
      • 쉽게 설명하면 HTTP Message Converter가 ObjectMapper를 대신 실행한다.

4. @RequestBody는 생략할 수 없다.

더보기

@RequstParam, @ModelAttribute는 생략이 가능하다.

 

@Slf4j
@RestController
public class JsonController {
	
	@PostMapping("/v4/request-body-json")
  public String requestBodyJsonV4(Tutor tutor) { // @RequestBody 생략시 @ModelAttribute가 된다.

      Tutor requestBodyTutor = tutor;

      return "tutor.getName() = " + requestBodyTutor.getName() + " tutor.getAge() = " + requestBodyTutor.getAge();
  }
	
}
Postman
  • 생략하면 @ModelAttribute가 된다.
    • 요청 파라미터를 처리하도록 설정된다.
  • Request Header의 contentType은 꼭 application/json 이여야 한다.
    • 위 설정 정보를 기반으로 MessageConverter가 실행된다.

 

5. HttpEntity 사용

더보기
@RestController
public class JsonController {
	
	@PostMapping("/v5/request-body-json")
  public String requestBodyJsonV5(
          HttpEntity<Tutor> httpEntity
  ) {
      // 값을 꺼내서 사용해야한다!
      Tutor tutor = httpEntity.getBody();

      return "tutor.getName() = " + tutor.getName() + " tutor.getAge() = " + tutor.getAge();
  }
	
}

 

Postman
  • HttpEntity<Tutor>
    • Generic Type으로 Tutor가 지정되어 있기 때문에 해당 Class로 반환된다.

 

6. @ResponseBody

더보기
@Controller
public class JsonController {
	
	@ResponseBody // @RestController = @Controller + @ResponseBody
	@PostMapping("/v6/request-body-json")
    public Tutor requestJson(@RequestBody Tutor tutor) {
        return tutor;
  }
	
}
Postman

 

  • View를 조회하지 않고 Response Body에 Data를 입력해서 직접 반환한다.
  • 요청 뿐만이 아니라 응답에도 HttpMessageConverter가 동작한다.
    • MaapingJackson2HttpMessageConverter 적용
    • 응답 객체인 Tutor가 JSON으로 변환되어 반환된다.
  • HttpEntity를 사용해도 된다.

 

요약

  1. 요청 데이터는 @RequestBody를 사용해서 바인딩 하면 된다.
  2. @RequestBody 는 생략이 불가능하다.
    • @ModelAttribute가 적용되기 때문
  3. HttpMessageConverter 가 요청 응답 데이터를 모두 변환할 수 있다.
    • JSON은 MappingJackson2HttpMessageConverter 를 사용한다.
    • Request Header의 Content-Type은 application/json 이어야 한다.
      • Header로 어떤 Converter가 동작할지 판별한다.