본문 바로가기
공부/프로그래밍

[spring, axios] Content-Type 을 json 또는 application/x-www-form-urlencoded 로 전송 테스트

by demonic_ 2020. 3. 4.
반응형

제목: [spring, axios] Content-Type 을 json 또는 application/x-www-form-urlencoded 로 전송 테스트

 

 

서버와의 통신 시 유형을 정하는 경우가 있는데, 상황에 따라 에러가 각기 나와 이참에 정리해두려 한다.

 

SpringBoot 2가지 유형을 받을 컨트롤러를 생성한다

 

TestController.java

@RestController
public class TestController {

    // application/json 으로 받을 때
    @PostMapping(value = "/test/json")
    public String testIndex(@RequestBody Map map) {
        System.out.println("map = " + map);

        return "testIndex";
    }

    // application/x-www-form-urlencoded (form)으로 받을때
    @PostMapping(value = "/test/form")
    public String testIndex2(@RequestParam Map map) {
        System.out.println("map = " + map);
        return "testIndex2";
    }
}

 

 

클라이언트에는 axois를 이용해 테스트 했다

 

axios에는 전송하는 파라미터에 따라 form 과 json을 분리하여 전송한다

예를들면 다음과 같다

 

test.jsx

testPostAjax = () => {
    const url = "http://localhost:8080/test/json";
    const sendParam = {
        name: '홍길동',
        age: 20
    }

    axios.post(url, sendParam)
        .then((res) => {
            console.log(res)
        })
        .catch((error) => {
            console.log(error.response)
        })
}

 

sendParam을 보면 json형태로 구성되어 있다. 이걸 data파라미터에 넣으면 json으로 받게 구성되어있는 /test/json 로 호출해보면 정상적으로 데이터를 받는다.

 

그런데 여기다가 header를 설정하면 다음과 같은 에러를 리턴한다

testPostAjax = () => {
    const url = "http://localhost:8080/test/json";
    // 추가된 부분
    const axiosConfig = {
        headers:{
            "Content-Type": "application/x-www-form-urlencoded"
        }
    }

    const sendParam = {
        name: '홍길동',
        age: 20
    }

    // headers 내용 추가
    axios.post(url, sendParam, axiosConfig)
        .then((res) => {
            console.log(res)
        })
        .catch((error) => {
            console.log(error.response)
        })        
}

 

클라이언트 에러 로그

 

서버 에러 로그

2020-03-03 16:38:23.458  WARN 34475 --- [nio-8080-exec-4] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/x-www-form-urlencoded;charset=UTF-8' not supported]

 

'application/x-www-form-urlencoded;charset=UTF-8' 를 지원하지 않는다고 쓰여있는데 컨트롤러에서 @RequestBody를 지우면 사실상 가능하다(대신 파라미터를 받을 수 없다)

 

415 에러는 Unsupported Media Type 에러인데, json으로 전송해놓고 form으로 지정해 발생한 오류이니 의도한대로 테스트 되었다.

 

 

이번에는 form에다 전송을 해보자.

testPostForm = () => {
    const url = "http://localhost:8080/test/form";

    let form = new FormData();
    form.append("name", '홍길동');
    form.append("age", 20);

    axios.post(url, form)
        .then((res) => {
            console.log(res)
        })
        .catch((error) => {
            console.log(error.response)
        })
}

 

FormData 를 이용해서 파라미터를 넣어 전송해보면 정상작동 한다.

form을 일일히 쓰기 싫고 json으로 관리되고 있다면 queryString을 이용하면 되는데, 명령어는 qs.stringify(jsondata) 다.

 

React.js 에서는 다음과 같이 import 하여 사용이 가능하다.

...
import qs from 'query-string';

...
testPostForm = () => {
    const url = "http://localhost:8080/test/form";

    const sendParam = {
        name: '홍길동',
        age: 20
    }

    axios.post(url, qs.stringify(sendParam))
        .then((res) => {
            console.log(res)
        })
        .catch((error) => {
            console.log(error.response)
        })
}
...

 

만약 여기다 header 를 application/json 으로 변경하면 어떻게 될까?

FormData 로 생성하여 전송하면 파라미터가 전송되지만 queryString 을 이용해 변환하여 전환할 경우

서버에서 데이터로 전환하지 못한다.

testPostForm = () => {
    const url = "http://localhost:8080/test/form";
    const axiosConfig = {
        headers:{
            "Content-Type": "application/json"
        }
    }

    let form = new FormData();
    form.append("name", '홍길동');
    form.append("age", 20);

    axios.post(url, form, axiosConfig)
        .then((res) => {
            console.log(res)
        })
        .catch((error) => {
            console.log(error.response)
        })
}                

서버 로그

map = {name=홍길동, age=20}

 

queryString 을 이용해 전송하는 경우

testPostForm = () => {
    const url = "http://localhost:8080/test/form";
    const axiosConfig = {
        headers:{
            "Content-Type": "application/json"
        }
    }

    const sendParam = {
        name: '홍길동',
        age: 20
    }

    axios.post(url, qs.stringify(sendParam), axiosConfig)
        .then((res) => {
            console.log(res)
        })
        .catch((error) => {
            console.log(error.response)
        })
}                

서버 로그

map = {}

 

그렇다면 이 상태에서 json으로 받던 url(/test/json)로 전송하면 어떻게 될까?

역시나 통과되지 않고 다음의 에러가 발생했다.

Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Unrecognized token 'age': was expecting (JSON String, Number, Array, Object or token 'null', 'true' or 'false'); nested exception is com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'age': was expecting (JSON String, Number, Array, Object or token 'null', 'true' or 'false')

 

 

무엇을 사용하든 마음이지만 실무적으로 생각한다면 json형태로 데이터를 주고받는게 좀더 익숙할 것이다.

다만 queryString을 사용할 경우 행여 서버측에서 제대로 전송받지 못하고 있다면 서버쪽에도 문제가 있진 않은지 점검이 필요하다.

 

최근에 외부연동 중에는 form으로 전송을 받는 것이 있었는데 FormData를 사용하면 데이터가 전송되지 않는 문제가 있었다.

혹시나 해서 queryString을 이용해 전송했더니 제대로 전송이 되었다.

수정문의를 할 수 없는 상황이라 그냥 queryString으로 썼다.

form 이 안될경우 queryString 을 이용해 파라미터를 전송해보는 테스트를 꼭 해보자.

 

끝.

 

반응형

댓글