노트

부수 효과와 Effect

Side Effects and Effects

프런트엔드#react · 연결된 개념 11개

쉽게 말하면

부수 효과는 함수가 답을 계산하는 본업 말고 바깥 세상을 건드리는 일이에요. 계산기가 답을 내면서 몰래 문자까지 보내면 그게 부수 효과죠. React의 Effect는 그중 화면이 그려진 뒤 바깥과 맞추는 일만 가리켜요.

비유가 깨지는 곳 모든 부수 효과를 Effect에 넣는 건 아니에요. 버튼 클릭처럼 사용자 행동 때문에 생기는 일은 이벤트 핸들러에 두고, 화면에 보였기 때문에 외부와 맞춰야 하는 일만 Effect로 처리해요.

부수 효과(Side Effect)는 함수가 값을 계산해 돌려주는 본업 외에 바깥 세계를 건드리는 모든 동작이다. React의 Effect(useEffect로 감싼 코드)는 그중에서도 렌더가 끝난 뒤 외부 시스템과 맞추려고 실행하는 부수 효과만 가리키는 좁은 이름이다. 즉 Effect는 부수 효과의 부분집합이다.

  • 부수 효과의 예: DOM(Document Object Model) 직접 수정, document.title 변경, 네트워크 요청, localStorage 쓰기, 타이머, 이벤트 구독, 함수 밖 변수 수정, 로그 출력
  • 컴포넌트의 본업은 JSX(JavaScript XML)를 계산해 반환하는 것뿐이고, 렌더 중에 부수 효과를 내면 안 된다(React의 규칙과 렌더 순수성)
  • 부수 효과를 둘 곳은 두 군데다
    • 사용자 행동 때문에 일어나는 일: 이벤트 핸들러(메시지 전송 버튼)
    • 화면에 보였기 때문에 외부와 맞춰야 하는 일: Effect(채팅 서버 연결, 정리 함수로 해제)
useEffect(() => {
  const conn = createConnection(roomId)   // 외부 시스템과 동기화
  conn.connect()
  return () => conn.disconnect()          // 정리
}, [roomId])

서버 컴포넌트는 왜 렌더 중에 데이터를 가져와도 되나

렌더 중 부수 효과 금지는 클라이언트의 조건(재렌더, state, 렌더 중단·폐기)을 전제로 한 규칙이다. 서버 컴포넌트는 요청마다 서버에서 한 번 실행되고 끝나며 state도 재렌더도 없다. 게다가 데이터 읽기는 같은 입력이면 같은 결과를 내는 성질에 가깝다(React는 cache()로 같은 요청 안 중복 읽기를 합쳐 이를 뒷받침한다). 그래서 await db.get(id)를 본문에서 바로 써도 된다. 반대로 쓰기는 서버에서도 렌더 중에 하지 않고 서버 함수로 이벤트를 계기로 처리한다.

Effect를 덜 쓰는 법은 Effect가 필요 없는 경우, 실행 시점 차이는 useEffect와 useLayoutEffect. 값을 돌려주는 일과 상태를 바꾸는 일을 나누는 생각은 명령-질의 분리과도 통한다.

연결된 개념

이 노트를 가리키는 문서

뜻이 가까운 노트

  • 서버 렌더에서 훅이 하는 일

    서버 렌더(Server-Side Rendering, SSR)에서도 컴포넌트 함수는 실제로 호출되고, 그 안의 훅도 호출은 된다. 다만 서버에는 커밋(DOM 반영)이 없어서, 렌더 중 동기적으로 값을 계산하는 훅만 일하고 커밋 뒤에 도는 훅은 아무것도 하지 않는다. "이 훅은 클라이언트에서만 동작한다"는 말은 대개 "Effect 안의 일은 클라이언트에서만 일어난다"는 뜻이다.

  • Fiber 아키텍처

    Fiber는 React 16부터 쓰는 내부 자료구조이자 렌더링 엔진이다. 엘리먼트마다 Fiber 노드를 만들어 렌더 작업을 작은 단위로 쪼개고, 우선순위를 매기고, 중간에 멈췄다 다시 이어 갈 수 있게 한다.

  • use()로 Promise 읽기

    use()는 렌더 중에 Promise나 Context 같은 리소스의 값을 읽는 React 19 API(Application Programming Interface)다. Promise가 아직 pending이면 컴포넌트가 suspend되어 가장 가까운 suspense의 fallback이 보이고, 끝나면 그 값으로 다시 렌더된다. reject되면 가장 가까운 에러 경계(Error Boundary)로 던져진다.

  • Suspense

    Suspense는 아직 준비되지 않은 하위 트리의 렌더를 잠시 보류(suspend)하고, 그동안 가장 가까운 경계의 fallback을 보여 주는 React의 비동기 렌더링 메커니즘이다. 로딩 상태를 컴포넌트마다 들고 있지 않고 경계에 위임한다.

보기 옵션