회사에서 새로 파일 업로드 기능을 추가하면서 프론트 쪽의 요청을 보내는 코드와 백엔드 쪽의 데이터를 받는 부분을 수정할 일이 생겼다.

 

기존에는 클라이언트에서 JSON 객체에다 필요한 값들을 담아서 서버로 요청을 보냈었다.

let value = {
    seq : compSeq,
    name : compName,
    
    ...
    
}

(이렇게 만든 JSON 객체를 백엔드 서버로 axios를 이용해 전송을 했었다)

 

 

그리고 백엔드 서버에서 @RequestBody를 이용해서 Java 객체로 값을 받을 수 있었다.

public ResponseEntity<Dto> saveInfo(@RequestBody Dto param) throws Exception {
	...
}

 

그런데 파일 업로드 기능을 추가하면서, 프론트 쪽에서 JSON이 아닌 FormData에 필요한 값을 담아 요청을 보내야 하는 상황이 되었다. 

const formData = new FormData();

formData.append('seq', compSeq);
formData.append('name', compName);

...

 

 

전송할 Http Body가 JSON 형태에서 multipart/form-data 형태인 FormData로 바뀌면서,

백엔드 서버에서 Java 객체로 데이터를 받기 위해서 기존의 @RequestBody가 아닌 @ModelAttribute를 사용해야 데이터를 잘 받을 수 있었다.

(그리고 FormData를 보낼 때, header 부분은 브라우저가 자동으로 설정해주기 때문에 Content-Type을 따로 지정할 필요가 없다고 한다)

요청을 보내고 크롬 개발자도구 > 네트워크 탭에서 보낸 요청을 클릭하여 요청 헤더에 있는 Content-Type을 확인해보면, 따로 설정해주지 않아도 multipart/form-data로 되어있는 것을 확인할 수 있다.

 

그래서 @RequestBody와 @ModelAttribute는 무슨 차이가 있는지 찾아보았다.

 

- @RequestBody

클라이언트가 전송하는 Json(Application/json) 형태의 HTTP Body 내용을 Java 객체로 변환시켜주는 역할을 한다.

@RequestBody로 받는 데이터는 Spring에서 관리하는 MessageConverter들 중 하나인 MappingJackson2HttpMessageConverter를 통해 Java 객체로 변환된다.

바인딩이 아닌 변환을 시켜주기 때문에 각각의 변수들에 Setter 메서드가 없어도 해당 객체에 저장이 된다.

 

- @ModelAttribute

클라이언트가 전송하는 multipart/form-data 형태의 HTTP Body 내용과 HTTP 파라미터들을 Setter를 통해 일대일로 객체에 바인딩시켜주는 역할을 한다.

바인딩을 해야 하기 때문에, 맵핑시키는 파라미터의 타입이 객체의 타입과 일치하는지를 포함한 다양한 검증 작업이 추가적으로 진행된다.

@RequestBody와는 다르게 변환이 아니라 바인딩을 시키기 때문에 변수들에 Setter 메서드가 꼭 있어야 한다.

 

 

정리해보면,

나의 경우에는 기존에 JSON 객체를 전송했기 때문에 @RequestBody를 사용해서 JSON 객체를 Java 객체로 변환했었고

이제는 FormData를 전송하기 때문에 @ModelAttribute를 사용해서 데이터를 Java 객체에 Setter를 이용해 바인딩 하게 된 것이다.

 

 

 

 

 

+ Recent posts