본문 바로가기

Programming/Javascript

Netlify Serverless function 작성

반응형

보안을 위해 API Key가 노출되지 않도록 API 요청 부분을 서버리스 함수로 작성하도록 하겠습니다.

추가로 API Key는 환경변수로 등록하여 Github 등으로 올릴 때 노출되는 것을 막기위해 추가적으로 보안설정을 하겠습니다.

 

1.netlify-cli 설치

npm i -D netlify-cli

2.netlify.toml

# Netlify Dev
# https://cli.netlify.com/netlify-dev/#netlifytoml-dev-block

# 제품 모드
[build]
  command = "npm run build"
  functions = "functions" # Netlify 서버리스 함수가 작성된 디렉토리를 지정합니다.
  publish = "build" # 프로젝트 빌드 결과의 디렉토리를 지정합니다.

# 개발 모드
[dev]
  framework = "#custom" # 감지할 프로젝트 유형을 지정합니다. 앱 서버 및 `targetPort` 옵션을 실행하는 명령 옵션은 `#custom`입니다.
  command = "npm run dev" # 연결할 프로젝트의 개발 서버를 실행하는 명령(스크립트)을 지정합니다.
  targetPort = 8080 # 연결할 프로젝트 개발 서버의 포트를 지정합니다.
  port = 8888 # 출력할 Netlify 서버의 포트를 지정합니다.
  publish = "public" # 프로젝트의 정적 콘텐츠 디렉토리를 지정합니다.
  jwtRolePath = "app_metadata.authorization.roles" # JWT 기반 리디렉션에 대한 역할 값을 찾아야하는 객체 경로를 지정합니다.
  autoLaunch = true # Netlify 서버가 준비되면 자동으로 브라우저를 오픈할 것인지 지정합니다.


3. package.json

 "scripts": {
    "dev": "snowpack dev",
    "dev:netlify": "netlify dev",
    "build": "snowpack build"
  },

4. /functions/movie.js

Netlify에서 작동할 서버리스 함수입니다. Netlify에서는 /functions/movie.js에 함수를 작성하게 되면, 'http://localhost:8079/.netlify/functions/movie' 와 같이 요청할 수 있습니다. node.js 환경에서 작동하므로 require로 모듈을 가져와야합니다.

const axios = require('axios')
const { OMDB_API_KEY } = process.env

exports.handler = async function(event, context) {
  const params = JSON.parse(event.body)
  const { title, type, year, page, id } = params
  //const OMDB_API_KEY='abd6b67a'

  const url = id 
    ? `https://www.omdbapi.com/?apikey=${OMDB_API_KEY}&i=${id}&plot=full` 
    : `https://www.omdbapi.com/?apikey=${OMDB_API_KEY}&s=${title}&type=${type}&y=${year}&page=${page}`

  try{
    const res = await axios.get(url)
    console.log(res.data)
    if (res.data.Error) { //OMDB의 특수한 경우(정상반환되었으나 내용에 에러가 포함됨) 처리
      //reject(res.data.Error)
      return {
        statusCode: 400,
        body: res.data.Error
      }
    }
    //resolve(res)
    return {
      statusCode: 200,
      body: JSON.stringify(res.data)
    }
  } catch(error) {
    console.log(error.response.status)
    //reject(error.message)
    return {
      statusCode: error.response.status,
      body: error.message
    }
  }
}

 

5. 테스트용 app.svelte 소스

<script>
  import { fade } from 'svelte/transition'
  import Router,{ location } from 'svelte-spa-router'  
  import routes from '~/routes/index.js'
  import Header from '~/components/Header.svelte'  
  import Footer from '~/components/Footer.svelte'
  
  import axios from 'axios'

  async function test() {
    const res = await axios.get('/.netlify/functions/test')
    console.log(res)
  }
  test()
</script>

<Header />
{#key $location}
  <div in:fade>
    <Router 
      routes={routes} 
      restoreScrollState={true}/>
  </div>
{/key}
<Footer />

6. Netlify 환경변수에  OMDB_API_KEY 설정

경로: Netlify -> Site settings -> Build & deploy -> Environment -> Environment variables -> Edit Variables

 

7. 로컬서버에서도 테스트 가능하도록 환경변수 설정( .env 파일 생성)

OMDB_API_KEY=7035c60c

(주의) .gitignore에 추가하여 깃헙에 업로드되지 않도록 한다.

 

8. 추후 유지보수를 위한 설정 변경

1) package.json 시작 스크립트 변경

"scripts": {
    "dev:snowpack": "snowpack dev",
    "dev": "netlify dev",
    "build": "snowpack build"
  },

2) netlify.toml파일 변경

command를 바꿔주고, 시작 포트를 8079로 변경한다.

# 개발 모드
[dev]
  framework = "#custom" # 감지할 프로젝트 유형을 지정합니다. 앱 서버 및 `targetPort` 옵션을 실행하는 명령 옵션은 `#custom`입니다.
  command = "npm run dev:snowpack" # 연결할 프로젝트의 개발 서버를 실행하는 명령(스크립트)을 지정합니다.
  targetPort = 8079 # 연결할 프로젝트 개발 서버의 포트를 지정합니다.
  port = 8080 # 출력할 Netlify 서버의 포트를 지정합니다.
  publish = "public" # 프로젝트의 정적 콘텐츠 디렉토리를 지정합니다.
  jwtRolePath = "app_metadata.authorization.roles" # JWT 기반 리디렉션에 대한 역할 값을 찾아야하는 객체 경로를 지정합니다.
  autoLaunch = true # Netlify 서버가 준비되면 자동으로 브라우저를 오픈할 것인지 지정합니다.

3) snowpack.config.js 파일의 시작 포트 변경

module.exports = {
  mount: {
    public: '/',
    src: '/_dist_'
  },
  plugins: [
    '@snowpack/plugin-svelte',
    ['@snowpack/plugin-babel', {
      transformOptions: babelOptions()
    }],
    '@snowpack/plugin-dotenv',
    '@snowpack/plugin-optimize'
  ],
  alias: {
    '~': './src'
  },
  devOptions: {
    port: 8079
  }
}
반응형