@ResponseBody - 객체에서 JSon으로의 변환

Kim Dong Kyun·2023년 8월 23일
1

의문

자바 객체는 Json 형식이 아니다. 그런데 우리가 사용하는 DTO는 자바 객체인데(클래스인데), 어떻게 Json 형식으로 변환이 되는걸까?


마샬링?(Marshalling)

마샬링에 대한 설명 [vs Serialize]

파싱? 인코딩? 직렬화? 마샬링?

파싱(Parsing)

데이터를 분석하여 의미 있는 부분을 추출 하는 과정이다. 텍스트나 구조화된 데이터를 해석하여 프로그램이 이해하고 처리할 수 있는 형식으로 변환된다.

인코딩(Encoding)

데이터를 다른 형식이나 규칙에 따라 변환하는 과정이다. 주로 문자나 데이터를 특정 인코딩 방식으로 변환하여 저장하거나 전송 할 때 사용된다. ex) Base64 로 한글->byte

직렬화(Serialization)

객체의 상태나 데이터를 일련의 바이트로 변환하는 과정이다. 주로 객체를 파일에 저장하거나 네트워크를 통해 전송할 때 사용 되며, 나중에 역직렬화하여 객체를 복원할 수 있다.


그래, @ResponseBody 는 자바 객체를 직렬화해서(마샬링해서) Json 혹은 XML, Text(String) 로 변환시켜주는구나!

그럼, 어떻게 변환을 시켜주나?


1. 요청 처리 과정:

  • 클라이언트 요청 수신: 클라이언트로부터 HTTP 요청이 서버에 도착

  • 핸들러 메서드 호출: Spring은 요청을 처리할 핸들러 메서드(Controller 메서드)를 찾는다. @RequestMapping 어노테이션을 사용하여 요청 URL과 매핑된 메서드를 선택하게 된다

  • 핸들러 메서드 실행: 선택된 핸들러 메서드가 실행되며, 이때 요청 파라미터들과 경로 변수 등이 매개변수로 전달

  • 핸들러 메서드 반환: 핸들러 메서드는 데이터를 반환해준다. 이때 @ResponseBody 어노테이션이 적용되어 있으면 반환되는 객체는 JSON으로 변환되며, 그 과정은 아래와 같다

2. 객체를 JSON으로 변환하는 과정:

  • 메시지 컨버터 선택: Spring은 @ResponseBody 어노테이션이 붙어 있는 메서드가 반환하는 객체를 어떤 형식으로 변환할지 결정하기 위해 메시지 컨버터(Message Converter)를 선택한다. 이 경우 JSON 변환이 필요하므로 JSON 메시지 컨버터가 선택된다(MappingJackson2HttpMessageConverter)

  • 객체를 JSON으로 변환: 선택된 JSON 메시지 컨버터가 반환할 객체를 JSON 형식으로 변환한다(Jackson 라이브러리 사용)


더하여 알아두면 좋은 것들

참고 블로그

  1. @JsonFormat / @JsonProperty

이 글을 작성하게 된 진짜 이유.

@JsonFormat : SHAPE(ex:String) 과 포맷 ("yyyy-MM-dd"...) 등을 설정할 수 있게 해준다.

@JsonProperty : 프로퍼티의 이름 등을 설정한다

여기서 @JsonProperty 가 문제

과제를 하나 부여받고, 코드리뷰를 받았다. 이 때 엔티티에서 시간을 property 로 두기 위해서 엔티티리스너 + @EnableJpaAuditing + @MappedSuperClass 등을 활용해서 시간을 찍는 TimeStamp 엔티티를 따로 주고 상속하는 형태로 시간을 찍었다.

그런데, 이전에 진행한 프로젝트의 포맷을 그대로 쓰다보니 저 @JsonProperty 의 존재를 몰랐던 것..."테스트 통과했으니 문제없지?"라는 안일한 마음이 바로 문제를 일으켰다.

코드리뷰에서 "저 어노테이션이 뭐하는 어노테이션인지 모르는데, 왜 쓴것이냐?"는 질문을 듣고 머리가 하얘져서, 지금 이 글을 쓴다

공부가 된거니 오히려 좋긴 해(사실 되게 감사하다)


  1. 자바의 long과 자바스크립트의 long은 길이가 다르기에(JavaScript의 숫자는 32bit 정수(interger)인 반면, Java의 Long이 표현할 수 있는 숫자는 64bit) String으로 변환하여 넘기는 게 좋다. (프로퍼티를)
  • 그 방법은 @JsonSerialize(using=ToStringSerializer.class) 어노테이션으로 간단히 가능하다

0개의 댓글