이게 NextJS보다 훨씬 낫네요 (TanStack 서버 컴포넌트)

BBetter Stack
컴퓨터/소프트웨어AI/미래기술

Transcript

00:00:00리액트 서버 컴포넌트. 좋거나 싫거나. 요새는 대부분 싫어하는 것 같지만,
00:00:04이제 상황이 바뀔지도 모르겠습니다. TanStack이 참전했거든요. 맞습니다, 이제 TanStack
00:00:08서버 컴포넌트가 생겼고, Next.js와는 꽤 다른 접근 방식을 취했습니다. 한번 살펴보죠.
00:00:13우선 많은 사람들을 안심시켜 줄 만한 그들의 발표 게시물 중 한 단락으로 시작하겠습니다.
00:00:21이렇게 적혀 있네요. "대부분의 사람들은 이제 리액트 서버 컴포넌트를 서버 우선
00:00:26방식으로 생각합니다. 서버가 트리를 소유하고, useClient가 상호작용이 필요한 부분을 표시하며, 프레임워크 규칙이
00:00:31전체 구조를 결정하죠. 이는 리액트 서버 컴포넌트를 유용한
00:00:35프리미티브에서 앱 전체가 중심을 잡아야 하는 존재로 바꿔버립니다. 우리는 여러분이
00:00:40리액트 서버 컴포넌트의 가치를 얻기 위해 그 모델 전체를 처음부터 강제로 받아들일 필요는 없다고 생각합니다."
00:00:45본질적으로 그들이 말하는 건 Next.js처럼
00:00:48기본적으로 서버 컴포넌트로 두고 상호작용이 필요할 때마다 useClient 지시어를 붙여야 하는
00:00:52방식을 따르고 싶지 않다는 겁니다. 대신 TanStack은 리액트 서버 컴포넌트를
00:00:57클라이언트에서 JSON을 가져오는 것만큼 세밀하게 사용할 수 있다면 어떨까라는 관점에서 접근합니다. 그런 목표를 염두에 두고,
00:01:01그들이 실제로 어떻게 서버 컴포넌트를 구현했는지 살펴보겠습니다. 스포일러를 하자면 저는 그 방식이 정말 마음에 듭니다.
00:01:06지금 제가 가진 건 일반적인 TanStack Start 애플리케이션이라서 현재는 모든 것이
00:01:10클라이언트 컴포넌트가 될 겁니다. 제가 한 거라곤 서버 컴포넌트를 실행하기 위해 필요한
00:01:15몇 가지 설치 단계를 거친 게 전부인데, 본질적으로는 패키지를 몇 개 설치하고
00:01:18vconfig를 수정하는 작업입니다. 현재 페이지 모습은 이렇습니다. 여기에 Greeting 컴포넌트가 있는데
00:01:22현재는 클라이언트 컴포넌트이고, 코드상으로는 말 그대로 단순한 리액트 컴포넌트 하나입니다.
00:01:27그리고 아래쪽에는 일반적인 TanStack 라우트가 있고 여기서 Greeting 컴포넌트를 사용하고 있습니다. 자, 이제
00:01:32Greeting 컴포넌트에서 서버 측 로직을 수행하고 싶다고 가정해 봅시다. 저는
00:01:36운영체제의 호스트네임을 가져오고, 서버에서만 사용할 수 있는 환경 변수도
00:01:40가져와서 이게 실제로 서버에서 실행되고 있음을 보여주려고 합니다. 현재 상태에서 os.hostname을 사용하려고 하면
00:01:45이건 노드 함수라서 브라우저에서는 사용할 수 없기 때문에 작동하지 않을 겁니다.
00:01:49그럼 어떻게 해야 할까요? Greeting 컴포넌트를 가져와서 서버에서 렌더링해야 하는데,
00:01:53TanStack Start에서 그렇게 하는 첫 번째 단계는 간단한 서버 함수를 사용하는 것입니다. 보시다시피
00:01:58여기 getGreeting이라는 함수가 하나 있고, 그 안에서 하는 일이라곤 새로운 renderServer
00:02:01Component 함수를 사용해서 컴포넌트를 그 안에 넣고, 반환된 렌더링 가능한 서버 컴포넌트를
00:02:06돌려주는 것뿐입니다. 이건 그냥 컴포넌트에 대한 GET 요청을 만드는 것만큼이나 간단하게 생각하시면 됩니다.
00:02:10그다음 할 일은 우리가 만든 서버 함수로부터 컴포넌트를 단순히 페치해 오는 것입니다.
00:02:14라우트의 로더 안에서 할 수 있는데, getGreeting을 await로 기다린 다음
00:02:18그 결과값을 반환하면 여전히 렌더링 가능한 서버 컴포넌트입니다. 그리고 이것을
00:02:23라우트 안에서 useLoaderData를 사용해 가져와 아래처럼 컴포넌트를 사용하면 됩니다. 이렇게 해서
00:02:27첫 번째 TanStack 서버 컴포넌트가 완성되었습니다. 보시다시피 os.hostname이 이제 잘 작동하고,
00:02:32서버에서만 접근 가능한 환경 변수들도 가져오고 있습니다. 제가 이 구현 방식에서
00:02:36정말 마음에 드는 점은, 유일하게 새로 추가된 것이 render
00:02:41ServerComponent 함수라는 점입니다. 나머지는 그냥 일반적인 TanStack Start 코드일 뿐이죠. 이것을
00:02:46단순히 JSON 데이터를 반환하는 방식으로 바꿔도 똑같은 방식으로 페치할 수 있습니다. 또한 저는
00:02:51이 구현 방식이 코드가 실제로 어디서 실행되는지 매우 명확하게 보여준다고 생각합니다. 모든 작업을
00:02:55서버 함수 안에서 수행하기 때문에 서버에서 실행될 것이라는 점이 꽤 분명하고,
00:02:59renderServerComponent 안에서도 마찬가지입니다. 사실 제 데모 코드를 개선할 수 있을 것 같은데,
00:03:03위에서 서버에서 실행되길 바랐던 함수들을 가져와서
00:03:07서버 함수 내부에 넣고, 그 값들을 Greeting 컴포넌트에 props로 전달하면
00:03:12이제 Greeting 컴포넌트는 클라이언트나 서버 어디서든 사용할 수 있는
00:03:16순수한 컴포넌트가 됩니다. 저는 서버에서 실행하고 싶은 모든 로직을
00:03:21여기 서버 함수 내부에서 실행하고 있습니다. 다시 말하지만, 서버에서 실행될 것이라는 점이 매우 명확합니다. 이건
00:03:25말 그대로 Next.js에서 사용된 로직과 정확히 반대되는 느낌인데, 정말 마음에 듭니다.
00:03:30리액트를 평소처럼 생각할 수 있다는 뜻이죠. 전부 클라이언트 우선으로 시작해서, 원할 때
00:03:34서버 컴포넌트를 그 위에 추가하면 됩니다. 하지만 서버 컴포넌트 안에 클라이언트 컴포넌트를 사용하고 싶다면 어떨까요?
00:03:38트리 안에 중첩해서 말이죠. 예를 들어 여기에 클릭할 때마다 카운터가 올라가는
00:03:43카운터 버튼을 추가하고 싶다고 해봅시다. 제가 단순히 서버 컴포넌트에 onClick과
00:03:47useState 호출을 추가하려고 하면, 완전히 망가집니다. useState는
00:03:52함수가 아니거나 그 반환값이 반복 가능하지 않다고 나오는데, 그건 Greeting이 서버
00:03:56컴포넌트로 사용되고 있기 때문입니다. 이런 클라이언트 기능을 사용할 수 없는 거죠. 이걸 해결하려면 두 가지 방법이 있는데, 두 번째
00:04:01방법이 확실히 더 좋지만 첫 번째 방법은 Next.js를 사용해 본 사람들에게 익숙하게 느껴질 겁니다.
00:04:05단순히 그 로직을 별도의 컴포넌트로 옮기고 useClient
00:04:10지시어를 사용하면 됩니다. 이건 TanStack Start 서버 컴포넌트에서도 작동합니다. 그냥
00:04:14서버 컴포넌트 안에서 그 컴포넌트를 사용하면 이제 아주 잘 작동합니다. 하지만 이 접근 방식의 단점은
00:04:18클라이언트 컴포넌트의 렌더링을 제어하는 서버 컴포넌트가 생겨버린다는 점이며,
00:04:22이게 조금 지저분해지기 시작할 수 있다는 겁니다. 예를 들어 카운터 컴포넌트가 트리 어디에 있는지
00:04:28찾으려면 라우트로 가서 Greeting 서버
00:04:32컴포넌트가 있다는 걸 보고, 다시 Greeting 서버 컴포넌트로 올라가서 그 안에서
00:04:37클라이언트 컴포넌트가 있는 걸 확인해야 하죠. 이런 복잡함이 계속 쌓이면서 서버와 클라이언트의
00:04:42경계가 조금 불분명해질 수 있습니다. 하지만 TanStack은 그렇게 타협하지 않았죠. 그들은
00:04:47서버가 UI의 모든 클라이언트 형태 부분을 결정할 필요가 없으면 어떨까 하고 자문했고,
00:04:51이것이 완전히 새로운 개념인 '복합 컴포넌트(Composite Components)'를 만드는 계기가 되었습니다. 하나를 사용하려면, 우선
00:04:56서버 컴포넌트에서 클라이언트 컴포넌트를 제거하고
00:05:00Greeting 컴포넌트의 모든 자식 컴포넌트로 대체하겠습니다. 다음으로, 서버 함수에서
00:05:05반환하는 값도 변경해야 합니다. 렌더링 가능한 서버 컴포넌트를 반환하는 대신, 우리는
00:05:09이른바 '복합 소스(Composite Source)'를 반환해야 합니다. 이를 위해 TanStack 서버 컴포넌트 헬퍼
00:05:14함수 중 두 번째인 createCompositeComponent를 사용할 수 있습니다. 여기서 우리는 본질적으로 컴포넌트를 구축하는 건데,
00:05:18여기서 props는 슬롯으로 간주됩니다. 저는 아주 간단한 children 슬롯을 사용하고 있으므로, 복합 컴포넌트의
00:05:22자식으로 넣는 모든 것이 props.children으로 전달되어 우리가 방금 가졌던 Greeting 컴포넌트로
00:05:27통과될 겁니다. 이렇게 하고 나서 다시 해야 할 일은
00:05:31서버 함수에서 복합 컴포넌트를 페치해 오는 것이며, 로더에서 똑같은 방식으로 수행합니다.
00:05:36보시다시피 source를 greeting으로 이름을 바꾸고 useLoaderData로 로드합니다.
00:05:41하지만 유일한 차이점은 이걸 컴포넌트로 직접 사용할 수는 없다는 겁니다. 보시다시피 에러가 발생하죠.
00:05:45복합 컴포넌트를 실제로 렌더링하려면 TanStack 서버 컴포넌트에서 제공하는 CompositeComponent 헬퍼
00:05:49컴포넌트를 사용해야 하며, source prop으로 우리가
00:05:53이전에 생성한 서버 함수에서 페치해 온 복합 컴포넌트를 전달합니다.
00:05:57이렇게 하면 서버 컴포넌트가 이전처럼 렌더링되고, 또한
00:06:01카운터를 복합 컴포넌트의 자식으로 전달하고 있으며, 이게 우리가 설정해 둔 Greeting 컴포넌트로
00:06:05전달되어 props.children으로 들어가므로 모든 것이 이제 잘 작동합니다.
00:06:10또한 카운터 컴포넌트에서 우리가 가졌던 지시어를 제거할 수도 있습니다. 왜냐하면
00:06:14복합 컴포넌트 내부에 있어서 클라이언트 컴포넌트라는 것을 이미 알고 있기 때문에 더 이상 필요가 없거든요.
00:06:18이게 슬롯으로 사용되는 중입니다. 결과만 보면 이전과 똑같은 것 같지만
00:06:23useClient 지시어를 사용하는 것보다 작업이 더 들어간 것 같겠지만, 진정한 강점은 개발자 경험에서 나옵니다.
00:06:27그리고 이건 useClient 모델과는 조금 다른 방식이죠. 우리의
00:06:32서버가 클라이언트 컴포넌트가 어디에 렌더링될지 결정하게 하는 대신, (카운터 컴포넌트를
00:06:36서버 컴포넌트 자체에 넣었을 때처럼 말이죠) 대신 복합 컴포넌트로는 이렇게 말하는 겁니다. 여기
00:06:40슬롯이 있을 거고 클라이언트 컴포넌트를 렌더링할 건데,
00:06:44서버 컴포넌트 자체는 그게 무엇인지 전혀 알 필요가 없다는 거죠. 우리는 나중에 클라이언트 코드에서 그 부분을 추가합니다.
00:06:48그러니 모든 클라이언트 기반 컴포넌트를 클라이언트 코드 자체 내에서 처리하는 거죠. 이건 시작에 불과합니다.
00:06:53이 게시물 페이지처럼 더 복잡한 페이지를 보면, 이 게시물은 서버에서 렌더링되고 있는데
00:06:58제가 해결하고 싶은 두 가지 문제가 있습니다. 첫 번째는 게시물 좋아요나
00:07:03작성자 팔로우 같은 동작을 추가하고 싶은데, 여기 제목 위에 넣고 싶고
00:07:08클라이언트 컴포넌트를 사용하고 싶다는 겁니다. 현재는 단순히 children 슬롯 패턴을 사용하고 있는데, 만약 제가
00:07:12포스트 액션을 아래쪽에 추가하면 댓글이 있는 곳으로 들어가 버릴 겁니다. 컴포넌트가 그렇게
00:07:17설정되어 있기 때문이죠. 그래서 서버 컴포넌트에게 특정 클라이언트
00:07:22컴포넌트를 어디에 배치할지 알려줄 방법이 필요합니다. 그다음 두 번째 문제는, 팔로우 작성자 버튼이 있다고 치면
00:07:27이 게시물 페이지는 현재 게시물 작성자가 누구인지 전혀 모릅니다. 우리는 사실 모든 로직을
00:07:32서버 컴포넌트 자체로 오프로드해 버렸거든요. 만약 아래쪽 클라이언트 컴포넌트에서 작성자를 가져오고 싶다면
00:07:37포스트에 대한 JSON을 페치해서 작성자를 가져와야 하는데, 그건 정말 좋은
00:07:42패턴이 아니죠. 데이터를 두 번 가져오게 되는 셈이니까요. 다행히 TanStack에는 복합 컴포넌트에서 사용할 수 있는
00:07:46children 외에도 두 가지 다른 슬롯 타입이 있습니다. 첫 번째는
00:07:50렌더 프롭(render props)입니다. 이건 본질적으로 리액트 요소를 반환하는 함수인 모든 prop을 의미하므로
00:07:56이름은 꼭 renderActions가 아니어도 됩니다. 여기서는 제가 서버 컴포넌트가 전달해주길 바라는 데이터가
00:07:59무엇인지 말하고 있는데, 바로 post ID와 author ID입니다.
00:08:04이제 복합 컴포넌트에서 해야 할 일은 우리가 전달하는 이 함수를
00:08:08결국 렌더링될 컴포넌트가 위치할 곳에 그냥 사용하기만 하면 됩니다.
00:08:12제 경우에는 카드 헤더 아래에 위치하고 싶으니 props.render
00:08:16actions로 호출하면 됩니다. 옵셔널을 사용할 수 있으니 전달되지 않아도 고장 나지 않고
00:08:20렌더링만 되지 않을 뿐입니다. 그리고 우리가 원하는 정보를 서버 컴포넌트에서
00:08:24클라이언트 컴포넌트로 전달할 수도 있습니다. 그 후 우리의 복합 컴포넌트는 방금 만든 renderActions
00:08:28prop을 허용할 것이고, 값으로는 단순히 포스트 ID와 작성자 ID를
00:08:32인자로 받는 함수를 전달하면 서버가 그 인자를 채워줄 것입니다. 그러고 나면 포스트 액션
00:08:36클라이언트 컴포넌트를 렌더링하고 그 데이터를 props로 전달하기만 하면 됩니다. 이제
00:08:41여기에 좋아요를 누르고 게시물 링크를 복사하거나, '팔로우 작성자' 버튼을 클릭할 수 있는 버튼이 생겼는데
00:08:45이 페이지에서는 전혀 가져온 적이 없음에도 작성자 이름을 알고 있습니다.
00:08:49서버 컴포넌트에서만 가져오고, 그 서버 컴포넌트가 그 데이터를
00:08:53클라이언트 컴포넌트로 전달해주고 있는 겁니다. 이제 우리가 이전에 말했던, 서버 컴포넌트가
00:08:57클라이언트 컴포넌트 렌더링을 담당해서는 안 된다는 논리가 깨진다고 생각할 수도 있지만, 그렇지 않습니다.
00:09:01그 이유는 슬롯은 사실 불투명(opaque)하기 때문입니다. 서버 컴포넌트는
00:09:06그 안에 뭐가 있는지 전혀 모르고, 그저 무언가가 여기에 들어가고 이 값들을 전달받아야 한다는 것만 압니다.
00:09:10이 경우에는 post ID와 author ID죠. 이 함수는 서버에서 실행되지 않습니다. 대신
00:09:15서버는 단순히 데이터를 전달해야 한다는 것을 알고 있고, 클라이언트 쪽에서
00:09:19비로소 함수가 실제로 실행되고 컴포넌트가 렌더링되는 겁니다. 정확히 같은 내용이
00:09:23세 번째 슬롯 타입인 컴포넌트 프롭(component props)에도 적용됩니다. 이건 렌더 프롭보다
00:09:28사실 더 간단합니다. 클라이언트 컴포넌트를 반환하는 함수를 가지는 대신
00:09:33우리는 그냥 클라이언트 컴포넌트 자체를 prop으로 전달하기만 하면 됩니다. 그다음 우리의 복합 컴포넌트
00:09:38정의 부분에서 post ID와 author ID를 props로 가지는 리액트 컴포넌트를
00:09:42prop으로 허용하겠다고 명시하면 컴포넌트 자체 내에서 이걸 사용할 수 있습니다. 컴포넌트 프롭을
00:09:47일종의 플레이스홀더처럼 생각할 수 있습니다. 서버 컴포넌트는 그곳에
00:09:51데이터가 필요한 어떤 컴포넌트가 들어올 것임을 알고 있지만(우리의 경우 post ID와 author ID), 그
00:09:56컴포넌트가 정확히 무엇인지는 상관하지 않습니다. 해당 props를 받기만 하면 되니까요. 그래서 제 포스트 액션 컴포넌트를
00:10:01fakePostActions라는 다른 것으로 변경하고 저장하면, 이것이
00:10:05여전히 렌더링되는 것을 볼 수 있습니다. 이 컴포넌트를 렌더링할 책임은 클라이언트에게 있기 때문이며,
00:10:10서버는 데이터만 제공할 뿐입니다. 문서를 살펴보면, 어느 접근 방식을 택하든
00:10:14컴포넌트 프롭을 쓰든 렌더 프롭을 쓰든 별다른 차이는 없어 보입니다.
00:10:18취향 차이일 수 있습니다. 제가 볼 수 있는 유일한 차이는 서버에서 받은
00:10:22데이터를 수정하고 싶을 때 정도인데, 이 경우에는 함수일 뿐이므로
00:10:26post ID와 author ID를 원하는 대로 처리한 다음 컴포넌트로 전달할 수 있습니다.
00:10:31반면에 컴포넌트 프롭을 사용하면 컴포넌트 자체를 전달하게 되고 서버가
00:10:36props 전달을 처리하게 되죠. TanStack 서버 컴포넌트의 기본은 여기까지입니다. 하지만
00:10:40더 좋은 점들이 많습니다. 예를 들어 페이지 대부분이 서버에서 렌더링되길 원해서
00:10:44헤더, 콘텐츠, 푸터 컴포넌트가 있고 이들을 모두 서버에서
00:10:49렌더링하고 싶다면, 모든 걸 하나의 renderServerComponent 함수에 묶을 필요가 없습니다. 실제로
00:10:53Promise.all을 사용해서 세 개의 다른 함수로 나누고, 단순히 단일 서버 함수에서
00:10:58객체로 반환할 수 있습니다. 하지만 그중 하나가 로딩이 오래 걸리면 어떻게 될까요? 그렇다면
00:11:03전체 서버 함수가, 결과적으로 전체 페이지가 느려질 겁니다. 하지만 그것도 걱정 마세요.
00:11:07실제로 우리가 할 수 있는 건 renderServerComponent 함수를 await로 기다리는 대신
00:11:12그것이 생성하는 promise를 반환하고, 클라이언트에서 use 훅과
00:11:16서스펜스(Suspense) 경계를 활용해 스켈레톤을 로드하는 것입니다. 그럼 서버 컴포넌트는 준비되는 대로 로드될 겁니다.
00:11:21저는 TanStack이 취한 이런 접근 방식이 정말 마음에 듭니다. 강압적으로 느껴지지 않고
00:11:25억지로 채택할 필요가 없으며, 이상한 우회 방법 없이도 사용할 수 있습니다. 게다가 실제로 사용하게 될 때
00:11:31서버 컴포넌트 자체는 사실 세 개의 새로운 함수일 뿐이고, 나머지는 그냥 평범한
00:11:36TanStack Start 서버 함수들입니다. 이미 제가 사용하고 있던 것이고, 그냥 데이터를 페치하는 것처럼 간단하죠.
00:11:41이건 또한 TanStack Query 같은 도구와도 잘 통합된다는 뜻인데, 제가
00:11:45꼭 그렇게 할 예정입니다. 그리고 캐싱 같은 것들도 더 간단해집니다. 원한다면
00:11:49CDN에서 GET 요청에 대한 응답을 그냥 캐시해 버릴 수도 있겠죠. 저는 확실히 이것들을 더 탐구해 볼 겁니다.
00:11:54그러니 여러분은 이것들에 대해 어떻게 생각하는지 아래 댓글로 알려주시고, 더 많은 영상을 보고 싶으시면
00:11:59구독해 주세요. 그럼 항상 그렇듯 다음 영상에서 뵙겠습니다.

