리코일을 사용한 이유: 한달 안에 기능 구현을 끝내야하는 부분에서 낮은 러닝커브와 적은 코드로 개발할 수 있어 채택
장소 정보 및 계정 정보를 가져왔음
웹이 발달하며 JS(리액트)로 DOM, CSS 등을 관리하기 시작하면서 우리는 더욱 효율적으로 만드는 방법을 강구해왔다. 그러면서 가장 크게 대두되는 방법론 하나가 있는데 바로 조립식으로 개발하는 CDD 방식이다.
컴포넌트를 모듈 단위로 개발하여 사용자 인터페이스(UI) 구축에 도달하는 개발 및 설계 방법론
그래서 리액트는 컴포넌트, 페이지 별로 각각 만들고 조립식으로 만들 수 있는 JS 라이브러리라고 할 수 있다.
한페이지에 여러개의 컴포넌트, 즉 분리된 파일들이 생기면서 문제가 생긴다. 어떤 문제냐면 리액트는 상태, State
라는 특유의 변수를 사용한다. 이 상태를 정의(set)하면 그 파일(컴포넌트)에서 쓸 수 있는 거시다.
하지만 이 컴포넌트 말고도 다른 컴포넌트에서 사용하고 싶다면? Props
라는 리액트만의 파라미터로 전해줘서 그 컴포넌트에서 쓸 수 있다. 단방향이 원칙이라 자식 컴포넌트에게만 전해줄 수 있고, 그 상태가 바뀌면 리렌더링이 된다.
여기서 Props Drilling
이 나오는데 Props
를 오로지 하위 컴포넌트로 전달하는 용도로만 쓰이는 컴포넌트들을 거치면서 React Component 트리의 한 부분에서 다른 부분으로 데이터를 전달하는 과정이다. 아래 사진 참고
이 Props Drilling
이 일어나도 된다. 대신 3개가 훨씬 넘어간다거나 단방향 원칙을 어긴 '상태 끌어올리기'같은 게 여러개가 중첩된다면? 구조가 한눈에 들어오질 않아 관리/보수가 힘들어질 것이다.
상태가 바뀌면 리렌더링되는데 상태를 사용하지 않는 많은 컴포넌트들까지 리렌더링된다면? 렉이 걸린다든지 성능에 문제가 생길 것이다.
이걸 Props Drilling Issue
라고 한다.
이러한 이슈들을 없애기 위해 상태관리 라이브러리를 쓰는 것이다!
다양한 라이브러리들이 있다. Redux
, Recoil
, Zustand
, Mobx
, Context API
등이 있다. 여기서 메인에서는 Recoil
을 사용하기로 했다.
리덕스와 비교했을때 낮은 러닝커브와 적은 코드 양
러닝 커브가 낮다는 얘기는 그만큼 코드의 품질이 사람마다 차이가 나지 않는다는 얘기여서 팀 프로젝트 특성상 코드를 알아보기 쉬워야하기 때문이었고, 코드의 양도 보일러 플레이트의 대명사 리덕스에 비해 많이 적기 때문에 골랐다.
리액트같은 직관적인 라이브러리
useRecoilState
같은 메소드를 사용하기때문에 useState
랑 비슷해 직관적인 사용이 가능
사용 빈도 수 증가
공고를 보니 리코일을 사용하는 회사도 은근 보였다. 저번엔 리덕스를 배워봤기때문에 리코일도 해봐야겠다 생각해서 사용했다.
이러한 이유로 사용하려고 마음 먹었다.
1부터 10까지의 사용법에 대한 건 검색을 해보시길,, 권한다,, 나도 전역 상태인 Atoms
까지만 써봤기때문에 그렇게 깊진 않다.
리덕스처럼 루트에 리코일 관련 상태를 씌워줘야한다.
<RecoilRoot>
<AppContainer toggle={visible}>
<Sidebar />
<div className={`feed_container_${visible ? "hidden" : ""}`}>
<Header />
<Routes>
...
</Routes>
</div>
<HeaderFeedHide visible={visible} setVisibility={setVisibility} />
<KakaoMap />
</AppContainer>
</RecoilRoot>
우리 프로젝트에선 이렇게 썼다. RecoilRoot
를 씌워서 적용시켜줬다.
아톰은 비눗방울이라 생각하면 되는데 리덕스는 store, 리코일은 atom에 넣어서 변수를 선언한다음 사진처럼 떠있다가 쓴다고 호출하면 호출되어지는 구조이다.
아톰에는 우리가 원하는 state를 넣으면 된다. 말그대로 useState
같이 초기 상태를 아톰에 선언해준다.
// store/searchPlaceAtoms.ts
import { atom } from "recoil";
export const searchResultsState = atom({
key: "searchResultsState",
default: [],
});
// searchStatusState는 검색 후 데이터가 오는지 안오는지의 기준을 세운 아톰
// "Loading", "Success", "Error" 3개가 들어감
export const searchStatusState = atom({
key: "searchStatusState",
default: "Idle",
});
이렇게 말이다. key
는 아톰 이름, const 뒤 변수 이름은 컴포넌트에 호출하고 싶을 때 가져와서 선언할 수 있는 거시다. default
는 초기값이다.
이제 선언 했으니 전역 상태를 사용해보자!
import { useRecoilState } from "recoil";
import { counting } from "./store";
export function Example() {
const [count, setCount] = useRecoilState(counting);
const handleIncrease = () => {
setCount((prev) => prev + 1);
}
return (
<div>
<span>{count}</span>
<button onClick={handleIncrease}>increase</button>
</div>
);
}
useRecoilState
, 아톰을 import
해와서 use 훅처럼 쓰면 된다. 이 얼마나 혁신적인가;; 완전 리액트같은 라이브러리다.
searchResultsState
를 사용한 곳은 저번에 기술했다.
검색 마커 페이지를 만들며 마커를 찍기 위해 검색 결과를 전역으로 선언하고 싶어서였다.
사용한 걸 요약하자면
useAxios
를 통해 네트워크 통신하여 Get해오기searchResultsState
에 set한다.searchResultsState
를 카카오맵 관련 컴포넌트에 호출한다.이런 식으로 했다. 카카오맵 - 검색 페이지 사이 자식, 부모컴포넌트가 많기도 많고 입력한 키워드를 전달하려면 상태 끌어올리기도 써야하고 왔다 갔다를 많이 했을 것이다. 또 이것만 쓰는 게 아니라 주변 검색 기능도 있으니까 상태를 한곳에 몰고 관리하는 것이 더 편했다.
그래서 리코일을 쓴 게 되게 좋았다. 쓰길 잘했다!
상태관리 라이브러리는 편하다! 너무 좋아!
근데 리코일의 기능 중 Atoms
만 썼고, Selector
같은 거나 비동기 함수 사용은 useAxios
로 다 관리했기 때문에 못썼다. 나중에 꼭 써보고 그런 편함을 알고 싶다. React-Query
도 같이 쓰는 경우도 많아서 꼭 나중에 써보겠다. 참고: 리코일+리액트쿼리 고수
또 Zustand
도 많이 쓰긴 쓰더라잘 안쓰는 줄 알았더니 npm trends를 봤는데 은근 많이 써서 놀랐다. 꼭 써봐야지
항상 왜 쓰는지, 써서 무엇을 얻었는지 항상 알자!
리코일 사용기 너무 좋네요! 저도 프리 때 주스탠드를 사용했는데 진짜 간편하더라구요!! 확실히 좋은 상태관리 라이브러리들이 많이 나오는 거 같아여~ 저도 리덕스를 시작으로 다 써보려고 준비중인데 친절하고 깔끔한 설명 감사합니다 공부할 때 참고할게요 ㅎㅎ 잘 보고 가요!