Search

Remix란?

리믹스(Remix.js)는 빠른 페이지 로딩속도와 좋은 사용자 경험(UX)을 제공하는 웹사이트를 만들 수 있도록 해주는 리액트(React) 기반의 SSR 프레임워크입니다. 같은 리액트 기반의 SSR 프레임워크인 Next.js가 리액트의 확장형 프레임워크 같은 느낌이라면 리믹스는 리액트를 화면 개발의 도구로 사용하긴 하지만 웹 표준 기술을 좀 더 중시하는 편입니다.
얼마전 구글에서 모바일 웹 페이지에 진입 했을 때 로딩 지연이 길어질 수록 사용자들이 웹 페이지를 이탈하는 확률이 증가하는 리포트를 공개 했었습니다. 그만큼 로딩이라는 것이 해당 웹의 첫인상에 매우 안좋은 영향을 끼친다는 것이죠. 실제로 어떤 웹 화면에 접속 했을 때, 스피너(Spinner)와 같은 로딩 아이콘이 자주 나타나거나 화면 이동에 버벅거림이 발생하면 사용할 때 매우 불편함을 느끼게 됩니다.
리서치 자료에 의하면 1초에서 3초 사이에 페이지 이탈이 32% 증가하고 1초에서 10초 사이일 때 페이지 이탈이 최대 123%가 증가하는 것으로 나타났습니다.
웹의 좋은 사용자 경험(UX)에 있어서 첫번째가 되는 것이 바로 화면 로딩 속도라는 것이죠. 그리고 페이지 로딩 이후에 react-queryuseEffect()를 사용한 데이터 fetch를 통해 단계적으로 페이지를 완성하는 것도 그다지 좋은 느낌을 주지는 못합니다.

로딩 아이콘이나 스피너 사용은 이제 안녕

실제 리믹스 홈페이지 로딩 관련 소개에 나오는 스크롤 이펙트입니다.  인상 깊어서 캡쳐해서 올려봅니다.
웹 개발을 할 때 화면 마운트 이후에 비동기 통신으로 데이터를 가져오고 로딩하는 동안 화면에 스피너를 보여주는 식의 처리를 100% 완전하게 배제할 수는 없을 겁니다. 최근 블록체인 기반의 Web3 웹앱처럼 클라이언트 사이드에서 사용자가 직접 데이터를 관리하고 처리하는 경우는 어쩔 수 없이 로딩이 발생하기 때문에 스피너와 같은 UI를 화면에 보여줘서 로딩 중이라는 상태를 사용자에게 전달해야만 하죠.
하지만 화면 구성에 필요한 데이터를 서버 렌더링 단계에서 미리 준비할 수 있다면 사용자가 화면에서 2차적으로 데이터를 로드하는 것을 기다리는 일을 최대한 피하도록 할 수 있습니다. 리믹스의 loader()와 같은 기능을 사용하면 서버에서 랜더링 이전에 필요한 데이터를 미리 가져와 서버 사이드 랜더링(SSR) 단계에서 전체 화면을 모두 랜더링해 사용자에게 페이지를 접속했을 때 온전한 화면을 바로 볼 수 있도록 할 수 있죠.
리믹스는 서버 사이드에서 랜더링을 모두 마친 뒤 사용자(클라이언트)에게 보내므로 사용자의 브라우저에서는 HTML과 CSS와 같은 document 파일만 다운로드되면 온전한 화면을 바로 볼 수 있게 됩니다. 이미지 출저: 리믹스 홈페이지, https://remix.run/
리믹스는 또한 한 페이지가 로드되면 그 페이지에서 넘어갈 수 있는 다른 페이지 렌더링에 필요한 파일들을 미리 prefetch 해 둡니다. 이렇게 다음 페이지 파일을 미리 로드해두면, 유저가 어떤 경로로 페이지 이동을 하더라도 SPA에서 화면 이동 하듯이 즉각적인 화면 이동을 할 수 있게 됩니다.

 form 태그가 뭐였지? 리믹스에서는 적극 사용

