# 주요 내용
1. netlify: command not found 해결방법
2. Client-Side 에서 API Key를 노출하지 않고, TMDB API와 통신하기 위한 redirect server 만들기(netlify를 통해 서버리스 만들기)
기업 과제 중 TMDB의 Open API를 통해서 영화 목록 리스트를 구현하고 있었고, API Key를 숨겨야하는 것이 구현 과제였다.
TMDB의 API는 key를 파라미터로 전달해주어야한다.
https://api.themoviedb.org/3/movie/76341?api_key= <<api_key>>
# 문제 (feat: .env 통해서 API Key 숨기는거 의미없다..)
나는 여태 .env 파일을 통해 API Key를 숨겼는데, 이건 진짜 숨겨지는 것이 아니였다.
.env는 깃헙에 내 key가 올라가는 것을 숨기는 정도의 역할만 하는 것이고,
실제로 네트워크 탭에 들어가면 요청 url에 그대로 내 Key가 노출되는 것이였다!!
# 해결 방법 탐색
프론트에서는 api 키를 숨길 수 없다고 한다.
클라이언트가 해당 서버로 바로 요청을 보내는 방식은 KEY를 숨길 수 없고,
KEY를 숨기기 위해서는 클라이언트가 아닌 곳에 KEY를 보관해야 한다고 한다.
대안은 서버를 하나 두는 것 인데,
API 키를 모르는 클라이언트가 추가된 서버(Netlify)에 요청을 보내고,
이어서 API 키를 알고 있는 나의 서버(Netlify)가 TMDB API서버에 요청을 보낸다.
이 방식으로 내 클라이언트의 요청을 받아줄 서버를 중간에 두면 KEY를 숨길 수 있다.
즉,
클라이언트 -> TMDB 다이렉트로 요청을 하는 것이 아닌,
클라이언트 -> Netlify(키 숨기는 중간 서버) ->TMDB 이런식으로 중간 서버를 만들어 API Key를 숨기면 된다!
# 또 다른 문제 직면..
먼저, netlify를 CLI 환경으로 깔아줘야 한다. 그래야 netlify 서버가 잘 구동되는지 확인할 수 있다.
터미널에 아래 명령어를 입력하자.
npm install netlify-cli -g
명령어를 치면 설치가 된다.
잘 되었는지 확인하기 위해 netlify 입력했다.
netlify
command not found 에러가 났다..ㅎ
https://medium.com/illumination/zsh-command-not-found-netlify-b9a217376937
위 블로그를 참고해서 아래 명령어를 입력했다. 아마 설치되는 경로를 지정해주는 것 같다.
npm config get prefix //입력
/Users/hyebin/.npm-global //요렇게 출력됨
export PATH=/Users/hyebin/.npm-global/bin:$PATH //입력
경로 설정하고 다시 설치하고, 설치되었는지 확인한다.
npm install netlify-cli -g
netlify
다시 netlify를 치니 아래처럼 드디어 netlify를 읽을 수 있게되었다!!!! ㅎㅎㅎㅎ
이후 아래 명령어를 통해 권한을 부여하여 CLI로 로그인한다.
ntl login
자세한 설명은 아래 공식문서를 통해 확인하자!
https://www.netlify.com/blog/intro-to-serverless-functions/
기본 셋팅은 끝났다..
이제 진짜 서버리스를 만들어보자!!
# 서버리스 or redirect server 만들기!
1. netlify.toml 파일을 가장 상위에 만들자.
netlify.toml 내에 아래 코드 복붙하쟝.
주석을 잘 읽어보고 사용하는게 좋을 것 같다!
# netlify.toml
[build]
command = "CI= npm run build"
functions = "netlify/functions/" # Netlify 서버리스 함수가 작성된 디렉토리를 지정합니다.
publish = "build" # 프로젝트 빌드 결과의 디렉토리를 지정합니다.
# 개발 모드
[dev]
framework = "#custom" # 감지할 프로젝트 유형을 지정합니다. 앱 서버 및 `targetPort` 옵션을 실행하는 명령 옵션은 `#custom`입니다.
command = "npm run dev" # 연결할 프로젝트의 개발 서버를 실행하는 명령(스크립트)을 지정합니다.
targetPort = 3000 # 연결할 프로젝트 개발 서버의 포트를 지정합니다. 리액트는 3000포트
port = 8888 # 출력할 Netlify 서버의 포트를 지정합니다.
publish = "public" # 프로젝트의 정적 콘텐츠 디렉토리를 지정합니다.
jwtRolePath = "app_metadata.authorization.roles" # JWT 기반 리디렉션에 대한 역할 값을 찾아야하는 객체 경로를 지정합니다.
autoLaunch = true # Netlify 서버가 준비되면 자동으로 브라우저를 오픈할 것인지 지정합니다.
[functions]
node_bundler = "esbuild"
[[redirects]]
from = "/*"
to = "/netlify/functions/movie"
status = 200
2. package.json 파일을 수정하자
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject",
"dev": "npm run dev",
"dev:netlify": "netlify dev" // netlify를 개발모드로 실행하기 위한 명령어이다. 추가하자!
},
3. netlify/functions/movie.js 파일을 만들자.
일단 나는 axios 라이브러리를 썻고, 인코딩 문제를 해결하기 위해 urlencode 라이브러리를 설치했다.
2개 모두 설치 하자.
아래는 TMDB에서 제공하는 api 명세인다. 이것을 잘 보고 코드를 짜자.
https://api.themoviedb.org/3/discover/movie?language=ko&api_key=c4c2f261766299bd7a173d106c6f7adb&page=5
아래는 netlify/functions/movie.js 파일 내용이다.
// netlify/functions/movie.js
const axios = require("axios");
const urlencode = require("urlencode");
exports.handler = async (event) => {
console.log(event); // 브라우저에 찍히지 않고, 터미널에 내 콘솔로그가 찍힌다!
const { queryStringParameters } = event; // event 객체를 통해 queryStringParameters을 받아올 수 있다.
const parameters = Object.entries(queryStringParameters) // 파라미터를 map으로 돌면서 key:value 이런식으로 저장
.map(([key, value]) => `${key}=${urlencode.encode(value)}`) // *** 인코딩 문제해결
.join("&")
.concat(`&api_key=${process.env.REACT_APP_API_KEY}`); // 명세에 적힌대로 api_key=${실제키 입력하기!}
const url = `https://api.themoviedb.org/3/discover/movie?${parameters}`;
const response = await axios.get(url);
const { headers } = response;
headers["Access-Control-Allow-Origin"] = process.env.REACT_APP_HOST_SERVER; // *** 동일출처정책 문제해결
return {
statusCode: 200,
headers,
body: JSON.stringify({
data: response.data.results,
}),
};
};
4. 기존 api 파일 url을 우리가 만든 파일 경로로 수정해주자!
// src/api/movieAPI.js
import axios, { AxiosError } from "axios";
import { axiosInstance } from "./axiosInstance";
// 박스오피스 영화 조회 함수
const test = async () => {
try {
const response = await axios.get("/.netlify/functions/movie", { // 우리가 만든 서버로 요청이 보내진다.
params: {
language: "ko",
sort_by: "popularity.desc",
include_adult: "true",
page: pageNum,
// 여기다가 키 넣으시면 안돼요!
},
});
console.log(response.data.data);
return response.data.data;
} catch (error) {
if (error instanceof AxiosError) {
return error.response;
}
}
};
5. 마지막
아래 명령어를 입력하자.
ntl init
ntl dev
그러면 .netlify 폴더 하위에 functions-serve가 생긴다.
그리고 add, commit, push 로 배포하면 끄읕!
# 참고문서
넷틀리파이 공식 문서 Create functions => https://docs.netlify.com/functions/create/?fn-language=ts
넷틀리파이 공식 문서 Intro to Serverless Functions => https://www.netlify.com/blog/intro-to-serverless-functions/
서버리스 구현 깃헙 => https://github.com/bigsaigon333/hide-api-key-with-serverless-functions
'React' 카테고리의 다른 글
[React] onKeyDown 이벤트 중복으로 2번 실행되는 문제 및 해결방법 (4) | 2023.05.10 |
---|---|
캐시 스토리지(cache storage) 설정, 에러 해결(clone is not a function), 디바운싱을 활용한 검색 기능 (0) | 2023.05.08 |