Dev/개발

요즘 핫한 SSR 프레임워크, Remix 사용해보기

단민 2022. 3. 6. 15:57
728x90

https://remix.run/

 

Remix - Build Better Websites

Remix is a full stack web framework that lets you focus on the user interface and work back through web fundamentals to deliver a fast, slick, and resilient user experience. People are gonna love using your stuff.

remix.run

위의 리믹스 공식 사이트를 둘러봅시다! 세상에.. 공식 사이트가 이렇게 힙할 수 있나요...? 첫인상부터 매우 강렬하게 다가왔습니다.

이번 프로젝트에 Remix를 도입해봐야겠다고 다짐하게 된 이유는 바로

Nested Routes

때문입니다.

 

특히 어드민 뷰를 구현할 때, 라우트 뎁스는 깊이 이동하면서도 뷰는 동일한 구조를 갖고 있는 경우가 많습니다.

이러한 경우, 동일한 부분을 컴포넌트로 분리하여 각 페이지마다 호출을 해주어야 하는 번거로움이 있었습니다. 범용성이 좋게 구현된 컴포넌트가 아닌, 단순히 분리시키기 위한 목적의 뷰를 이렇게 컴포넌트로 분리해내는 게 과연 맞는가? 하는 의문도 매번 들었습니다.

 

리믹스에서는 이 번거로움을 "nested routes"로 해결하고자 합니다.

 

상위 라우트 페이지에서 공통된 뷰를 작성하고, 바뀌어야 하는 부분은 <Outlet />으로 넣어주면, 하위 라우트 페이지에서 작성된 뷰가 Outlet에 들어가게 됩니다.

 

코드로 한 번 살펴보도록 하죠!

 

우선은 위와 같은 구조로 라우터를 생성해보도록 하겠습니다.

/, /blog, /blog/{id} 의 세 라우터가 만들어지겠죠?

 

// routes/index.tsx
export default () => {
  return (
    <div>
      index.tsx
    </div>
  );
};

// routes/blog.tsx
export default () => {
  return (
    <div>
      <div>blog</div>
      <Outlet />
    </div>
  );
};

// routes/blog/index.tsx
import { Comp } from "~/components/comp";

export default () => {
  return (
    <div>
      blog/index.tsx <Comp />
    </div>
  );
};

// routes/blog/$id.tsx
export default () => {
  const { id } = useParams();
  return <div>blog/$id.tsx {id}</div>;
};

// components/Comp.tsx
export const Comp = () => {
  return (
    <div>
      comp
    </div>
  );
};

 

해당 코드에 대응되는 페이지들을 한 번 보도록 하죠.

루트에서는 index.tsx 에 정의된 UI가 뜨는 것을 볼 수 있습니다.

/blog에서는 blog.tsx 와 blog/index.tsx 에 해당하는 코드 (+ import 한 컴포넌트 내부 코드)가 뜨는 것을 볼 수 있고,

/blog/{id}에서는 blog.tsx 와 blog/$id.tsx 에 해당하는 코드가 뜨는 것을 볼 수 있습니다.

 

blog.tsx의 코드는 blog 라우트 하위에 해당하는 뷰에서는 nest 되어 모두 뜨게 되는 것이고,

라우트에 따라서 <Outlet />에 들어가는 코드가 달라지게 되는 것입니다.

 

${}로 정의된 파일은 다이나믹 라우팅에 해당하는 페이지로, useParams 훅을 통해 파라미터를 가져올 수 있습니다.

 

간편한 Server side 데이터 로딩

도 매우 편리한 기능이었습니다.

 

리믹스에서 제공하는 LoaderFunction을 사용하면 쉽게 서버사이드에서 데이터를 로딩할 수 있습니다.

그리고 해당 데이터는 해당 라우트 및 해당 라우트에서 사용되는 컴포넌트 내에서 useLoaderData 훅을 사용하여 패칭 할 수 있습니다.

 

해당 로직을 추가하여 코드를 새로 작성해보도록 하죠.

// routes/index.tsx
import { LoaderFunction, useLoaderData } from "remix";

export const loader: LoaderFunction = () => {
  return { data: "index loader" };
};

export default () => {
  const data = useLoaderData();
  return (
    <div>
      index.tsx <div>data:{data.data}</div>
    </div>
  );
};

// routes/blog.tsx
import { LoaderFunction, Outlet, useLoaderData, useParams } from "remix";

export const loader: LoaderFunction = () => {
  return { data: "blog loader" };
};

export default () => {
  const data = useLoaderData();
  return (
    <div>
      <div>blog</div>
      <div>data:{data.data}</div>
      <Outlet />
    </div>
  );
};

// routes/blog/index.tsx
import { LoaderFunction, useLoaderData, useParams } from "remix";
import { Comp } from "~/components/comp";

export const loader: LoaderFunction = () => {
  return { data: "blog/index loader" };
};

export default () => {
  const data = useLoaderData();

  return (
    <div>
      blog/index.tsx <div>data: {data}</div> <Comp />
    </div>
  );
};


// routes/blog/$id.tsx
import { useParams } from "remix";

export default () => {
  const { id } = useParams();
  return <div>blog/$id.tsx {id}</div>;
};

// components/Comp.tsx
import { useLoaderData } from "remix";

export const Comp = () => {
  const data = useLoaderData();
  return (
    <div>
      comp <div>data from router: {data.data}</div>
    </div>
  );
};

해당 코드에 대응되는 페이지들을 한 번 보도록 하죠.

 

루트에서는 index.tsx 에 정의된 loader에서 리턴하는 데이터를 훅으로 가져오는 것을 볼 수 있습니다.

/blog에서는 blog.tsx 와 blog/index.tsx 에 정의된 loader에서 리턴하는 데이터를 훅으로 가져오는 것을 볼 수 있고,

Comp 컴포넌트의 경우 라우터가 아니기 때문에 loader를 정의할 수는 없지만, 훅을 통해 데이터를 가져오는 것을 것을 볼 수 있습니다.

/blog/{id} 에서는 마찬가지로 blog.tsx 에 정의된 loader에서 리턴하는 데이터를 훅으로 가져오는 것을 볼 수 있습니다.

 

LoaderFunction 내부에서 ajax 호출을 하고, 해당 데이터를 컴포넌트에서 사용한다면 훨씬 더 좋은 사용자 경험을 제공할 수 있겠죠 :)

 

아직은 버그도 많고 탈도 많은 프레임워크지만, 강력한 기능들을 많이 제공하기에 기대가 됩니다 :)

(실제로 현재 리믹스로 프로젝트를 진행하고 있는데, 아직까지 큰 문제는 딱히 없습니다.)

새로운 프레임워크로 사이드를 진행해보고 싶다? 디자인 시안을 봤는데 nest 되는 뷰가 많다? 하시면 리믹스를 써보는 것도 좋을 것 같습니다!

 

 

728x90