리액트로 웹 개발을 하다보면 입력 양식 처리를 <form> 태그 양식을 사용하지 않고 그냥 <input> 요소들을 <div> 태그로 감싸서 onChange, onClick 이벤트 핸들링만으로 처리할 때가 있습니다. 전통적으로 웹이 처리하던 방식인 <form> 태그를 활용하려면 FormData를 다루고 submit 이벤트를 핸들링 해야하는 번거로움이 있기 때문인데요. 리믹스는 웹 표준 기술을 중시하기 때문에 원래부터 브라우저에서 입력 양식 처리에 사용되는 <form> 태그의 기능을 적극 활용하도록 디자인 되어 있습니다.
리믹스에서는 네이티브 <form> 태그를 래핑한 추가적인 기능을 갖추고 있는 <Form> 컴포넌트와 FormData 사용과 submit 이벤트 핸들링을 쉽게 하도록 하는 useFetcher() 훅을 제공합니다. 이 두가지 만으로도 fetch() 함수나 다른 라이브러리 없이 빠르면서 간결한 입력 양식 처리가 가능해 집니다.
위 두가지와 더불어 요청 받은 데이터 처리를 정의하는 action() 기능을 사용하면 아래 코드처럼 한 파일에서 화면 입력 폼 양식 코드와 서버 데이터 등록 처리코드가 함께 존재하는 풀스택 코드를 작성할 수 있게 됩니다.
import { action, Form } from "@remix-run/react"; // 받은 POST 요청을 처리하는 action 코드 export const action = async ({ request }: ActionArgs) => { const formData = await request.formData(); const todo = await createTodo(formData); return redirect(`/todo/${todo.id}`); }; // 양식을 작성해 POST 요청으로 submit하는 form 컴포넌트 export const CreateTodo = () => { return ( <Form method="post"> <input type="text" name="todo" /> <button type="submit">Todo 생성</button> </Form> ); };
TypeScript
복사
리믹스는 클라이언트 코드와 서버 코드를 함께 작성 할 수 있습니다. 빌드 타임때에 코드가 클라이언트 용과 서버 용으로 각각 분리됩니다. (파일명에 .server, .client를 붙여서 서버용, 클라이언트용을 마킹하여 전용으로 사용하는 것도 가능합니다.)

Nested Routes

리믹스는 react-router와 동일한 개발진이 개발한 프레임워크이고 내부적으로 react-router를 라우터 모듈로 사용하고 있습니다. 따라서 react-router에서 사용되는 중첩 라우트(Nested Routes)를 리믹스에서도 사용합니다.
Nested Routes란 중첩된 라우트로 화면을 계층화시켜 공통된 레이아웃을 사용하는 리믹스의 라우팅 시스템입니다. Nested Routes를 활용하면 공통된 UI를 레이아웃으로 페이지마다 공유해 사용할 수 있어 중복된 UI 코드 개발을 피하고 보다 효율적으로 화면 개발을 할 수 있게 됩니다. 이에 대한 자세한 내용은 따로 정리한 중첩 라우트(Nested Routes) 포스트에서 확인하세요.
중첩 라우트를 활용하면 중첩 구조로 공통 컴포넌트를 레이아웃으로 공유해 중복된 UI 코드를 줄이고 같은 레이아웃을 공유하는 페이지간 이동 시 화면 로드 속도가 빨라지게 됩니다.

create-remix로 간편하게 프로젝트 시작

create-remix를 사용해서 간편하게 리믹스 프로젝트를 설치할 수 있습니다. 설치할 경로에서 아래 커맨드를 입력하면 create-react-app을 사용하는 것처럼 자동으로 설치됩니다.
npx create-remix@latest
Bash
복사
remix.guide에 미리 만들어져 있는 템플릿으로 프로젝트를 시작하는 것도 가능합니다. 아래 코드처럼 —template 옵션과 가져올 탬플릿 경로를 같이 입력하면 됩니다. github에 있는 탬플릿의 경우 <유저이름>/<저장소이름> 과 같은 식으로 탬플릿 경로를 지정해야 합니다.
npx create-remix@latest --template <templateUrl>
Bash
복사
예를 들면 제 github에 올려놓은 remix-starter 탬플릿으로 시작하려면 아래 커맨드로 입력하는 식입니다.
npx create-remix@latest --template crispy43/remix-starter
Bash
복사
리믹스는 SSR 웹을 구현하기에 심플하면서 강력한 기능들이 많아 빠르면서 쾌적한 웹사이트를 간편하게 구축할 수 있다는 장점이 있습니다. 리액트 기반의 프레임워크이므로 리액트 생태계에서 사용되는 대부분의 라이브러리는 리믹스에서도 사용 가능합니다. 리액트 스타일링에 사용되는 styled-component와 같은 CSS-in-JS 라이브러리는 SSR 프레임워크에 적용할 때 추가적인 세팅이 필요한 경우가 대부분인데요. 대부분 Next.js와 같이 별도의 설치 튜토리얼이 함께 존재합니다.
데이터 통신 처리에 그동한 익숙했던 axios, fetch 함수와 json 포멧을 활용하는 것 대신, formData 포멧과 브라우저의 기본 메소드로 데이터 통신 처리하는 것이 처음엔 난해하다고 느껴질 수 있으나, 이는 원래부터 브라우저에서 데이터 요청을 처리하는 웹 표준 방식입니다. 익숙해지면 이렇게 처리하는 것이 꽤나 매력적으로 느껴지기도 합니다. 물론 fetch 함수나 json 포멧의 사용을 제한하는 것이 아니기 때문에 함께 사용할 수 있습니다.
최근 리믹스에서 V2 컨벤션을 공개 했는데요. 여러가지 개선점을 비롯해 V1에 비교해 사용 법이 바뀐 것들이 있습니다. 현재 신규 리믹스 프로젝트를 설치하면 V2가 기본 컨벤션 으로 적용되어 있습니다. 제 블로그에서 리믹스 관련 포스팅은 이 V2 컨벤션을 기준으로 작성됩니다!

 중첩 라우트(Nested routes)

Remix 목록