ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • API 서버 연동 - 웹팩 심화편 | 김정환
    Front-end/개발환경 2020. 6. 16. 19:11
    반응형

    2. API 연동

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

     

    2-1. 목업 API : devServer.before

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

     

    아래 코드를 보자.

    webpack.config.js : 

    module.exports = {
      devServer: {
        before: (app, server, compiler) => {
          app.get('/api/keywords', (req, res) => {
            res.json([
              { keyword: '이탈리아' },
              { keyword: '세프의요리' }, 
              { keyword: '제철' }, 
              { keyword: '홈파티'}
            ])
          })
        }
      }
    }

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

     

    웹팩 개발 서버는 GET /api/keywords 요청시 4개의 엔트리를 담은 배열을 반환할 것이다.

     

    서버를 다시 구동하고 

    $ npm start

    * ctrl+c 입력하면 웹팩 개발 서버를 종료한다.

     

    curl로 http 요청을 보내보자.

    $ curl localhost:8080/api/keywords

     

    [{"keyword":"이탈리아"},{"keyword":"세프의요리"},{"keyword":"제철"},{"keyword":"홈파티"}]

     

    이런 기능이 왜 필요할까? 개발 초기 서버 api가 만들어지기 전, 서버 api 응답을 프론트엔드에서 추가할 때 사용할 수 있다. 익스프레스 사전 지식이 있다면 여기에 다양한 서버 응답을 구현할 수 있다.

     

    프론트 코드를 수정해서 방금 만든 엔드폰인트를 호출하는 코드로 변경해 보자. ajax 라이브러리인 axios를 설치한다.

    $ npm i axios

     

    프론트엔드의 app.js 코드를 다음과 같이 수정한다.

    src/app.js :

    import axios from 'axios'
    
    document.addEventListener("DOMContentLoaded", async () => {
      const res = await axios.get("/api/keywords")
      console.log(res);
      document.body.innerHTML = (res.data || []).map(keywords => {
        return `<div>${keywords.keyword}</div>`
      }).join("");
    });

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

     

    2-2. 목업 API : connect-api-mocker

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

     

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

    $ npm i connect-api-mocker

     

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

     

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

    GET.json :

    [
      { "keyword": "이탈리아" }, 
      { "keyword": "세프의요리" }, 
      { "keyword": "제철" }, 
      { "keyword": "홈파티 " }
    ]

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

    webpack.config.js :

    const apiMocker = require('connect-api-mocker')
    
    module.exports = {
      devServer: {
        before: (app) => {
          app.use(apiMocker('/api', 'mocks/api'))
        },
      }
    }

    익스프레스 객체인 app은 get() 메소드 뿐만 아니라 미들웨어 추가를 위한 범용 메소드 use()를 제공하는데, 이를 이용해 목업 미들웨어를 추가했다. 첫번째 인자는 설정할 라우팅 경로인데 /api로 들어온 요청에 대해 처리하겠다는 의미다. 두번째 인자는 응답으로 제공할 목업 파일 경로인데 방금 만든 mocks/api 경로를 전달했다.

     

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

    2-3. 실제 API 연동 : devServer.proxy

    이번에는 api 서버를 로컬환경에서 띄운 다음 목업이 아닌 이 서버에 직접 api 요청을 해보자.

     

    로컬호스트 8081 포트에 아래와 같이 서버가 구성되었다고 가정하겠다.

    $ curl localhost:8081/api/keywords

     

    [{"keyword":"이탈리아"},{"keyword":"세프의요리"},{"keyword":"제철"},{"keyword":"홈파티"}]

     

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

    src/app.js :

    document.addEventListener("DOMContentLoaded", async () => {
      // const result = await axios.get('/api/keywords');
    
      // 직접 api 서버로 요청한다.
      const result = await axios.get('http://localhost:8081/api/keywords');   
    });

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

    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 : 

    app.get('/api/keywords', (req, res) => {
      res.header("Access-Control-Allow-Origin", "*"); // 헤더를 추가한다 
      res.json(keywords)
    })

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

    webpack.config.js

    module.exports = {
      devServer: {
        proxy: {
          '/api': 'http://localhost:8081', // 프록시
        }
      }
    }
    

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

    src/app.js : 

    document.addEventListener("DOMContentLoaded", async () => {
      const result = await axios.get('/api/keywords');
    
      // 직접 api 서버로 요청한다.
      //const result = await axios.get('http://localhost:8081/api/keywords');   
    });

    확인해보면 정상 동작하는 것을 확인할 수 있다.

     


     

    TODO

    webpack.config.js에 api 서버 프록싱 설정을 추가하세요

    더보기

    # 프론트엔드 서버 : http://localhost:8080/

    # 백엔드 API 서버 : http://localhost:8081/

     

    webpack.config.js :

    module.exports = {
      devServer: {
        proxy: {
          "/api": "http://localhost:8081" // 프록시 설정
        }
      },
     }

    *웹팩 개발 서버 세팅 시 "/api" 요청으로 들어 온 것은 http://localhost:8081/로 요청하도록 프록시 설정한다. 

     

    반응형

    댓글

Luster Sun