한국어
  • nextjs
  • sdk
  • edge

Next.js SDK에 엣지 런타임 추가 경험

Logto의 Next.js SDK는 이제 엣지 런타임을 지원합니다. 이 글에서는 우리가 겪은 장애물들, 그것들을 어떻게 극복했는지, 그리고 이 과정에서 배운 멋진 것들에 대해 공유하려 합니다.

Sijie
Sijie
Developer

서론

엣지 런타임은 AWS Lambda@Edge, Cloudflare Workers, Vercel Edge와 같은 플랫폼에서 동적이고 지연 시간이 짧은 기능을 추진하는 기술 풍경에서 화제가 되었습니다. 그 중요성을 강조하기 위해, Vercel은 최근에 "experimental-edge"를 "edge"로 변경하여 인기있는 Next.js 프레임워크에서 공식적으로 지원한다는 신호를 보냈습니다.

Next.js SDK가 큰 관심을 받으면서, 우리 Logto는 "왜 엣지 런타임 지원을 추가하지 않을까?"라고 생각했습니다. 그래서 우리는 소매를 걷어붙이고 바로 도전했습니다. 이 글에서는 우리의 모험을 공유하면서, 우리가 직면한 장애물들, 그들을 어떻게 극복했는지, 그리고 이 과정에서 배운 멋진 것들을 공유하려 합니다.

엣지 런타임 지원을 위한 모듈 및 종속성 전환

엣지 런타임을 다루는 것은 몇 가지 독특한 도전을 던집니다. 주로 Node.js에서 흔히 사용되는 모든 모듈과 종속성을 지원하지 않기 때문입니다. 우리는 crypto, lodash, 그리고 iron-session 모듈에서 이 문제에 부딪혔고, 몇 가지 독창적인 대안을 찾아야 했습니다.

크립토

Node.js 환경에서, crypto 모듈은 OpenSSL 암호화 기능의 래퍼 역할을 합니다. 불행히도, 엣지 런타임은 이를 지원하지 않습니다. 하지만 걱정하지 마세요 - 대부분의 엣지 런타임들은 Web Crypto API 지원을 통해 구조를 제공합니다. 몇 가지 작은 차이점에도 불구하고, 이것은 crypto 모듈에 대한 탄탄한 대체물입니다. 예를 들어, 랜덤 바이트를 생성하려면:

그리고 해싱:

로대시

많은 개발자들 사이에서 Lodash는 그 유틸리티로 인해 인기가 있지만, 엣지 런타임은 그렇지 않습니다. 우리의 해결책은 무엇인가요? 우리는 Lodash 기능을 대체하면서도 코드를 효율적이고 읽기 쉽게 유지하기 위해 네이티브 자바스크립트 메서드로 Lodash 함수를 교체했습니다.

대부분의 Lodash 함수를 대체하는 것은 헤라클레스의 일이 아니었지만, 일부 섬세함을 필요로 했습니다. "once"의 유틸리티를 우리만의 방식으로 어떻게 재현했는지 살펴봅시다:

아이언 세션

iron-session 모듈의 최신 버전은 Edge Runtime에 친화적이므로, 우리는 단지 우리의 버전을 업데이트만 하면 됩니다. 그것만이었습니다!

엣지 런타임에서 "Response"의 복잡함 찾아보기

우리가 SDK를 엣지 런타임에 적용할 때 마주한 다른 도전 과제는 "Response" 객체의 차이를 다루는 것이었습니다. 우리가 이 차이를 어떻게 극복했는지 살펴봅시다:

수동으로 응답 생성하기

Node.js에서와는 달리, 엣지 런타임에서의 요청은 응답을 공급받지 않습니다. 이는 우리가 new Response()를 호출함으로써 응답을 직접 생성해야 한다는 것을 의미합니다. 다음은 데이터를 반환하는 예입니다:

"withIronSessionApiRoute"를 포기하기

엣지 런타임에서 Response.body는 읽기 전용이라는 것은, 우리가 데이터가 준비될 때까지 응답을 초기화할 수 없다는 것을 의미합니다. 결과적으로, 우리가 의지하는 "withIronSessionApiRoute" (그리고 다른 미들웨어들)는 대기팀에 넣어야 했습니다.

우리가 교체한 것이 무엇인지 이해하려면, withIronSessionApiRoute가 실제로 어떤 일을 하는지부터 살펴봅시다:

  1. 그것은 쿠키를 살펴보고, 세션 객체를 구성하고, 이를 res에 연결합니다.
  2. 세션에 변화가 있으면 res에 "set-cookie" 헤더를 자동으로 추가합니다.

그렇다면, 우리는 이 기능을 새로운 엣지 런타임 환경에서 어떻게 모방했을까요?

  1. 읽기: 우리는 기존의 getIronSession 함수를 활용했습니다. 이를 통해 비어 있고 가짜 response를 제공하면 필요에 따라 세션을 검색합니다. 이것은 req.session의 "get" 메서드를 대체했습니다.
  2. 쓰기: 우리는 데이터를 미리 준비한 response를 만들었고, 그 다음에 이 response 인스턴스에 getIronSession을 사용하여 세션 객체를 얻었습니다. 한번 우리가 이 객체를 손에 넣으면, 필요에 따라 세션을 수정할 수 있습니다.

리디렉션

엣지 런타임에서의 리디렉션은 우리가 수동으로 Location 헤더를 응답에 추가할 필요가 있었습니다.

한 패키지, 두 런타임

우리의 이 여정에서, 우리는 엣지와 Node.js 런타임을 모두 지원하기 위해 하나의 패키지를 고수하기로 결정했습니다.

왜 그랬는가

우리는 엣지용으로 별도의 패키지를 만들 생각을 했지만, 이는 불필요하다는 것을 빠르게 깨달았습니다. 대부분의 코드는 두 런타임에 공유되며, 몇 줄의 코드만이 소소한 수정이 필요했습니다. 또한, SDK의 사용은 대체로 두 런타임에서 모두 거의 동일하므로, 통합된 패키지를 유지하는 것이 가장 많은 의미가 있었습니다.

우리가 한 것은 어떤가

노력을 중복시키는 대신, 우리는 기존 패키지를 확장하기로 결정했습니다. 우리는 패키지의 루트에 바로 "edge" 폴더를 추가했고, 그것은 오래된 "src" 폴더 옆에 편안하게 위치했습니다. 그 다음, 우리는 package.json 파일을 업데이트했고, "exports"에 새로운 경로를 추가했습니다. 이 방법으로, 엣지와 Node.js 런타임은 같은 패키지 내에서 최소한의 번거로움으로 조화롭게 공존할 수 있었습니다.

마무리

여러분은 우리의 다음.js SDK edge 부분의 전체 소스 코드를 여기에서 확인할 수 있습니다.

엣지 런타임을 포용하는 여행을 공유함으로써, 우리는 다른 사람들이 비슷한 경로를 탐색하는 데 영감과 가이드를 제공하려고 합니다. 우리의 Next.js SDK와 함께 더 많은 업데이트를 기대해 주세요.