[Typescript] Next.js App Router에서 Barrel Index를 사용할땐 서버와 클라이언트를 주의하여 구분하자

728x90
반응형

[Typescript] Next.js App Router에서 Barrel Index를 사용할땐 서버와 클라이언트를 주의하여 구분하자

서론

뭐... 이번 포스팅은 이미 제목에서 모든걸 설명하고 있다... Next.js App Router에서 Barrel Index를 사용하다가, 주의할 점을 발견하게 되어 포스팅으로 남기게 됐다.

서버 컴포넌트는 "use client"가 붙은 파일에서 export한 요소를 사용할 수 없다.

어찌보면 당연한 사실일 수 있지만, 놀랍게도 서버 컴포넌트에선 "use client"를 붙인 파일에서 export한 모든 요소를 "return 키워드" 이전에 사용할 수 없다.

위 이미지 처럼 "use client"를 붙인 client.ts에서 SessionProvider 컴포넌트와 getServerSession 함수를 export하고, "use client"를 붙이지 않은 layout.tsx에서 이를 import 하는 상황을 예시로 들어보겠다.
SessionProvider는 컴포넌트이기 때문에 일반적으로 layout.tsx RootLayout 컴포넌트의 return 키워드 안에서 사용될 것이다. 다만 getServerSession 함수는 return 키워드 이전에 호출이 되어 값을 반환해야하기 때문에, layout.tsx의 RootLayout 컴포넌트가 서버 컴포넌트인 점을 고려하면 getServerSession은 서버 환경에서 return 키워드 이전에 호출 될 것이다.

그래서 실행 결과를 살펴보면, (0, _common_session_WEBPACK_IMPORTED_MODULE_2__.getServerSesion) is not a functinon 오류가 나타나는 점을 확인할 수 있다. RootLayout 컴포넌트가 랜더링되는 시점에서 getServerSession은 존재하지 않았다는 것이다.

이는 Webpack의 번들링 문제와 관련있는 것으로 보이며, Webpack 번들링으로 인해 "use client"가 붙은 파일에서 export를 한 요소는 서버 컴포넌트의 랜더링 시점에서 import해올 수 없는 것으로 보인다. 이러한 문제는 함수 뿐만 아니라 상수를 export 했을때도 동일하게 발생한다 (단 type은 이러한 문제가 발생하지 않는다. type은 js상에선 컴파일될때 사라지기 때문에 번들링 결과에 포함되지 않는다.)

해결책

이를 위한 해결책은 간단했다.
barrel index를 아예 사용하지 않거나, 사용하더라도 server와 client index를 분리하는 것이다.

다만 필자의 경우, 후자(사용하되 분리하자)를 택했다(import가 길어지는건 너무 싫었다...)
그래서 index를 server.ts와 client.ts로 분리했고, client.ts에만 "use client"를 붙이게 됐다. index.ts에서 server.ts와 client.ts를 export 해주면 실제 import할때는 내가 import하려는 요소의 경로가 server인지 client인지 고민할 필요가 없어진다.

728x90
반응형