혼자서 작업 하는 개인 프로젝트였기 때문에, 단일 코드 베이스에서 작업 하는 것이 효율적일 수도 있겠다는 생각을 하기도 하였습니다. 하지만 어느 정도의 백엔드 플로우를 프론트 개발자가 이해 할 줄 알아야 하고 유지보수와 성능의 개선을 위해 코드를 분할을 하기로 결정하게 되었습니다.
백엔드 코드가 전반적으로 어떻게 구성되고 진행하였는지에 대한 과정에 대해 작성 해보겠습니다.
- 백엔드 서버를 구축해본 경험이 많지 않았습니다. 또 코드를 분할해서 작성 해본 적이 없었기 때문에, 가장 익숙한
node.js환경에서, 이전에 사용 해본 적이 있는express를 사용해서 서버를 만들어 보기로 하였습니다.

express 를 사용하여 서버를 만드는 간단한 예시 코드 입니다. 보통 node.js 와 같은 commonJS 방식을 사용해서 작성하는 법이 대표적이지만, 작성법이 익숙하지 않거나, ES6 문법을 사용하는 경우 Babel 과 같은 JavaScript 컴파일러를 설치하여 사용하시는 것이 작성하기에 유리 합니다. 제 경우엔 commonJS 보다 ES6 문법을 사용해서 작성하는 것을 선호 하였기 때문에 위와 같은 server.js 를 만들었습니다.
- pokeapi 에서는 정말 많은 정보가 제공 되지만 존재하지 않는 것들이 있었습니다. 도감 사이트라는 이름에 걸맞게 최대한 다양한 정보를 사용자가 확인할 수 있도록 만들고 싶었습니다. 그 중 하나가 바로 인물 정보였습니다.
mongoDB 를 사용하여 DB를 만들기로 하였습니다. JSON 의 구조의 장점을 가져오면서 빠른 속도로 데이터를 가져올 수 있는 BSON 구조로 저장되는 mongoDB 가 pokeapi 와 동일한 익숙한 형태의 정보를 저장 할 수 있다고 생각하였습니다. 
mongoose 라이브러리를 사용하여 DB 와 연결 해준 뒤 제가 원하는 정보의 Schema 형태를 생성 해주었습니다.
인물 정보를 만들어 주는 과정에서 약간의 문제가 있었습니다. 초기에 나무위키에서 정보들을 얻어 DB를 작성 해주었는데, 이미지나 BGM 과 같은 정보들의 주소가 바뀐다는 점이었습니다.
검색 해보니 나무 위키는 정보 보안을 위해 주기적으로 이미지 주소를 바꾼다는 사실을 알 수 있었습니다. 해서 약 2주간 정상적으로 가져와 지던 이미지가 모두 깨지는 현상이 생겼습니다.

aws-s3 버킷을 생성한 뒤 퍼블릭 액세스가 가능하도록 설정 해주고, DB에 버킷 주소 값을 넣는 방식으로 해결 해주었습니다.
- 게시판 기능을 이용하기 위해서 로그인, 회원 가입 등의 절차가 필요했고, UserSchema 를 생성 해주었습니다.
mongose.model을 사용하여 User model 을 생성 합니다.
bcrpyt 를 사용하여 해싱 된 값이 저장 됩니다.회원가입과 동일하게 findOne 훅을 사용하여 존재하는 사용자인지 검증 합니다. user collection 에 저장된 password 는 해싱 된 값이 들어가 있기 때문에, bcrpyt.compare 를 사용하여 확인 합니다.
로그인 과정에서 조건이 만족하였을 때 세션을 발급, 저장 하기 위해
express-session , connect-Mongo 라이브러리를 사용하였습니다.

session 이 DB에 저장 될 수 있도록 store 옵션에서 를 connect-Mongo 를 사용, cookie 옵션도 적절한 값을 작성 해주었습니다. DB에서 sessions 라는 이름의 컬렉션이 생성 되고, 값이 저장 되는 것을 확인 할 수 있습니다.

- 사용자가 직접 CRUD를 할 수 있는 환경을 만들기 위해 게시판 기능을 구현 하였습니다.