Key Takeaway

TanStack 서버 컴포넌트는 클라이언트 우선 개발 흐름을 유지하면서도 필요할 때만 서버 컴포넌트와 복합 컴포넌트 패턴을 사용하여 서버 로직을 명확하고 효율적으로 분리할 수 있게 합니다.

Highlights

TanStack 서버 컴포넌트는 Next.js와 달리 기본 서버 중심 모델을 강제하지 않고 필요에 따라 선택적으로 사용할 수 있는 유연한 프리미티브 방식을 채택합니다.

서버 측에서 renderServerComponent 함수를 통해 컴포넌트를 렌더링하고, 클라이언트에서 GET 요청처럼 단순히 페치해 가져오는 방식을 사용합니다.

복합 컴포넌트(Composite Components) 패턴은 createCompositeComponent를 사용하여 서버가 UI의 클라이언트 부분을 알 필요 없이 슬롯 패턴으로 데이터만 전달합니다.

렌더 프롭(render props)과 컴포넌트 프롭(component props)을 사용하여 서버 컴포넌트에서 클라이언트 컴포넌트로 post ID, author ID와 같은 데이터를 안전하게 전달할 수 있습니다.

전체 페이지 렌더링을 기다리지 않고 Promise.all과 서스펜스(Suspense) 경계를 활용해 컴포넌트 단위로 개별적인 비동기 로딩이 가능합니다.

