개발은 아름다워

[ Spring ] Content-Type에 따른 어노테이션 간단 정리 - 제약을 통한 정확한 의사소통 본문

스프링

[ Spring ] Content-Type에 따른 어노테이션 간단 정리 - 제약을 통한 정확한 의사소통

do_it_zero 2024. 10. 12. 10:44

content-type에 따라 어떤 어노테이션을 써야하는지 매번 헷갈렸다.
램이 작은 나를 위해 아주 간단하고 명료하게 정리하려고한다.

 

content-type이란?

또 잊어버릴 미래의 나를 위해 content-type을 간단하게 설명하자면,
content-type이란 말 그대로 콘텐츠의 타입이다. 요청 보낼 콘텐츠의 타입은 이거야~! 라고 content-type에 명시해서 서버에 보내는 것이다.

 

그렇다면 왜 content-type을 보내야하지? 간단하게 요청 데이터가 어떤 타입인지 알아야 서버에서도 처리할 수 있기 때문이다.

 

대표적인 content-type의 종류와 그에 맞는 어노테이션

application/x-www-form-urlencoded -> @RequestParam || @ModelAttribute

쿼리 파라미터 또는 폼 데이터로 전달할 때의 content-type이다. application/x-www-form-urlencoded으로 서버에 요청을 보낼 경우 서버는 @ModelAttribute 또는 @RequestParam 를 쓰면 된다.

  • @ModelAttribute 와 @RequestParam의 차이 : ModelAttribute의 경우는 받은 데이터를 객체로 변환할 때 사용하는 것이다.

코드로 확인!

   // content-type : application/x-www-form-urlencoded -> @ReqeuestParam
    @PostMapping("/requestParam")
    public UserDto requestParam(@Valid @RequestParam("name") String name,@Valid @RequestParam("password") String password){
        log.info("request 테스트 중");
        UserDto user = new UserDto(name,password);
        return user;
    }

    // content-type : application/x-www-form-urlencoded -> @ModelAttribute
    @PostMapping("/modelAttribute")
    public UserDto modelAttribute(@Valid @ModelAttribute UserDto user){
        log.info("request 테스트 중");
        return user;
    }

 

application/json -> @RequestBody

json 형식의 데이터를 보낼 때 사용하는 content-type이며 서버에서는 @RequestBody로 데이터를 객체를 변환하여 사용할 수 있다.

   // content-type : application/json -> @RequestBody
   @PostMapping("/requestBody")
   public UserDto requestBody(@Valid @RequestBody UserDto user){
       log.info("request 테스트 중");
       return user;
   }

 

multipart/form-data -> @ReqeustPart || @ModelAttribute

멀티파트 요청을 할 때 쓰는 content-type이며(예를 들어 파일 업로드 등) , 서버에서는 @ReqeustPart 또는 @ModelAttribute로 데이터를 받을 수 있다.

 

 // content-type : multipart/form-data -> @RequestPart
    @PostMapping("/requestPart")
    public UserDto requestPart(@Valid @RequestPart("name") String name,@Valid @RequestPart("password") String password){
        log.info("request 테스트 중");
        UserDto user = new UserDto(name,password);
        return user;
    }

    // content-type : multipart/form-data -> @ModelAttribute
    @PostMapping("/multipartMA")
    public UserDto multipartMA(@Valid @ModelAttribute UserDto user){
        log.info("request 테스트 중");
        return user;
    }

 

 

전체 테스트 코드

postMan으로 요청 테스트를 진행했다.
전체 컨트롤러 코드!

 

@Slf4j
@RestController
public class TestController {

    /**
     * content-type에 따른 어노테이션 사용 정리 예제 코드
     * */

    // content-type : application/x-www-form-urlencoded -> @ReqeuestParam
    @PostMapping("/requestParam")
    public UserDto requestParam(@Valid @RequestParam("name") String name,@Valid @RequestParam("password") String password){
        log.info("request 테스트 중");
        UserDto user = new UserDto(name,password);
        return user;
    }

    // content-type : application/x-www-form-urlencoded -> @ModelAttribute
    @PostMapping("/modelAttribute")
    public UserDto modelAttribute(@Valid @ModelAttribute UserDto user){
        log.info("request 테스트 중");
        return user;
    }

    // content-type : application/json -> @RequestBody
    @PostMapping("/requestBody")
    public UserDto requestBody(@Valid @RequestBody UserDto user){
        log.info("request 테스트 중");
        return user;
    }

    // content-type : multipart/form-data -> @RequestPart
    @PostMapping("/requestPart")
    public UserDto requestPart(@Valid @RequestPart("name") String name,@Valid @RequestPart("password") String password){
        log.info("request 테스트 중");
        UserDto user = new UserDto(name,password);
        return user;
    }

    // content-type : multipart/form-data -> @ModelAttribute
    @PostMapping("/multipartMA")
    public UserDto multipartMA(@Valid @ModelAttribute UserDto user){
        log.info("request 테스트 중");
        return user;
    }

    @Data
    public static class UserDto{
         private String name;
        private String password;

        public UserDto(String name, String password) {
            this.name = name;
            this.password = password;
        }
    }

}

 

정리
content-type 별로 쓸 수 있는 어노테이션을 정리했다. content-type이 있음으로 어떤 콘텐츠 타입인지 명확하게 표현함으로써 서버에서 어떻게 데이터를 받을지도 정확하게 정할 수 있었다. 어쩌면 콘텐츠 타입을 명시하는 것이 제약을 두는 것일 수 있다. 하지만 이 제약으로 인해서 클라이언트와 서버간의 정확한 소통이 가능하게 된다. 프로그램에서 애매한 것은 좋지 않다는 김영한 강사님의 말씀이 생각났다. 오늘 정리를 한 문장으로 표현하자면 제약을 통한 정확한 의사소통!