Posts [프론트엔드 개발환경의 이해와 실습] 웹팩 API 서버 연동
Post
Cancel

[프론트엔드 개발환경의 이해와 실습] 웹팩 API 서버 연동

API 연동

프론트엔드에서는 서버와 데이터 주고 받기 위해 ajax를 사용한다. 보통은 api 서버를 어딘가에 띄우고(혹은 로컬 호스트에 띄우고) 프론트 서버와 함께 개발한다. 개발 환경에서 이러한 api 서버 구성을 어떻게 하는지 알아 보자.

목업 API 1: devServer.before

웹팩 개발 서버 설정 중 before 속성은 웹팩 서버에 기능을 추가할 수 있는 여지를 제공한다. 이것을 이해하려면 노드 Express.js에 사전지식이 있으면 유리한데, 간단히 말하면 익스프레스는 미들웨어 형태로 서버 기능을 확장할 수 있는 웹프레임워크다.

devServer.before에 추가하는 것이 바로 미들웨어인 셈이다. 아래 코드를 보자.

  • webpack.config.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
module.exports = {
  devServer: {
    before: (app) => {
      app.get("/api/users", (req, res) => {
        res.json([
            {
                id: 1,
                name: "Alice"
            },
            {
                id: 2,
                name: "Bek"
            },
            {
                id: 3,
                name: "Chris"
            },
        ])
      })
    },
  },
}

before에 설정한 미들웨어는 익스프레스에 의해서 app 객체가 인자로 전달되는데 Express 인스턴스다. 이 객체에 라우트 컨트롤러를 추가할 수 있는데 app.get(url, controller) 형태로 함수를 작성한다. 컨트롤러에서는 요청 req과 응답 res 객체를 받는데 여기서는 res.json() 함수로 응답하는 코드를 만들었다.

웹팩 개발 서버는 GET /api/users 요청시 3개의 엔트리를 담은 배열을 반환할 것이다. 서버를 다시 구동하고 Dom 로드시 ajax 요청을 해서 데이터를 받아오도록 변경해보자.

먼저 ajax 라이브러리인 axios를 설치한자.

1
npm i axios

그리고 app.js 를 아래와 같이 바꿔보자.

  • app.js
1
2
3
4
5
6
7
8
9
10
11
12
import axios from "axios";

document.addEventListener("DOMContentLoaded", async () => {
  const res = await axios.get("/api/users");
  console.log(res);

  document.body.innerHTML = (res.data || [])
    .map(user => {
      return `<div>${user.id}: ${user.name}</div>`;
    })
    .join("");
});

기존에는 data에 데이터를 관리했는데 이제는 ajax 호출 후 응답된 데이터를 반환하도록 변경했다. 화면을 확인해 보면 웹펙에서 설정한 api 응답이 화면에 나오는걸 확인할 수 있다.

스크린샷 2022-03-26 오후 9 02 17

목업 API 2: connect-api-mocker

목업 api 작업이 많을때는 connect-api-mocker 라이브러리의 도움을 받자. 특정 목업 폴더를 만들어 api 응답을 담은 파일을 저장한 뒤, 이 폴더를 api로 제공해주는 기능을 한다.

먼저 이 패키지를 설치하고,

1
npm i -D connect-api-mocker

mocks/api/keywords/GET.json 경로에 API 응답 파일을 만든다.

스크린샷 2022-03-26 오후 9 04 07

GET 메소드를 사용하기때문에 GET.json으로 파일을 만들었다.(물론 POST, PUT, DELETE 도 지원)

  • GET.json
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[
    {
      "id": 1,
      "name": "Alice"
    },
    {
      "id": 2,
      "name": "Bek"
    },
    {
      "id": 3,
      "name": "Chris"
    },
    {
        "id": 4,
        "name": "Daniel"
    }
]

기존에 설정한 목업 응답 컨트롤러를 제거하고 connect-api-mocker로 미들웨어를 대신한다.

  • webpack.config.js
1
2
3
4
5
6
7
8
9
const apiMocker = require("connect-api-mocker")

module.exports = {
  devServer: {
    before: (app) => {
      app.use(apiMocker("/api", "mocks/api"))
    },
  },
}

