SPA를 ‘SNS공유하기’ 가능하게 해보자.

Donghoon Nam
원티드랩 기술 블로그
8 min readOct 19, 2021

안녕하세요. 프론트엔드 개발 팀 남동훈 입니다.

배경

현재 크레딧잡 사이트가 SPA로 구현이 되어 있는 상황이다 보니 SNS공유등이 되지 않는 상황입니다.
앞으로 크레딧잡을 더 활성화 시키기 위해서는 SNS공유가 되도록 해야하는 상황이라고 판단되어 SNS공유가 되도록 하는 것을 목표로 진행하게 되었습니다.

AS-IS
아래와 같이 페이스 북 공유시 meta태그가 모든 페이지에서 동일하게 출력이 되고 있습니다.

TO-BE
페이지의 정보에 따라 meta태그가 변경되도록 작업을 진행하였습니다.

또한, 기존 레거시/여건상(빡빡한 일정 등) 아래 두 가지 환경 중 하나를 선택해야하거나 하는 경우를 고려해 두 가지 구현 방식을 공유하려고 합니다.

  • Cloudfront + Lambda@Edge + S3
  • Express + middleware

SNS공유하기를 위해서 전체 코드/구조를 바꾸는 개편작업을 진행한다고 했을때 이해해줄 수 있는 곳이 있을까란 생각을 하면서 같은 고민을 하실 분들을 위해 두 가지 상황을 전제, 그리고 써드파티 형태로 언제든 제거 가능하도록 고려하여 위의 프로토타입을 진행 및 공유하게 되었습니다.

SPA의 이슈

SPA란? (SPA에 대한 설명이 주가 아니기 때문에 링크를 통해 참고 부탁드립니다.)

SPA로 구축되어 있는 사이트는 봇들(페이스북, 카카오 등)이 해당 사이트를 crawling 할 수 없는 이슈가 있습니다. (구글은 제외)

이 이슈를 해결하는 방법은 아래와 같은 내용들을 고려해볼 수 있을거 같습니다.

1.Server-Side Redering이 가능한 Next.js를 도입, 리팩토링 진행

  • 위의 내용은 기존 구조, 코드를 전체적으로 변경 및 기존 기능을 전부 테스트해야하다 보니 배제하였습니다.

2. request요청을 파악하여 bot여부 판단하에 선택적인 SPA/SSR렌더링

  • 현재 구조, 코드를 변경하지 않고 어렵지 않게 구현할 수 있다.

위와 같은 이유 때문에 2번으로 진행하는 것으로 결정하고 구현 방법에 대해서 설명드리고자 합니다.

SPA 운영 방법에 따른 SSR 구현 방식

SPA로 배포 및 운영하는 방법은 아래와 같은 두 가지 방식으로 운영을 할 수 있습니다.

  1. AWS Cloudfront(CDN) + AWS S3
  2. React-Cli를 사용하여 EC2에서 SPA구현
  • 1번의 AWS Cloudfront(CDN) + AWS S3조합은 다음과 같은 형태를 가지게 됩니다.

react-cli에서 build를 하여 생성된 static 파일들을 s3에 저장하여 cloudfront를 통해 delivery하는 매우 간단한 형태 입니다.

위의 구조에서 Lambd@Edge를 추가해서 특정페이지의 SSR구현을 해보겠습니다.

Lambda@Edge 함수를 트리거하는 데 사용할 수 있는 CloudFront 이벤트는 다음과 같습니다.

  • Viewer request : CloudFront가 클라이언트로부터 요청을 수신하면 실행
  • Origin request : CloudFront가 오리진 서버로 요청을 전달할 경우에만 실행
  • Origin response : CloudFront가 오리진 서버로부터 응답을 수신한 후 실행되어 응답의 객체를 캐싱
  • Viewer response : 요청된 파일을 클라이언트에게 반환하기 전에 함수가 실행

위의 4가지 이벤트 중 Viewer request, Origin response 두 개의 이벤트에 Lambda@Edge 함수를 사용하여 구현하려고 합니다.

  • Viewer request : 클라이언트의 userAgent를 bot인지 아닌지 여부를 판단
  • Origin response : bot이면 해당 내용이 포함된 meta를 출력 아니면 static파일로 출력

위의 로직을 구현할 Lambda@Edge를 생성, 구현해보기 전에 제약사항을 먼저 알아보려고 합니다.

  • Memory와 Timeout 제한 : viewer-requestviewer-response는 128MB Memory와 5초 timeout 제한이 있으며 origin-requestorigin-response는 3008MB Memory와 30초 시간 제한이 존재합니다.

Lambda@Edge의 생성 및 cf연동까지 하면 너무 길어져서 다른 분의 블로그 글을 참고 해주시면 좋을거 같습니다.

viewer-request.js

  1. 위의 스크립트로 Lambda@Edge를 생성합니다.
  2. 위의 스크립트를 CloudFront A/B템플릿 테스트를 수정하여 테스트 합니다.
  1. CloudFront의 Viewer request에 연동한다.
  2. CloudFront의 Edit Behavior에서 허용할 경로(path)를 선택한 후 ‘Allow Header’에 ‘is-bot’을 허용시킵니다.

origin-response.js

위의 경로와 봇여부 판단이 되면 data를 ajax혹은 DB조회를 하여 html과 파싱시켜 callback으로 넘겨준다.

CloudFront와 S3를 사용할 수 있는 곳은 위의 방식으로 해결하면 될거 같습니다.

React-Cli에서 build는 bundle 파일들을 아래와 같이 생성해 줄 수 있습니다

Deployment | Create React App

  • serve패키지를 이용하여 static server 구축
  • express패키지를 이용하여 static server 구축

여기서는 두번째인 express를 가지고 SSR을 구현해 보려고 합니다.

우선 위의 Lambda@Edge를 통해 구현한 방식을 이용하여 진행해보려고 합니다.

그러려면 간단하게 express서버의 통신 과정부터 보려고 합니다.

CloudFront의 EventTrigger와 비슷한 형태이니 참고해서 봐주시면 좋을거 같습니다.

위의 그림은 client->node->express->middleware로 client의 request와 response응답 과정을 보여줍니다.

저희가 주목하고 구현해야하는 부분은 middleware이고 위의 그림을 기준으로 간단하게 로직을 설명하려고 합니다.

express에서 middleware에 request, response를 전달하는 과정이 있는데 request의 useragent에서 bot을 판단하는 로직을 구현합니다.

middlewareCheckBot.js

req.botInfo에 저장된 내용을 이제 아래와 같이 가져다 쓰면 됩니다.

index.js

Test

위와 같이 작성을 했으면 서버를 시작하고 SSR이 잘 동작되는지는 facebook, twitter developer toolbar 혹은 curl로 확인하면 됩니다.

마치며

검색/SNS 공유는 마케팅을 위해 중요한 부분이라고 생각이 됩니다.
하지만 위의 목적을 고려하지 않고 진행한 프로젝트들이 있는 경우 추후 변경하기란 여간 까탈스러운 작업인지라 같은 고민을 하고 계신 분들에게 도움이 되었으면 좋겠습니다.

원티드에서는 다양한 직군에서 적극적으로 채용중입니다! 서버, 웹, 앱, 디자인 등 제품을 만들어가는 각자의 분야에서 전문적인 분들과 함께 일하기를 기대하고 있습니다. 회사 채용 정보 페이지를 확인해 주세요!

--

--