7. dotenv를 사용해 프로젝트 배포하기(CRA 아님)

Circlewee·2022년 7월 29일
0

WYLSBingsu

목록 보기
8/8
post-thumbnail

0. 진행 상황

CRA를 사용하지 않고 직접 번들러와 트랜스 파일러를 설정해 주었다. 번들러로는 webpack, 트랜스 파일러로 babel, 언어로 TS를 사용할 것이었기 때문에 TS설정까지 추가하였다.
이제 우리가 만든 것을 배포해야하는 마무리 단계로 접어들었고, 배포를 위한 설정 과정과 마주했던 문제들을 이야기 해보려 한다.

1. API 수정

당연하게도 지금까지의 코드는 로컬에서 테스트하며 요청을 보내고 응답을 받아 처리하였기 때문에 localhost:포트 이렇게 시작했다. 배포하게 된다면 이를 수정하여 배포해야하기 때문에 CI/CD를 고려해 환경 변수를 사용하기로 하였다.

우선 CRA로 생성된 프로젝트는 .env, .env.production등의 파일을 만들어 작성만 해 주어도 환경 변수를 사용할 수 있다.
하지만 우리 프로젝트는 CRA 템플릿을 사용하지 않았기 때문에 몇 가지 설정해줘야할 것이 있었다.

1.1 dotenv 설정

npm install dotenv
or
yarn add dotenv

우선 .env파일을 사용하기 위한 dotenv를 설치해준다.

API_URL=http://localhost:포트
API_BUILD_URL=API서버가 배포된 URL

그리고 env파일은 간단하다. 환경변수로 사용하고 싶은 값을 변수에 담아주면 된다.
위에서도 말했지만 CRA를 사용하지 않았기 때문에 REACT_APP_...로 시작하지 않아도 된다.

1.2 package.json에 script 추가

  "scripts": {
    "start": "NODE_ENV=development webpack-dev-server --open --history-api-fallback",
    "build": "NODE_ENV=production webpack --mode production", // 배포용 빌드
    "build:dev": "NODE_ENV=development webpack --mode development" // 개발용 빌드
  },

배포용 빌드를 위한 스크립트를 추가해줘야한다. 추후에 process.env.NODE_ENV변수를 사용해야하기 때문이다.
우리의 프로젝트에서는 npm run build를 실행하면 배포용으로 빌드가 된다.

1.3 Webpack.config.js 설정 추가

다음으로할 것은 webpack 설정이다.

const dotenv = require('dotenv');
dotenv.config();

방금 전 설치했던 dotenv 모듈을 불러오고 config()메소드로 설정 파일을 불러온다.

  ...
  plugins: [
    new webpack.DefinePlugin({
      'process.env.API_URL': JSON.stringify( // 원하는 변수 명
        process.env.NODE_ENV === 'development'
          ? process.env.API_URL
          : process.env.API_BUILD_URL
      ),
    }),
  ],

그리고 DefinePlugin을 사용해야한다.

The DefinePlugin replaces variables in your code with other values or expressions at compile time. This can be useful for allowing different behavior between development builds and production builds.(Webpack 공식문서)

여기서 DefinePlugin이란 컴파일할 때 config파일에 선언된 변수를 우리가 원하는 값으로 바꿔 넣어주는 것이라고 생각하면 된다. 따라서 development와 production을 구분하여 build할 때 사용할 수 있는 것이다.

다시 우리의 코드를 보면 process.env.NODE_ENV를 이용해 조건문을 돌린다. 위에 스크립트에서 작성한 NODE_ENV변수에 담긴 값에 따라 배포용 URL과 로컬용 URL을 변수에 담는 것이다

1.4 HTTP 요청 코드 수정

이제 우리의 소스코드에 작성된 모든 localhost를 수정해야한다.

await axios.post<LoginResponse>('localhost:5000/user/login', data, { withCredentials: true });

기존 코드는 이렇게 작성되어있다. 여기 URI를 아래처럼 수정해주면 된다.

await axios.post<LoginResponse>(`${process.env.API_URL}/user/login`, data, { withCredentials: true })

그런데 여기서 process.env를 사용하면 오류가 생긴다.

'process' 이름을 찾을 수 없습니다. 노드의 형식 정의를 설치하려는 경우 'npm i --save-dev @types/node'를 시도한 다음, tsconfig의 형식 필드에 'node'를 추가하세요.

1.4.1 완벽히 해결했어!

npm i -D @types/node
or
yarn add @types/node -D
  1. @types/node 설치
// tsconfig.json
    "types": ["node"],
  1. tsconfig.json에 types추가


위 과정을 거치면 process의 type을 인식한다.
이 밖에도 여러 공개하기 민감한 정보들을 .env파일에 설정한 뒤 webpack.config.js에서 전역 변수로 추가해 사용할 수 있다.

