개발공부/React

[React] AXIOS를 사용해서 Get, Post 요청(feat. JSON)

jnnjnn 2024. 5. 16. 23:10

Axios는 백엔드와 프론트엔드의 통신을 쉽게 하기 위한 라이브러리로, 프레임워크에서 ajax를 구현하기 위해 사용합니다.

 

AXIOS를 사용하면

  • AJAX 방식으로 응답, 요청할 수 있습니다
  • 자바, 자바스크립트 객체를 자동으로 JSON 형식으로 변환해줍니다

 

npm 설치

npm install axios

 

axios를 사용하기 위해 설치해줍니다

 

Proxy 설정

React의 포트 번호와 스프링의 포트 번호가 다르기 때문에 vite.config.js 파일에서 다음과 같이 설정합니다

server: {
    proxy: {
      "/api": {
        target: "http://localhost:8080",
      },
    },
  },

 

/api 경로로 요청이 오면 :8080 포트로 요청을 보냅니다

 

Get 요청

axios.get("url")을 사용해 해당 url 경로로 get 요청을 보냅니다. 스프링 컨트롤러가 요청을 받아 해당 경로에 매핑된 메소드를 실행합니다.

function App(props) {
  return <div></div>;
  function handleClickButton() {
    const params = new URLSearchParams();
    params.append("id", 5);
    params.append("city", "서울");
    params.append("country", "한국");
    axios.get(`/api/someurl?${params}`);
  }

  return (
    <div>
      <button onClick={handleClickButton}>get 요청</button>
    </div>
  );
}
@GetMapping("/api/someurl")
    public void method6(@RequestParam("id") Integer id,
                        @RequestParam("city") String city,
                        @RequestParam("country") String country) {
        System.out.println("id = " + id);
        System.out.println("city = " + city);
        System.out.println("country = " + country);
    }

 

get 요청 button을 클릭하면 handleClickButton 함수가 실행됩니다.

/api/someurl 경로로 get 요청이 가고 해당 경로에 매핑된 method1이 쿼리스트링을 전달받아 출력합니다

 

Post 요청

axios.post("url",  data)을 사용하여 post 요청을 할 수 있습니다. 스프링 컨트롤러가 요청을 받아 해당 경로에 매핑된 메소드를 실행합니다. 두 번째 파라미터인 data에는 post 요청의 바디에 해당되는 내용이 들어가게 됩니다.

function App(props) {

  function handleClickButton6() {
    const params = new URLSearchParams();
    params.append("id", 5);
    params.append("city", "서울");
    params.append("country", "한국");

    axios.post("/api/someurl3", params);
  }

  return (
    <div>
      <button onClick={handleClickButton6}>post 요청 with data</button>
    </div>
  );
}

 

@PostMapping("/api/someurl3")
    public void method6(@RequestParam("id") Integer id,
                        @RequestParam("city") String city,
                        @RequestParam("country") String country) {
        System.out.println("id = " + id);
        System.out.println("city = " + city);
        System.out.println("country = " + country);
    }

 

요청을 전달받은 컨트롤러 메소드에서 데이터를 전달받아 출력합니다

 

POST 요청으로 JSON 데이터 주고받기

JSON은 자바스크립트 객체와 유사하지만 문자열인 데이터로 키 부분은 문자열,

값 부분에는 문자열, 수, 불린, 객체, 배열 , null 값이 들어갈 수 있습니다.

 

클라이언트와 서버가 요청, 응답과 함께 데이터를 주고받기 위해서는 데이터를 JSON 형식으로 보내야 합니다. 이때 자바스크립트와 자바에서 사용하는 객체를 JSON 형식으로 변환하여 주고받아야 합니다.

 

자바 객체나 자바스크립트 객체를 JSON으로 변환하는 것을 직렬화(Serialization) 또는 Stringify,

다시 JSON 타입을 자바나 자바 스크립트 객체로 변환하는 것을 역직렬화(Deserialization) 또는 파싱(Parse)이라고 합니다

 

Axios와 Spring의 @RequestBody이 직렬화와 역직렬화를 자동으로 처리해줍니다,

 

function handleClick1() {
    const obj1 = { name: "son", age: 44 };
    // const json1 = JSON.stringify(obj1);

    // axios가 두번째 파라미터가 객체면 직렬화 해줌
    axios.post("/api/sub1", obj1);
  }
 @PostMapping("/api/sub1")
    public void sub1(@RequestBody Map<String, Object> map) {
        // @RequestBody
        // 역직렬화(파싱, 디코딩) JSON -> MAP
        System.out.println("map = " + map);
    }

 

 

자바스크립트 객체가 Axios를 통해 JSON으로 직렬화되어 컨트롤러로 전달되고 전달받은 데이터는 @RequestBody 어노테이션을 통해 역직렬화되어 Map<String, Object>에 바인딩 되었습니다

 

 

 @PostMapping("sub6")
    public void sub6(@RequestBody MyBean411 bean411) {
        System.out.println("bean411 = " + bean411);

    }