익스프레스 객체인 app은 get() 메소드 뿐만 아니라 미들웨어 추가를 위한 범용 메소드 use()를 제공하는데, 이를 이용해 목업 미들웨어를 추가했다.

첫번째 인자설정할 라우팅 경로인데 /api로 들어온 요청에 대해 처리하겠다는 의미다.

두번째 인자응답으로 제공할 목업 파일 경로인데 방금 만든 mocks/api 경로를 전달했다.

목업 API 갯수가 많다면 직접 컨트롤러를 작성하는 것 보다 목업 파일로 관리하는 것을 추천한다.

실제 API 연동: devServer.proxy

이번에는 api 서버를 로컬환경에서 띄운 다음 목업이 아닌 이 서버에 직접 api 요청을 해보자. 로컬호스트 8081 포트에 아래와 같이 서버가 구성되었다고 가정하겠다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ curl localhost:8081/api/users
[
    {
      "id": 1,
      "name": "Alice"
    },
    {
      "id": 2,
      "name": "Bek"
    },
    {
      "id": 3,
      "name": "Chris"
    },
    {
        "id": 4,
        "name": "Daniel"
    }
]

ajax 요청 부분의 코드를 변경한다.

  • src/app.js
1
2
3
4
5
6
7
8
9
const model = {
  async get() {
    // const result = await axios.get('/api/users');

    // 직접 api 서버로 요청한다.
    const { data } = await axios.get("http://localhost:8081/api/users")
    return data
  },
}

웹팩 개발서버를 띄우고 화면을 확인해 보자. 잘 나오는가? 브라우져 개발자 도구에 보면 다음과 같은 오류 메세지가 출력된다.

cors 출처: https://jeonghwan-kim.github.io/series/2020/01/02/frontend-dev-env-webpack-intermediate.html

localhost:8080에서 localhost:8081 로 ajax 호출을 하지 못하는데 이유는 CORS 정책 때문이라는 메세지다. 요청하는 리소스에 "Access-Control-Allow-Origin" 헤더가 없다는 말도 한다.

CORS(Cross Origin Resource Shaing) 브라우져와 서버간의 보안상의 정책인데 브라우저가 최초로 접속한 서버에서만 ajax 요청을 할 수 있다는 내용이다. 방금같은 경우는 localhost로 같은 도메인이지만 포트번호가 8080, 8081로 달라서 다른 서버로 인식하는 것이다.

해결하는 방법은 두 가지(서버측에서 해결, 프론트측에서 해결)이다.

서버측에서 해결하는 방법은 다음과 같다. 해당 api 응답 헤더에 "Access-Control-Allow-Origiin: *" 헤더를 추가한 뒤 응답하면, 브라우져에서 응답 데이터를 받을 수 있다.

  • server/index.js (노드 서버 코드)
1
2
3
4
app.get("/api/users", (req, res) => {
  res.header("Access-Control-Allow-Origin", "*") // 헤더를 추가한다
  res.json(keywords)
})

한편 프론트엔드 측 해결방법을 보자. 서버 응답 헤더를 추가할 필요없이 웹팩 개발 서버에서 api 서버로 프록싱하는 것이다. 웹팩 개발 서버는 proxy 속성으로 이를 지원한다.

  • webpack.config.js
1
2
3
4
5
6
7
module.exports = {
  devServer: {
    proxy: {
      "/api": "http://localhost:8081", // 프록시
    },
  },
}

개발서버에 들어온 모든 http 요청중 /api로 시작되는것은 http://localhost:8081로 요청하는 설정이다. api 호출코드를 다시 복구한 뒤,

  • src/app.js
1
2
3
4
5
6
7
8
const model = {
  async get() {
    // const { data } = await axios.get('http://localhost:8081/api/users');

    const { data } = await axios.get("/api/users")
    return data
  },
}

확인해보면 정상 동작하게 될 것이다.

Note: 강의에서는 실습을 진행하지 않는다.

출처

This post is licensed under CC BY 4.0 by the author.

[프론트엔드 개발환경의 이해와 실습] eslint 자동화하는 방법

[프론트엔드 개발환경의 이해와 실습] 웹팩 개발 서버