성공!

❗ 다만 우리의 앱 소스코드에 작성된 process.env를 포함한 전역 변수는 컴파일 단계에서 우리가 설정해준 값으로 전부 바뀌기 때문에 브라우저의 콘솔에서 직접 확인할 수는 없다.


2. vercel로 배포하기

마무리하기로 정한 기간까지 시간이 얼마 없었기에 프론트는 vercel로 배포하기로 했다.
Organization 레포지토리를 배포하려면 무료 요금제로는 불가능했기 때문에 fork하여 개인 레포로 추가한 후 배포하였다.
vercel로 배포하는 과정은 다른 좋은 글이 많기 때문에 따로 적지는 않겠다.

그런데 배포 후에 생각지 못한 여러 문제가 생겼다.

2.1 404 not found


단순히 라우팅되지 않은 URL로 접근하지 않아서 생기는 것이 아니다. vercel에 프로젝트를 배포할 때 FRAMEWORK PRESET을 선택하는 데 우리는 CRA로 만든게 아니라 Other를 골랐고 vercel에서 SPA로 인식하지 못해 새로고침 시 해당 오류가 화면에 출력되는 것이다.

이걸 해결하기 위해 vercel.json을 만들면 된다.

2.1.1 vercel.json

{
  "rewrites":  [
    {"source": "/(.*)", "destination": "/"}
  ]
}

2.2 쿠키가 정상적으로 추가되지 않음

우리 프로젝트에서는 로그인 요청이 정상적으로 처리되면 응답으로 토큰을 Set-cookie로 보내 쿠키가 자동으로 추가된다. 이 쿠키는 만료가 설정되어 있고 httpOnly 옵션이 적용되어 있다.

여기서 문제가 생기는 데 vercel로 배포하게 되면 https가 자동으로 적용된다.
그런데 CORS 정책에 의해 Secure cookie를 사용하게 되면 도메인이 일치하지 않을 시 쿠키 자체가 추가되지 않았던 것이다.

그래서 해결 방법을 물색하다가 서버를 AWS EC2로 배포하면서 https를 사용하기 위해 도메인을 구매했었는 데 vercel로 배포한 URL을 구매한 도메인의 서브 도메인으로 변경하기로 했다.

2.2.1 vercel의 domain 설정


vercel의 프로젝트 설정에 들어가면 domain을 추가할 수 있다.
(URL이 bingsuserver.link인 이유는 도메인을 구매할 때 server만 사용할 목적으로 네이밍을 해서 그렇다...😭)

예시 이미지 입니다.

상단 input에 subdomain으로 사용할 주소를 입력한 후 add하면 이런 화면이 나오는 데 여기서 CNAME, Nameserver 중 원하는 방법을 사용하면 된다.
우리 팀은 백엔드분이 CNAME을 사용해서 AWS에 관련 설정을 추가해 주셨고 이렇게 모든 배포 과정이 마무리 되었다.

쿠키야 반가워!😊!


3. 마무리

이번 프로젝트는 2차 스터디를 시작하기 전부터 너무 해보고 싶었던 주제였다.
제일 큰 이유 중 하나는 어떤 서비스를 구현할지 미리 생각하고 있었고 서비스를 배포했을 때 사용할 타겟 유저 층을 머릿 속으로 미리 생각하고 있었던 게 아닐까 싶다. 이것은 시작부터 배포까지 완벽하게 한번 해보고 싶다는 욕심과도 맞아 떨어졌다.

약 3주의 기간동안 수업도 들으면서 틈틈히 프로젝트를 하는 것이 쉽지는 않았던 것 같다.
개인 시간이 거의 없었고 자기 전에 침대에 누워 유튜브를 보는 것이 하루의 낙이었다.
그치만 새로운 기술 스텍을 사용해보고 프로젝트 설정부터 마무리까지 대부분의 것을 도움 받지 않고 알고 있던 지식과 구글링을 더해 완성해 냈다는 뿌듯함이 정말 최고였던 프로젝트다.

좋은 팀원분들을 만났고 서로 원하는 것을 주고 받으며 하나의 목표를 완성했다.
사실 이것만으로도 개발자의 꿈꿔왔던 것을 이뤘다. 그 순간 느낀 감정은 내가 개발자로써 계속 성장하는 원동력이 되지 않을까 싶다.
배포 후 실 사용자는 목표에 한참 못 미칠만큼 많지 않았지만 언제 어디서든 우리의 서비스를 접속할 수 있다는 사실만으로도 보람을 느낄 수 있었다.

좀 더 자세한 내용은 회고에서 다뤄보고자 한다.

profile
공부할 게 너무 많아요

0개의 댓글