본문 바로가기

프론트엔드/ReactJS

useEffect와 생명주기 (0) - 주절주절

다음 글 : useEffect와 생명주기 (1) - 클래스형 컴포넌트의 state와 lifecycle

 

항상 글을 시작하는 건 어렵네요. 공부한 내용을 정리하는 것도..

 

https://github.com/VoiceSpaceUnder5/VoiceSpace

 

GitHub - VoiceSpaceUnder5/VoiceSpace: 피로감은 덜하지만, 더욱 현실감 있는 음성채팅을 위한 프로젝트

피로감은 덜하지만, 더욱 현실감 있는 음성채팅을 위한 프로젝트. Contribute to VoiceSpaceUnder5/VoiceSpace development by creating an account on GitHub.

github.com

 

주절주절

7월 초에 공개SW 개발자대회에 참가하기로 결정하고, 웹 기반 음성채팅 서비스를 구현하면서 처음으로 리액트를 만지게 됐습니다. 어찌어찌 대회를 마무리하고 운좋게 수상을 했지만, 너무너무 부끄럽게도 리액트의 ㄹ자도 모르는 상태라고 할 수 있습니다. 

 

처음 리액트를 접하고, C에서와 달리 코드가 순서대로 진행되지 않는다는 느낌에 굉장히 답답했습니다. 자바스크립트의 기본에 대한 학습도 잘 되어있지 않았고, 리액트 생명주기도 '아 이걸 언제 이해해' + '동작만 하게 만들고 넘어가자'라는 생각에 제대로 이해하지 않고 넘어갔습니다.

 

대회가 끝났고(무려 한 달 전에), 42서울 마지막 과제를 진행하면서 다시 한번 (시간에 그나마 덜 쫓기며) 공부할 기회가 생겼습니다. 그래서 벨로퍼트와 함께하는 모던 리액트를 차근차근 따라하면서 개념을 보충하는 중이지만, 습관이란 게 참 무섭습니다. 예제 코드를 그대로 따라하면서 그게 동작을 하면, '이게 왜 되지?'하고 이해하려고 하는 게 아니라 '그렇구나..'하고 넘어가게 되더군요.

 

그러다가 API 연동의 기본챕터에서 다음 코드를 보고 갑자기 모든 게 이상하게 느껴졌고, 이번에 이해하지 않고 넘어가면 안 되겠다는 생각이 들었습니다.

import React, { useState, useEffect } from 'react';
import axios from 'axios';

function Users() {
  const [users, setUsers] = useState(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);

  useEffect(() => {
    const fetchUsers = async () => {
      try {
        // 요청이 시작 할 때에는 error 와 users 를 초기화하고
        setError(null);
        setUsers(null);
        // loading 상태를 true 로 바꿉니다.
        setLoading(true);
        const response = await axios.get(
          'https://jsonplaceholder.typicode.com/users'
        );
        setUsers(response.data); // 데이터는 response.data 안에 들어있습니다.
      } catch (e) {
        setError(e);
      }
      setLoading(false);
    };

    fetchUsers();
  }, []);

  if (loading) return <div>로딩중..</div>;
  if (error) return <div>에러가 발생했습니다</div>;
  if (!users) return null;
  return (
    <ul>
      {users.map(user => (
        <li key={user.id}>
          {user.username} ({user.name})
        </li>
      ))}
    </ul>
  );
}

export default Users;

왜 처음엔 로딩중..이 출력되다가 왜 금방 유저 목록이 출력되지? useEffect는 대체 언제 실행되는 거지? setState가 실행되면 대체 Users의 어떤 부분이 다시 실행되는 거지?와 같은, 제 나름대로는 심오한 질문이지만 겉으로 꺼내면 너무 허접해서 부끄러운 궁금증들이 마구마구 떠올랐습니다.

 

지금까지는, 'useEffect의 dependency가 비어있으면 컴포넌트가 처음 마운트 됐을 때만 콜백함수가 실행되고, dependency에 무엇인가가 있으면 dependency가 변할 때 콜백함수가 실행된다'라는 정도만 알고 useEffect를 사용해왔습니다. useState는 'state가 변하면 컴포넌트가 리렌더링된다'라는 정도만 알고 사용해왔습니다.

 

사실 저 두 문장 중에서도 마운트가 무엇인지도 모르고, 대체 컴포넌트의 어느 부분이 리렌더링되는 건지도 잘 몰랐습니다. 근본적으로는 생명주기도 모르고, 리액트가 어떤 식으로 DOM에 접근하는 것인지도 잘 모른다는 것입니다. 사실 제가 이걸 모른다고 하는 게 맞는지도 모르겠습니다. 글을 쓰면 쓸수록 아무것도 모르는 것 같습니다.

 

말을 할수록 밑천이 드러나는 게 느껴지고, 얼굴이 화끈화끈하네요. 이만 주절주절은 급하게 마무리하고, 모르는 부분을 차근차근 정리해나가야겠습니다. 시간이 지난 뒤 다시 이 글을 볼 때 '그땐 그랬지'하길 바라면서..!

 

다음 글 : useEffect와 생명주기 (1) - 클래스형 컴포넌트의 state와 lifecycle