NextJS Middleware와 CDN으로 이런것도 가능해요.

endmoseung·2024년 3월 11일
4
post-thumbnail

최근 회사에서 같은 도메인으로 접속했을때 서로 다른 서비스를 보여줘야 할 일이 생겼다. 그때 과정에서 어떤 문제를 만났고 그 문제를 어떻게 해결했는지 정리한 글이다.

1. Intro

회사가 글로벌로 나가게되면서 기존에 국내 서비스들을 해외에서 사용할 수 있어야 했다. 그 과정에서 당연히 홈페이지의 번역이 필요했고 그와 동시에 외국에 맞는 서비스를 만들어야하는 니즈가 생겼다.
그 중에서 회사 플랫폼서비스에서 제공하는 기능을 외국에도 제공해야할 필요가 있었고 당시 레거시가 좀 있던 플랫폼임에 동시에 권한과 관련 된 작업이 있어서 해당 서비스를 새롭게 개발하여 다국어가 지원되는 플랫폼으로 마이그레이션 하자고 결정이 났다.
하지만 모든 서비스를 한번에 마이그레이션하는건 많은 시간이 필요하기에 필요한만큼 부분적으로 해야했고, 같은 URL로 접속했을때 국외에선 마이그레이션 하는 서비스로 국내에선 기존에 만들어둔 서비스로 이동해야 했다.
이 과정에서 NextJS와 CDN으로 문제해결을 한 걸 공유한다.

Why NextJS?

당시 NextJS로 마이그레이션 하자고 결정이 났는데 그 배경은 이렇다.

1. 느린 데이터 속도

우선 최근 회사가 동남아쪽에 많이 진출했다. 플랫폼을 마이그레이션 하기로 결정이 나던 순간에 불현듯 동남아에서 데이터속도는 어떨까라는 생각이 들었다. 그래서 당시 출장가신 동료분들과 구글링으로 실제로 속도가 느리다는 결론을 냈다. 그래서 SSR로 유저에게 LCP를 최적화해주면 좋을 것 같았다.

베트남 내 이동통신망 다운로드 속도는 42.46Mbps로 세계 평균인 55.07Mbps보다 낮은 것으로 나타났다.
한국과 5배 차이난다.
-한국경제TV-

2. 서버사이드에서 함수 실행

위에서 공유한 설명에 대한 처리를 리액트에서 진행하게되면 사용자는 클라이언트에서 함수가 들어있는 스크립트를 다운로드 받고나서야 리다이렉트 해야하는 로직이 실행된다. 이를 잘 분리하면 용량이 크지 않지만 동남아에선 데이터 속도 이슈가 있기에 배제했다.

//In React
React 코드를 유저가 다 받아야 비로소 함수 실행
// In NextJS
서버사이드에서 함수를 바로 실행한다.

그래서 serverLess하게 이 처리를 하고 싶었고 NextJS를 이용해서 이를 처리하려고 했다. 아래 사진은 당시 유저 플로우이다.

3. 번역된 SEO

당시 NextJS에서 I18n을 적용하면 수월하게 ServerSide에서 번역작업이 적용돼어 프리렌더된 html을 받을 수 있었다.

그리하여 이런 모든 이유를 통합했을떄 NextJS라는 프레임워크를 사용하는것이 좋은 결정이라는 생각을 했고 당시 이미 NextJS를 사용하여 개발중인 서비스도 있었다. 그래서 인프라분들께도 서버를 띄우는걸 요청하기 쉬웠다.

2. 문제 발견

그리하여 NextJS로 개발하기로 결정했지만 많은 문제가 발생했다.

1. css

당시 기존 서비스는 StyledComponents로 개발했고 최근 팀에서는 서버사이드와 개발속도의 이점을 살리기 위해서 Tailwind를 사용하기로 결정됐다.
그리하여 기본적인 마크업은 비슷하지만 CSS를 거의 새로 타이핑 해야하는 문제가 생겼다.

2. SSR

기존 코드를 베이스를 참고하여 마이그레이션 했다.
기존에는 리액트로 개발했기에 로직이 클라이언트 사이드만 적용하도록 코드가 구성돼있어서 부분적으로 동작하지 않을수도 있었다. 그래서 이부분은 팀원들과 협의하여 클라이언트 사이드에서 동작이 필요한것과 그렇지 않은 상황을 분리하여 SSR을 컴포넌트로 삽입할 수 있도록 했다.

3. 유저의 Geo 값

아래의 링크들과 이유 때문에 NextJS request에 있는 geo값을 사용하지 않기로 했다. 정리하면 성능이 별로 좋지 않고 Vercel외엔 적용이 어렵다.
그러던 중 당시 인프라분이 CloudFront에서 Geo값을 정해둔 인터페이스로 넘겨주도록 설계해주셨다. 그래서 이를 NextJS middleware에서 request값에서 해당 인터페이스를 읽고 geo값을 받아서 redirect할 수 있도록 적용했다.

4. 무한 Redirect

위에서 설명한 3번을 진행하고 번역서비스인지 아닌지를 구분하여 만약 www.moseung.com/redirect로 접속하게 되
면 퍼스트레이어로 NextJS로 탄 후 CDN에서 다시 www.moseung.com/redirect로 Redirect 했는데 이렇게 하면 당연하게도 무한 Redirect가 일어난다.
그래서 React쪽에서 pathname을 조금 수정하고 CDN에서 분기처리를 인프라분이 해주셔서 React쪽 서비스와 NextJS서비스로 갈 수 있도록 했다.
이부분이 복잡하여 그림으로 다시 설명하겠다.

참고로 redirect의 상태코드는 307이다. https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/307

3. 기술은 도구일 뿐

이번에 NextJS를 사용해서 주어진 요구사항을 구현했다. 만약에 React를 사용한다면 CDN과 LambdaEdge같은 ServerLess를 이용하여 적용할 수도 있다.

똑같은 작업이지만 정말 많은 방법이 있다. 그리고 요즘 OpenAI를 통해서 쉽게 여러 방법을 알 수 있다.
하지만 우리는 그것들중에서도 가지고 있는 자원으로 최대한 효율적으로 할 수 있는 방법으로 결정하고, 많은 경험을 통해 결정하는 눈을 기르는게 필요한 것 같다.

profile
Walk with me

0개의 댓글