Vercel Serverless 예제 | Jsonplaceholder

고광필·2022년 7월 18일
4

Front

목록 보기
22/33

예전에 노션 클론 코딩을 하고 회고 글을 작성했었습니다
미뤄놨던 배포와 버그 수정, 리팩토링을 진행할 예정입니다
그 중 배포할 때 api 요청 url과 관련 api key에 대해서 숨겨야 하는 사항이 있어서 vercel의 serverless function을 먼저 도입하게 되었습니다


이대로 배포하면 안되니깐...

이 글은 vercel serverless를 사용하는 예제 글입니다

Vercel Serverless

Vercel Serverless Funtion은 사용자 인증, 양식 제출, DB query 등의 명령을 추가 인프라 없이 vercel에서 자체적으로 처리하도록 합니다

이 때 네트워크 요청이 감춰집니다

api url과 key를 숨겨야 하니 적용해야 합니다

적용 방법

Vercel Serverless Funtion에 있는 적용 방법을 간략하게 번역한 내용입니다

  1. 프로젝트의 루트 디렉토리에 api 폴더를 만들고, 이 폴더 안에서 서버리스 함수를 작성합니다
    결과적으로 api 폴더가 /api url로 매핑됩니다

  2. serverless 함수에서 환경 변수를 설정할 수 있습니다
    .env 파일을 이용합니다

  3. url에 입력되는 값을 동적으로 받고 싶다면 파일명을 중괄호로 감싸줍니다
    ex) [name].js

Jsonplaceholder로 알아보는 예제

기본 코드

npx create-react-app folder-name으로 리액트 프로젝트를 하나 만듭니다

//App.js
import './App.css';
import { useEffect, useState } from 'react';

function App() {
  const [data, setData] = useState([]);

  useEffect(() => {
    fetch('https://jsonplaceholder.typicode.com/todos')
      .then((response) => response.json())
      .then((result) => setData(result));
  }, []);

  useEffect(() => {
    console.log(data);
  }, [data]);

  return (
    <ol>
      {data.map(({ id, title }) => (
        <li key={id}>{title}</li>
      ))}
    </ol>
  );
}

export default App;

App.js를 위 코드처럼 작성하고 npm start 명령어를 입력합니다

당연하게도 jsonplaceholder로 요청을 보낸 기록이 남습니다

이제 serverless 함수를 도입하겠습니다

serverless 도입 코드

// /api/index.js
import fetch from 'node-fetch';

export default async function handler(request, response) {
  const res = await fetch('https://jsonplaceholder.typicode.com/todos');
  const data = await res.json();
  return response.status(200).json({ data });
}

루트 디렉토리에 api폴더를 만들고, api 폴더에 index.js를 위 코드처럼 만듭니다
이 때 node-fetch는 2버전으로 설치합니다
그리고 레포지토리를 vercel에서 배포합니다

배포 링크에 /api을 붙이면 /api/index.js를 통해 얻은 data를 볼 수 있습니다
jsonplaceholder로 요청을 보냈다는 기록은 Network 탭에서 찾을 수 없습니다

하지만 레포지토리를 들어와서 코드를 보면 요청 보낸 곳을 알 수 있기 때문에 환경 변수를 설정하겠습니다

process.env 도입 코드

먼저 vercel settings - Environment Variables에서 위처럼 설정합니다

// /api/index.js
import fetch from 'node-fetch';

export default async function handler(request, response) {
  const res = await fetch(process.env.BASE_URL);
  const data = await res.json();
  return response.status(200).json({ data });
}

api 폴더의 index.js를 위와 같이 수정합니다
jsonplaceholder로 요청보내던 내용을 환경변수의 BASE_URL로 요청을 보내도록 수정했습니다

// App.js
import './App.css';
import { useEffect, useState } from 'react';

function App() {
  const [loaded, setLoaded] = useState(false);
  const [data, setData] = useState([]);

  useEffect(() => {
    fetch('/api')
      .then((response) => response.json())
      .then((json) => {
        setData(json.data);
        setLoaded(true);
      });
  }, []);

  useEffect(() => {
    console.log(data);
  }, [data]);

  return loaded ? (
    <ol>
      {data.map(({ id, title }) => (
        <li key={id}>{title}</li>
      ))}
    </ol>
  ) : (
    '데이터 fetch 미완료'
  );
}

export default App;

App.js를 위 코드처럼 수정합니다
/api url로 요청을 보내고, 받은 데이터의 .data를 사용하도록 했습니다

동적 값 fetch serverless

// /api/[page].js
import fetch from 'node-fetch';

export default async function handler(request, response) {
  const { page } = request.query;
  const res = await fetch(`${process.env.BASE_URL}/${page}`);
  const data = await res.json();
  return response.status(200).json({ data });
}

api 폴더 안에 index.js가 이미 있는 상황에서
[page].js를 위 코드처럼 만들어줍니다

/api/1
/api/2
같은 url로 접속하면 그 값을 request.query에서 page라는 이름으로 데이터를 받게 됩니다
그 page에 해당하는 jsonplaceholder 요청 결과를 반환하는 serverless 함수가 만들어졌습니다

물론 network에는 jsonplaceholder를 찾아볼 수 없습니다

깃허브와 배포 링크

github 링크에서 코드를 볼 수 있고
vercel 배포 링크에서 위 예제를 테스트할 수 있습니다

메인은 새로고침 시 /api로 요청을 보내고 렌더링합니다
/api는 process.env.BASE_URL로 정의된 jsonplaceholder 전체 값을 가져옵니다
/api/1은 /api와 동일하지만 해당 값만을 가져옵니다

노션 클론코딩에도 serverless 빨리 도입해서 리팩토링해야징~

참고

vercel 공식 사이트 - serverless function

profile
이해하는 개발자를 희망하는 고광필입니다.

0개의 댓글