[MGS 3기 - 29일차] React 라이브러리 (2)

박철연·2022년 5월 23일
0

MGS STFE 3기

목록 보기
26/35

저번 시간에 이어 이번 정리글에서도 다양한 React 라이브러리들에 대해 학습 내용을 요약해 보았습니다.

데이터 모킹 라이브러리

데이터 모킹 라이브러리란?

현업에서나, 프론트엔드를 학습하는 단계에서나 데이터를 페칭해오는 과정은 대단히 빈번하게 마주하게 되는 영역입니다.

데이터 페칭을 해야하는 경우 통신을 통해 응답을 내려주는 서버가 구축되어 있어야 합니다.

하지만 완전하게 서버가 구축되지 않은 단계에서는, 프론트엔드 개발자들은 API 호출과 관련된 테스팅을 진행하기 위해서 API의 레플리카를 만들어서 데이터 페칭을 테스트하게 됩니다.

바로 이 API의 레플리카를 만드는 것이 데이터 모킹이라고 칭합니다. 데이터 모킹은 대단히 복잡한 작업입니다. 이를 도와주는 것이 바로 데이터 모킹 라이브러리입니다.

학습 내용을 고려해서, 이번 글에서는 Mock Service Worker에 대해서만 파악하고 갈 생각입니다.

Mock Service Worker

(글에서는 편의를 위해 MSW라고 칭하겠습니다.)

MSW(Mock Service Worker)는 서비스 워커(Service Worker)를 사용해 네트워크 호출을 모방하는 API 모킹(mocking) 라이브러리입니다.

쉽게 말해, 브라우저를 기반으로 백앤드 API를 모방해 프런트엔드 단의 요청에 가짜 데이터를 응답해주는 라이브러리라고 할 수 있습니다.

비교적에 최근에 도입된 웹 표준 기술인 서비스 워커를 사용하면 브라우저로 부터 나가는 요청이나 들어오는 응답을 중간에서 감시하거나 변조, 캐싱과 같은 기존에 웹에서 할 수 없었던 부가적인 작업들을 할 수 있습니다.

MSW는 이러한 서비스 워커의 능력을 활용하여 데이터 모킹을 도와주는 강력한 라이브러리로 부상했습니다.

MSW는 백엔드 API 개발과 프론트엔드 개발이 동시에 진행되어서 백엔드 구현 전까지 임시로 사용할 가짜 API가 필요할 때 매우 유용합니다.

뿐만 아니라, 프론트엔드 테스트를 진행할 때 실제 백엔드 API에 호출을 보내는 대신 더 빠르고 안정적인 API를 잠시 사용할 때에도 사용됩니다.

MSW의 특징

기존 API 모킹 라이브러리 대비 MSW의 가장 중요한 장점은 데이터 모킹이 네트워크 단에서 일어나기 때문에 프런트엔드의 코드를 실제 백앤드 API와 네트워크 통신하는 것과 크게 다르지 않게 작성할 수 있다는 것입니다.

즉, 나중에 가짜 API를 실제 API로 대체하는 것이 쉽고 그만큼 프런트엔드 프로젝트의 개발 생산성이 올라가는 결과로 이어지게 됩니다.

또한 라이브러리가 상당히 유연하게 디자인이 되어 있어서 개발용으로 브라우저 환경에서 서비스 워커로 실행하든, 테스트용으로 Node.js 환경에서 Jest나 Cypress와 같은 테스트 러너(runner)로 돌리든 동일한 요청 핸들러 코드를 공유해서 사용할 수 있다는 것입니다.

따라서 API 모킹을 위해서 작성해야하는 코드를 최소화 할 수 있기 때문에 이미 언급한 개발 생산성 뿐만 아니라 유지 보수성 측면에서도 긍정적인 효과를 가져오게 됩니다.

뿐만 아니라, REST API 모킹과 GraphQL API 모킹을 모두 지원한다는 점도 유용하게 작용합니다.

단점이라고 한다면, 인터넷 익스플로러와 같이 서비스 워커를 지원하지 않는 구식 브라우저에서는 동작하지 않는다는 점을 꼽을 수 있겠습니다.

MSW 설치 및 사용법

MSW 설치

다음의 명령어를 터미널에 입력해 설치를 진행할 수 있습니다.

$ npm i -D msw

서비스 워커 등록

MSW는 브라우저에서 서비스 워커를 통해서 작동하기 때문에 서비스 워커 등록을 위한 기본적인 코드가 필요합니다. MSW에서 제공하는 CLI 도구를 사용하면 이 코드를 쉽게 만들어 낼 수 있습니다.

$ npx msw init public/ --save

public 부분에는 프로젝트에서 정적 리소스를 두는 폴더를 지정해주게 됩니다. Create React App, NextJS, VueJS, Svelte.js, Vite 등 많은 라이브러리/프레임워크에서는 프로젝트 구성 단계에서 이미 public 폴더를 제공하는데, 이를 그대로 사용해도 무방합니다.

요청 핸들러 작성

여기까지 진행을 했다면, 그 다음에는 API를 구현하려면 요청이 들어왔을 때 임의의 응답을 해주는 핸들러(handler) 코드를 작성해야합니다.

import { rest } from "msw";

const todos = ["먹기", "자기", "놀기"];

export const handlers = [
  // 할일 목록
  rest.get("/todos", (req, res, ctx) => {
    return res(ctx.status(200), ctx.json(todos));
  }),

  // 할일 추가
  rest.post("/todos", (req, res, ctx) => {
    todos.push(req.body);
    return res(ctx.status(201));
  })
];

