부수 효과(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. 값을 돌려주는 일과 상태를 바꾸는 일을 나누는 생각은 명령-질의 분리과도 통한다.