React의 목적
React는 사용자의 입력에 반응하여 필요할 때마다 UI를 렌더링한다는 주요 임무를 갖고 있다.
state나 event들의 특징을 보자면 화면에 무언가를 가져오는 것들이었다.
그리고 사용자가 그 무언가와 상호 작용하게 하는 것이 주된 목적이었다.
- JSX 코드와 DOM을 평가하고 렌더링하고 state와 props를 관리한다.
- 사용자 입력이 올바르게 반영되는지 확인하기 위해서 모든 component에 필요한 데이터가 있는지 체크한다.
Side Effect란?
side effect 혹은 effect라고 불리는 이것은 무엇일까?
side effect는 애플리케이션에서 "범위 밖"을 함께 실행할 때 나타나는 모든 것을 말하며,
component가 렌더링된 이후에 비동기로 처리되어야 하는 부수적인 것들을 흔히 Side Effect라고 부른다.
React 범위 밖에 있다는 것은 브라우저의 React framework의 일부가 아님을 의미한다.
일반적인 SIde Effect의 예시는 다음과 같다 : )
- 웹 서버(http)에 데이터를 요청(request)하기 위한 브라우저 API와의 상호작용
- localStorage나 cookie와 같이 브라우저 저장소에 무언가를 저장하는 일들
- setTimeout, setInterval 등 타이머나 일정 간격동안 실행되는 타이밍 함수 사용
위의 이러한 작업들은 모두 애플리케이션이라면 고려되어야하는 작업들이다.
하지만 이런 작업은 React가 추구하는 component를 활용하여 UI를 렌더링하는 것과는 거리가 멀다.
적어도 직접적인 관계가 없으며 request를 보내거나 잠재적인 오류를 처리하는 것 등은 React를 필요로하지 않는다.
그렇기 때문에 React framework의 일부가 아닌 이 작업들에 대한 대처를 어떻게 해야할지가 관건이다.
자, 정리하자면 이런 일들은 일반적인 component 함수 밖에서 일어나야 하는 일들이다.
React에 의해, 적어도 state가 바뀔 때마다 자동으로 재실행되는 statefull component는 지속적으로 재실행될 것이다.
그런데 http request에 대한 응답을 component에서 수행한다면 state가 바뀔 때마다 함수가 다시 실행되어 무한 루프에 빠질 수도 있다.
따라서 그런 side effect는 직접적으로 component 함수에 들어가서는 안된다.
무한 루프(infinite loop)
앞서서 설명하기 무한 루프에 빠질 수 있다고 했는데 그 예시를 보자.
import React, { useState } from 'react';
import Login from './components/Login/Login';
import Home from './components/Home/Home';
import MainHeader from './components/MainHeader/MainHeader';
function App() {
const [isLoggedIn, setIsLoggedIn] = useState(false);
const storedUserLoggedInInformation = localStorage.getItem('isLoggedIn') ;
if(storedUserLoggedInInformation === 'true'){
setIsLoggedIn(true) ;
}
const loginHandler = (email, password) => {
// We should of course check email and password
// But it's just a dummy/ demo anyways
localStorage.setItem('isLoggedIn', true) ;
setIsLoggedIn(true);
};
const logoutHandler = () => {
localStorage.removeItem('isLoggedIn') ;
setIsLoggedIn(false);
};
...
위의 코드는 임의의 email과 password를 받아 로그인 하는 페이지로, 서버에 request를 받아 valid를 체크하는 것이 아닌 dummy 자격 증명으로 로그인하는 데모 페이지이다.
로그인의 상태를 state만으로 관리하다보면 새로고침할 때마다 로그인이 풀려버린다.
따라서 새로고침을 해도 로그인이 유지되길 원하기 때문에 localStorage를 활용해보겠다.
localStorage에 저장되는 값은 객체 형태로 저장되며, 그 객체 안의 속성 값들은 모든 값이 문자열인 것 같다.
email과 password를 받으면 localStorage에 로그인되었다는 것을 알리고 로그인의 state를 true로 만들어준다.
그런데 로그인한 상태로 페이지가 새로고침되면 무한 루프가 발생해 흰 화면만을 비추게 된다.
(... 물론, 조건문에 && !isLoginIn을 추가하면 없어지긴 하지만... 이거 코딩을 덜한거 아닌가..? 강의에서는 무한 루프를 설명하면서 언급하고 있다.)
이번 시간에는 side effect에 대해서 이야기해봤다.
다음은 이 문제를 어떻게 해결할 수 있는지 이야기하겠다.