[SWR] SWR VS NoSWR 코드 비교

With·2021년 10월 10일
0

SWR

목록 보기
3/4
post-thumbnail

개인 학습용 기록입니다. 틀린 부분이 있을 수 있습니다! 혹시 있다면 댓글 부탁드립니다. 🙇‍♂️

SWR를 사용하지 않은 경우

const todos: NextPage = () => {
  const [todos, setTodos] = useState<TypeTodo[]>(null);
  const [isLoading, setIsLoading] = useState<boolean>(false);

  const fetchTodos = async () => {
    try {
      setIsLoading(true);
      const { data } = await todoApi.loadTodos();
      setTodos(data);
      setIsLoading(false);
    } catch (e) {
      console.log(e);
      setIsLoading(false);
    }
  };

  useEffect(() => {
    fetchTodos();
  }, []);

  if (isLoading) return <div>로딩 중!</div>;
  return (
    <div>
      {todos &&
        todos.slice(0, 20).map((todo) => (
          <Link href={`/todos/${todo.id}`} key={todo.id}>
            <a>
              <TodoRow>{todo.title}</TodoRow>
            </a>
          </Link>
        ))}
    </div>
  );
};

export default todos;

SWR를 사용하지 않은 경우, react hook을 이용해서 상태를 관리했다. useEffect를 이용해서 컴포넌트가 mount될 때 fetchTodos()를 실행하게 했으며, useState를 이용해서 값을 할당했다.

또한, data가 fetch하는 상태를 관리하기 위해 isLoading 이라는 상태를 또 하나 만들었으며, 로딩상태에 따라 early return 문을 통해 error를 방지했다.

reduxcontext api등과 같은 전역 상태관리가 적용됐다면 코드가 달라질수도 있겠지만 비동기 처리 로직의 위치가 다른 곳으로 바뀌는 것일뿐 아마 일반적인 과정은 위와 같을 것 같다.

SWR를 사용하는 경우

const todos: NextPage = () => {
  const fetcher = async (url: string) => {
    const { data } = await todoApi.loadTodos(url);
    return data;
  };
  const { data: todos, error } = useSWR<TypeTodo[]>("/todos", fetcher);
  
  if (!todos) return <div>로딩 중!</div>;
  return (
    <div>
      {todos &&
        todos.slice(0, 20).map((todo) => (
          <Link href={`/todos/${todo.id}`} key={todo.id}>
            <a>
              <TodoRow>{todo.title}</TodoRow>
            </a>
          </Link>
        ))}
    </div>
  );
};

export default todos;

SWR를 사용하면, 일단 useStateuseEffect가 사라진다. useSWR는 컴포넌트가 mount될 때 실행되기 때문에 useEffect가 필요없다. 또한 이것을 굳이 어떤 값에 할당하지 않아도 되며, !data를 통해 loading 상태를 유추 할 수 있다.

만약 data : todos 라는 값을 다른 컴포넌트에서 사용하고자 한다면, 즉 전역으로 관리하고 싶다면 그 컴포넌트에서도 useSWR("/todos", fetcher) 를 하면 된다.

그렇게 하면 API 요청을 중복으로 하게 되잖아요?

SWR은 중복으로 요청안하고 1번만 한다. 아마 이게 SWR의 진가가 아닐까 생각한다. end-point를 기준으로 동일한 요청이 있다면 최초에 한번만 요청을 보내고, 이후에는 캐싱해 놓은 결과값을 사용하여 클라이언트에 보여준다. 즉, useSWR을 여러 개의 컴포넌트에서 아무리 작동시켜도 end-point만 같다면 1번만 요청을 보낸다. 이러한 원리로 redux의 대체자 라고 불리고 있는 것 같다.

로컬에서만 관리하든, 전역으로 관리하든 코드가 줄고 리덕스보다 쉽다. 물론 mutate 같은 것들이 더 추가 되어야 하지만 말이다.

profile
주니어 프론트엔드 개발자 입니다.

0개의 댓글