Timeline

TanStack 서버 컴포넌트의 접근 방식

  • 리액트 서버 컴포넌트를 강제적인 전체 모델로 받아들일 필요가 없습니다.
  • 클라이언트에서 JSON을 가져오는 것과 유사하게 세밀한 단위로 서버 컴포넌트를 활용합니다.

TanStack은 서버가 트리를 소유하고 useClient 지시어로 클라이언트를 표시하는 Next.js 방식과는 다른 접근을 취합니다. 개발자는 전체 앱 구조를 서버 중심으로 재편하지 않고도 필요한 부분에만 서버 컴포넌트를 점진적으로 도입할 수 있습니다.

서버 함수를 이용한 컴포넌트 렌더링

  • renderServerComponent 함수로 서버 측 컴포넌트를 생성하고 반환합니다.
  • 라우트의 로더에서 서버 함수를 await로 대기한 뒤 페치하여 사용합니다.

서버에서만 실행 가능한 os.hostname이나 환경 변수 등을 활용하기 위해 서버 함수를 정의합니다. 이 방식은 일반적인 데이터 페치 방식과 동일하여 개발자가 로직이 어디서 실행되는지 명확히 파악할 수 있게 합니다.

복합 컴포넌트와 클라이언트 슬롯 패턴

  • 클라이언트 기능을 서버 컴포넌트 안에 직접 넣을 수 없는 한계를 복합 컴포넌트로 해결합니다.
  • createCompositeComponent를 사용하여 컴포넌트를 슬롯 기반으로 구축합니다.

서버 컴포넌트 내부에 직접 클라이언트 컴포넌트를 중첩하면 의존성 문제가 발생합니다. TanStack은 서버가 클라이언트 렌더링 위치를 제어하지 않고 슬롯에 데이터를 전달하는 복합 컴포넌트 방식을 통해 이를 해결합니다.

데이터 전달 및 비동기 처리 최적화

  • 렌더 프롭과 컴포넌트 프롭으로 서버의 데이터를 클라이언트 컴포넌트로 전달합니다.
  • Promise.all과 서스펜스를 활용해 컴포넌트별로 비동기 로딩을 처리합니다.

데이터를 두 번 가져오지 않기 위해 서버에서 렌더 프롭이나 컴포넌트 프롭을 사용하여 클라이언트 컴포넌트에 필요한 인자를 전달합니다. 또한 개별 컴포넌트가 로딩이 길어질 경우 전체 페이지가 아닌 해당 컴포넌트만 스켈레톤을 보여주며 비동기로 로드하여 성능을 최적화합니다.

Community Posts

No posts yet. Be the first to write about this video!

Write about this video