= 우리가 기존에 사용하던 대로 사용한다면 SSR에서는 해당 객체나 메소드에 접근하지 못하고 에러가 출력됩니다.
CSR에서는 접근이 가능하지만, SSR에서는 접근하지 못하고 에러가 출력됩니다.
useEffect(() => {},[]) 는 렌더링이 되고 난 후 실행되기 때문에 useEffect는 서버사이드에서는 실행되지 않는 CSR 전용 이벤트라고 생각할 수 있습니다. 그렇기 때문에 useEffect를 사용하여 SSR이 완료 된 후 동작하게 한다면 에러가 출력되지 않습니다. 의존성 배열의 값을 잘 활용하여 useEffect를 사용한다면 localStorage, alert() 등을 사용할 수 있습니다.
아래의 예제는 todo-list를 만들어 localStorage에 저장하고 불러오는 컴포넌트를 작성한 내용입니다.
따라 치면서 한번 다같이 이해해 봅시다!
------------------------------------------------------------------/pages/api/double.tsx import React, { useCallback, useEffect, useState } from 'react'; import styled from 'styled-components'; const AddBtn = styled.button` background-color:skyblue; `; const RemoveBtn = styled.button` background-color:red; `; function TodoList () { const [list, setList] = useState([]) const [text, setText] = useState('') //window 객체는 CSR에서는 접근 가능하지만, SSR에서는 접근 못하고 에러가 출력된다. // window is not defined가 출력되면 SSR에서의 window 객체이기 때문이라고 추측 가능 // alert, document 다 SSR에서는 접근할 수 없다. // console.log(window) // console.log(alert(' ')) // console.log(document) // 또한 서버에서는 LocalStorage를 읽지 못한다. // 그렇기때문에 useEffect를 사용해서 페이지가 렌더 된 후 사용해야 한다. // useEffect -> 컴디마, 컴디업을 비교해서 다루는데 // 즉 useEffect는 서버사이드에서는 실행되지 않는 CSR 전용 이벤트가 된다. useEffect(() => { console.log('123') console.log(localStorage) const result = localStorage.getItem('todo-list') console.log(JSON.parse(result)) setList(JSON.parse(result)) }, []) const addItem = useCallback(() => { const items = [...list, { id: (new Date().getTime()).toString(), text }] setList(items) localStorage.setItem('todo-list', JSON.stringify(items)) },[list, text]) const removeItem = useCallback((id) => { const filterList = list.filter((el) => { return el.id !== id && el }) setList(filterList) localStorage.setItem('todo-list', JSON.stringify(filterList)) },[list]) return ( <> <h1>TODO List</h1> <div> 할일 내용 <input type="text" value={text} onChange={(e) => setText(e.target.value)}/> <AddBtn onClick={addItem}>추가</AddBtn> <ul> <li>할일내용<RemoveBtn>삭제</RemoveBtn></li> {list.map((el) => { return ( <li key={el.id}>{el.text}<RemoveBtn onClick={() => removeItem(el.id)}>삭제</RemoveBtn></li> ) })} </ul> </div> </> ) } export default TodoList