puppeeteer 를 사용하여 웹 스크래핑을 하기로 결정 하였습니다.프로젝트가 제 생각보다 장기화 된 가장 큰 이유는 바로 배포였습니다. 프론트 같은 경우 vercel 을 이용하여 배포 하였는데, 쉽고 간편해서 vercel.json 같은 파일 외에 딱히 더 설정 해줄게 없었습니다.
문제는 백엔드 배포 였는데, 배포 방식부터 코드 구조까지 여러가지를 수정하면서, 제가 예상한 기간보다 시간을 더 잡아먹게 되었습니다. 배포하면서 어떤 문제를 겪었는지 어떻게 해결 하였는지 에 대해서 작성해보도록 하겠습니다.
Paas(Platform as a Service)서비스 입니다.이전에 배포를 진행 하였던 경험이 있습니다. 코딩을 시작 한지 얼마 되지 않았을 무렵 노마드 코더 사이트에서 [풀스택] 유튜브 클론코딩 이라는 강의의 챌린지를 진행하고 있었습니다. 약 6 주 정도 진행 되는 챌린지 였는데, 약 1주가 남은 시점에 배포라는 마지막 과정이 남아있었습니다.
챌린지 완료 후 우수작을 선정하는 과정이 있었는데, 당시 저는 이 우수작이라는 타이틀에 약간 매몰되어 있는 상태 였습니다. 강의 내용 외의 여러가지 기능을 구현하려고 노력하였고, 종료가 약 2일 정도 남은 시점에서 배포를 진행 하였습니다.
배포를 너무 쉽게 생각한 것이 원인이었습니다. 당시 저는 배포 그냥 다 완성 된 코드 어디에 올리기만 하면 되는 거 아닌가? 라는 생각을 하던 초보였고, Heroku 를 통한 배포 과정에서 완전히 멘탈이 나가버렸습니다. 로컬에서 정상적으로 작동 되던 코드들이 배포 과정에서 여러가지 오류가 나면서, 남은 기간 동안 버그를 고치는데, 온전히 시간을 투자 하였으나 결국 해결하지 못한 채로, 미완성 된 프로젝트 배포 Url 을 제출 할 수 밖에 없었습니다.
puppeeteer 를 사용한 웹 스크래핑 데이터를 가져올 수가 없었습니다. 확인해보니 puppeeteer 를 실행 시키기 위해 필요한 종속성이 Elastic-Beanstalk 배포 과정에서 자동적으로 설치 되지 않기 때문에, 생기는 문제였습니다. 로컬에서 실행 시 크롬에서 실행 되지만, EB 인스턴스에는 chromium 종속성이 설치 되어 있지 않기 때문 입니다.EB 인스턴스 환경에서 배포 시 종속성을 설치하는 방법 입니다.
배포 시에 종속성이 설치 될 수 있도록 하려면 .ebextentions 폴더와 .config 확장자를 가진 파일을 생성 해주어야 합니다.
로그를 확인 해보니 오류 내용이 조금씩 달라지기는 하지만, 해결 되지는 않았습니다.
이후에도 package.lock 파일을 포함 또는 제외 한 후 배포 하거나, puppeeteer.launch() 의 Headless 설정을 변경 하는 등, 검색하여 나온 방법들을 적용 해보았으나 해결될듯 해결되지 않는 상태로 인스턴스를 [ 배포 - 삭제 - 배포 ] 하는 삽질을 반복하다 보니, 내가 지금 뭘 하고 있는 건가? 싶었습니다.
aws-ec2 를 사용하여 처음부터 다시 배포를 하기로 하였고 아래와 같은 방식으로 해결 하였습니다.
aws-ec2배포 과정
aws-ec2 에서 ubuntu 환경의 인스턴스를 생성, 보안 그룹(사용자 지정 TCP PORT)을 설정한 뒤 SSH 키를 사용하여 인스턴스에 접속할 수 있도록 하였습니다.
git-hub 백엔드 코드를 클론한 뒤 필요한 의존성을 설치 하였습니다.
route53 에서 호스팅 영역을 생성 해준 뒤 https 를 사용하기 위해 가비아 에서 구매한 도메인을 등록, 네임서버를 변경 해주었습니다.
amazon-certificate-manager 에서 퍼블릭 인증서를 발급 받은 뒤(DNS 검증), CNAME 레코드를 생성 하였습니다.
aws-ec2 인바운드 규칙을 재설정 (http, https), 로드 밸런싱 대상 그룹을 생성, 로드 밸런서를 생성 해주었습니다.
route53 에서 A 레코드를 생성, 로드 밸런서 리스너 규칙을 수정 하였습니다.
pm2 를 이용, 무중단 서비스를 실행 하였습니다.
정상 배포 된 것을 확인 할 수 있습니다. PokéHub_BE
느낀점
위 방식을 진행하면서 어려운 부분도 많았습니다. 처음 사용해보는 ubuntu 환경과 https 를 사용하기 위하여 nginx 의 .conf 설정 변경 방식에서 애를 먹기도 하였습니다.(ACM SSL 인증서를 발급 받아서 해결 하였습니다.)
또 배포가 모두 완료 된 이후에도 cookie가 제대로 발급되지 않는 문제가 있었습니다. 클라이언트와 서버의 도메인이 다르기 때문에 생긴 이슈 였습니다.
FE | https://pokehub-encyclopedia.vercel.app
BE | https://pokehub-encyclopedia.site
기존에는 로컬 환경에서 작업하다보니 포트 번호가 다를 뿐, 도메인은 동일하여 정상적으로 작동 하였지만, 배포 환경에서는 도메인이 다를 시 쿠키 발급시 제약이 있기 때문에 설정을 다르게 해주어야 했습니다.
검색 후 cors origin 에 클라이언트의 도메인 주소를 넣고, cookie secure (https 통신에서는 true 로 변경) , sameSite , Proxy 설정을 추가 하여 해결 하였습니다.
마무리
사실 Elastic-Beanstalk 배포 부분에서 스크래핑 부분을 제외하면 다른 것들은 의도한 대로 작동 하였기 때문에, puppeeteer 를 사용한 웹 스크래핑 부분을 삭제할까? 라는 생각도 많이 하였습니다.
하지만 이전 프로젝트에서도 초기 기획 하였던 부분을 시간이 부족하다는 이유로 얼렁뚱땅 넘겼던 적이 있었는데, 다시 그런 짓을 반복하고 싶지는 않았기 때문에 혼자 합리화 하지 않고 끝까지 할 수 있었던 것 같습니다.
익숙하지 않은 탓에 예상 시간보다 더 걸리긴 하였으나, 개발이라는 것은 역시 계속 찾으면 답이 나온다는 것을 알 수 있었습니다. 저만의 방식으로 프로젝트를 처음부터 끝까지 작업을 완료한 것은 꽤나 성취감을 느낄 수 있는 일이었습니다.