Front-End

vsoghlv@naver.com

React.js json Server, cors, proxy

json-server

개발공부를 할 때 연습용으로 API를 받아오기 위해 json-server 를 이용해 연습용 restAPI 서버를 가져올 수 있다.

먼저 기존에 가짜로 만들었던 데이터(posts)를 크롬 콘솔창에 입력한 후 JSON.stringify(posts, null, 2) 를 입력하면 json 형태로 변경해서 돌려준다.

이제 프로젝트 디렉토리에 data.json 파일을 만들고 위에서 json 형태로 변형된 값들을 넣어주자.

//data.json
{
  "posts":[
      {
        "id": 1,
        "title": "리덕스 미들웨어",
        "body": "리덕스 어렵다"
      },
      {
        "id": 2,
        "title": "redux-thunk",
        "body": "thunkthunk"
      },
      {
        "id": 3,
        "title": "리덕스 사가도 공부해야지",
        "body": "사가사가"
      }
    ]
}

이제 이를 기반으로 서버를 열어볼건데 터미널에

npx json-server ./data.json(데이터경로) --port 4000(port)

를 입력해주면된다.

restAPI 를 쉽게 테스트 하기 위해서 getpostman 를 이용하면 편한데 getpostman 안에서 여러 메소드를 사용할 수 있다.

이제 기존에 리덕스를 공부할 때 만들었던 posts 를 만들어 놓은 서버에서 직접 받아와 보자.

//api/posts.js
import axios from "axios";

//getPosts 호출 시 Promise 객체가 만들어지고 500ms 후에 posts 리턴
export const getPosts = async () => {
  const response = await axios.get("http://localhost:4000/posts/");
  return response.data;
};

export const getPostById = async (id) => {
  const response = await axios.get(`http://localhost:4000/posts/${id}`);
  return response.data;
};

Network 에서 확인해보니 제대로 불러오고 있다. 실수로 await 를 빠드리고 했었는데 await 빼먹으니 서버에서 받아는 오는데 reponse.data 가 바로 리턴되서 아무것도 보이지 않았다.

CORS 와 proxy

기본적으로 API 를 요청할 때 브라우저의 현재 도메인과 호출하는 API 의 도메인이 다르다면 브라우저에서 해당 API 에 대한 결과물을 조회할 수 없다.

위에서 json-server 를 공부할 때 원래대로라면 API 도메인과 요청하는 브라우저의 도메인이 다르기 때문에 조회할 수 없어야 된다.

http://localhost:3000/
http://localhost:4000/posts

하지만 가능했던 건 json 에서 어디서 오는 요청이든 다 허용하는 것으로 이미 설정이 되있어서 가능했던 것이다.

만약 실제 서비스를 개발하게 된다면 원칙적으로는 백엔드 서버 쪽에 해당 도메인을 허용하도록 해야 하지만 웹팩 개발서버에서 제공하는 Proxy 를 사용하면 그럴 필요가 없어진다.

프록시를 사용하게 되면, API 를 요청할 때 백엔드 서버에 요청하는 것이 아닌 개발서버의 주소로 요청을 하게되고 그러면 웹팩 개발서버에서 요청을 받아 백엔드로 전달 후 백엔드에서 응답한 내용을 다시 브라우저로 전환한다.

브라우저 요청 -> 개발 서버 -> 프록시(백엔드에 요청 내용 전달) -> 백엔드 응답 -> 프록시(응답 내용 받음) -> 브라우저로 전달

이제야 예전에 하던 프록시 우회가 어떤 개념이었는지 이해가 얼추 된다.

원래 프록시 설정은 웹팩 설정을 통해 하지만, 리액트 프로젝트에서는 packge.json 에서 쉽게 설정할 수 있다.

//package.json 에 추가
  "proxy":"http://localhost:4000"

이후 기존에 API 요청을 하던 주소를 http://localhost:4000/posts 에서 /posts 로 변경해준다.

//api/posts.js
export const getPosts = async () => {
  const response = await axios.get("/posts");
  return response.data;
};

export const getPostById = async (id) => {
  const response = await axios.get(`/posts/${id}`);
  return response.data;
};