@Data
public class MyBean411 {
    private String name;
    private Integer age;
}

 

자바 객체에 데이터를 바인딩 할 수도 있습니다

 

JSON 응답 파싱하기

.then은 응답 성공 시(200번대 상태 코드) response를 받습니다.

response.data에 서버가 제공하는 응답이 들어있습니다

 function handleClick3() {
    axios.get("/api/sub3").then((res) => console.log(res.data));
  }

 

컨트롤러가 view로 포워딩 하지 않도록 @RestController 또는 @ResponseBody 어노테이션을 사용합니다

@RestController
@RequestMapping("api")
public class Controller42 {

    @GetMapping("sub3")
    public String method1() {

        return "어떤 데이터";
    }
}

 

String 본문 응답으로 res.data는 "어떤 데이터"를 출력합니다

@GetMapping("/api/sub3")
    @ResponseBody
    public Map<String, Object> method3() {
        return Map.of("name", "흥민",
                "age", 35,
                "married", true,
                "info", Map.of("team", "토트넘",
                        "location", "런던"),
                "item", List.of("축구공", "운동화", "유니폼"));
    }

 

Map 객체 응답으로 res.data는 Map 객체를 출력합니다

 

 @GetMapping("/api/sub3")
    @ResponseBody
    public MyBean411 method5() {
        MyBean411 obj = new MyBean411();
        obj.setName("이강인");
        obj.setAge(55);

        return obj; // json으로 직렬화
    }
public class MyBean411 {
    private String name;
    private Integer age;

    public String getDesc() {
        return STR."이름은 \{name}이고 나이는 \{age}세 입니다.";
    }
}

 

JavaBean 객체 응답으로 res.data는 getter 메소드로 생성된 desc 프로퍼티를 함께 출력합니다

 

 

응답 코드를 명시해서 응답하기

특정 url로 오는 요청의 응답 코드를 지정할 수 있습니다

ResponseEntity.status(응답코드).build()를 리턴하여 원하는 응답코드를 지정합니다

 

자주 쓰는 응답코드는

.status(200)은 .ok()

.status(400)은 .badRequest()

.status(404)는 .notFound

.status(500)은 .internalServerError

등으로 바꾸어 쓸 수 있습니다

@Controller
@RequestMapping("/api")
public class Controller43 {

    // ResponseEntity 상태코드를 직접 명시해서 응답할 때
    @GetMapping("sub1")
    @ResponseBody // ResponseEntity 응답일 땐 생략 가능
    public ResponseEntity sub1() {

        return ResponseEntity.status(200).build();
    }

    @GetMapping("sub2")
//    @ResponseBody
    public ResponseEntity sub2() {
        return ResponseEntity.status(400).build();
    }
}

 

/api/sub1으로 오는 요청은 200번대 응답(ok) /api/sub2로 오늘 요청은 400번대 응답(클라이언트 에러)을 보냅니다

 

 

200(ok)외의 응답 처리하기

.then() 메소드는 200번대의 응답을 받았을 때만 실행되기 때문에 200번대 외의 응답은 .catch()메소드를 사용하여 실행합니다. catch는 response가 아닌 error 객체를 받고 error.response.status로 응답코드를 받을 수 있습니다.

function App(props) {

  function handleStatus() {
    axios
      .get("/api/sub2")
      .then((res) => {})
      .catch((err) => {
        if (err.response.status === 400) {
          console.log("잘못된 요청입니다.");
        } else if (err.response.status === 404) {
          console.log("존재하지 않는 요청입니다.");
        } else if (err.response.status === 500) {
          console.log("서버에서 오류가 발생하였습니다.");
        }
      });
  }

  return (
    <div>
      <button onClick={handleStatus}>응답</button>
    </div>
  );

 

응답 코드가 400번일 경우, 404번일 경우, 500번일 경우 각각 다른 로그를 콘솔에서 출력합니다

 

 

응답코드에 관계없이 항상 실행되는 메소드

.finally()를 사용하면 원하는 코드가 응답코드에 관계없이 항상 실행되게 할 수 있습니다

  axios
      .get(/api/sub4)
      .then(() => {
        console.log("잘 됨 ");
      })
      .catch((error) => {
        const code = error.response.status;
        switch (code) {
          case 401:
            console.log("401 응답 입니다. 로그인되지 않았습니다.");
            break;
          case 403:
            console.log("403 응답 입니다. 권한이 없습니다.");
            break;
        }
      })
      .finally(() => {
        // finally : 응답 코드가 200이든 아니든 항상 실행됨
        console.log("항상 실행되는 메소드");
      });

 

응답 코드에 관계없이 /api/sub4로 get 요청을 보내면 콘솔에 "항상 실행되는 메소드"가 출력됩니다.