모킹 관련 코드를 프로젝트의 아무데나 상관해도 상관은 없으나 mocks이라는 디렉토리에 두는 것이 일반적인 컨벤션입니다.

할일 목록을 조회하가 위한 GET /todos 엔드포인트는 배열에 담긴 3개의 할일을 응답해주고, 새로운 할일을 추가하기 위한 POST /todos 엔드포인트는 요청 바디로 넘어온 할일을 배열에 추가합니다.

서비스 워커 생성

다음으로 msw 모듈에서 제공하는 setupWorker() 함수를 사용해서 서비스 워커를 생성하겠습니다. 위에서 작성한 요청 핸들러 코드를 불러와서 그대로 setupWorker() 함수의 인자로 넘겨주면 됩니다.

import { setupWorker } from "msw";
import { handlers } from "./handlers";

export const worker = setupWorker(...handlers);

서비스 워커 삽입

마지막으로 서비스 워커를 구동하는 코드를 프로젝트의 엔트리 포인트에 삽입을 해야 합니다. 예를 들어, Create React App으로 만든 애플리케이션의 경우, src/index.js 파일을 다음과 같이 수정해주면 됩니다.

import { StrictMode } from "react";
import { createRoot } from "react-dom/client";

import App from "./App";
import { worker } from "./mocks/worker";
if (process.env.NODE_ENV === "development") {
  worker.start();
}

const rootElement = document.getElementById("root");
const root = createRoot(rootElement);

root.render(
  <StrictMode>
    <App />
  </StrictMode>
);

상태 관리 라이브러리

상태 관리 라이브러리의 필요성

이미 리액트 기본 개념들을 학습하면서, 컴포넌트 간에 state를 넘기기 위해서는 props 문법을 사용해야 한다는 것은 확인했습니다.

props 문법은 컴포넌트의 재사용성을 살려주고, state 의존성을 관리한다는 측면이 있지만, 그렇다고 복잡한 프로젝트에서 정직하게 사용하기에는 쉽지 않습니다.

실제 프로젝트에서는 컴포넌트들간의 종속 관계가 매우 복잡하기 때문에, props로 state를 넘겨줄 때 지나치게 많은 props drilling이 발생합니다.

이를 해결하기 위해, state를 props 문법없이 효과적으로 등장한 것이 다양한 상태 관리 라이브러리들입니다. Redux, MobX, Zustand, Recoil 등 여러 종류의 상태 관리 라이브러리들이 존재합니다.

이번 항목에서는 그 중 Redux와 MobX에 대해 살펴보겠습니다.

Redux

리액트를 개발한 페이스북에서는 기존의 MVC 아키텍쳐로 이루어진 프로젝트들이 복잡해질 수록 관리가 힘들어진다는 점을 인지했습니다.

그 결과, 페이스북에서는 Flux 아키텍쳐를 고안하게 됩니다.

store라고 하는, 상태나 데이터를 보관할 수 있는 저장소를 만들고, 이 store의 관리를 담당하는 dispatcher를 action을 통해 조작하는 식입니다.

이러면 MVC 아키텍쳐 때와는 다르게, 데이터와 상태가 한 곳에 정리되어 있기 때문에, 복잡한 형태의 데이터 흐름이 사라지고 일방향의 흐름이 가능해집니다.

이를 라이브러리의 형태로 구체화한것이 바로 Redux입니다.

Redux와 같은 Flux 아키텍처의 라이브러리의 경우, store에 모든 상태를 저장하는 중앙집중방식입니다. 이 store는 외부 요소이기 때문에 리액트의 내부 스케줄러에 접근할 수가 없습니다.

또한 Redux의 경우 비동기 데이터 처리를 하기 위해서는 사가와 같은 별도의 라이브러리를 추가적으로 사용해야 합니다.

Redux는 바로 위에서 언급한 것과 같이 데이터 관리에 대해 상당히 보수적인 접근방식을 취하고 있는데, 이는 높은 러닝커브와 큰 보일러플레이트 코드를 낳지만 확장 및 디버깅에 있어서는 대단히 용이하게 작용합니다.

여담으로, Redux는 React에 귀속된 라이브러리가 아닙니다. 따라서 바닐라 자바스크립트로 작성한 프로젝트나, Vue, Angular 등 다른 프레임워크와도 충분히 쓸 수 있습니다.

MobX

MobX의 경우 Redux와 달리 immutablity에는 신경써주지 않아도 될 정도로 규칙만 잘 신경써준다면 최적화가 잘 됩니다.

단적으로 설명하자면, MobX는 여러 면에서 Redux보다는 다루기가 쉬운 라이브러리인데, 그로 인한 단점들도 존재합니다.

MobX의 경우 Redux와 달리 store가 여러 개가 될 수 있습니다. 이는 분리가 용이해 상태 관리가 쉬워지는 측면이 있는 동시에, 상태를 변경할 때 다수의 스토어가 영향을 받을 수 있기 때문에 주의를 요해야 합니다.

Redux와 다르게 스토어의 데이터를 액션을 발행하지 않고도 업데이트할 수 있습니다. 이는 구현은 쉽고 용이하지만 테스트나 유지보수의 측면에서는 문제를 일으킬 수도 있습니다.

그렇기에 장기적인 프로젝트, 유지보수 및 확장성을 고려해야 하는 프로젝트의 경우에는 일반적으로 MobX보다 Redux가 더 좋은 선택일 수 있습니다.

하지만 Redux보다 러닝커브가 낮고 보일러플레이트 코드의 양 또한 적기 때문에 프로젝트의 규모가 크지 않다면 MobX를 사용하는 것이 더 효율적일 수 있습니다.

profile
Frontend Developer

0개의 댓글