React

리액트 Context API에 대해서

date
Apr 20, 2023
thumbnail
context-api.png
slug
About React Context API
author
status
Public
tags
Context
ContextAPI
TIL
React.js
summary
리액트에서 상태를 다루는 방법 중 하나, Context-API에 대해 알아보자.
type
Post
category
React

상태 끌어올리기와 Prop Drilling


리액트의 상태 끌어올리기
리액트의 상태 끌어올리기
 
리액트를 사용해서 개발을 하다보면 프로퍼티를 특정 컴포넌트를 거쳐 원하는 컴포넌트에 전달하는 작업을 자주 하게 된다. 이를 Prop drilling이라고 한다. 만약 데이터가 거쳐가는 컴포넌트가 한 개에서 두 개일 경우 사실 그렇게 큰 불편함이 없을 수 있지만, 3~4개 이상의 컴포넌트를 거쳐 데이터를 전달해야할 경우에는 매우 번거롭게 된다.
 
Prop drilling
Prop drilling
이런 식으로 리액트 앱의 규모가 커지고 컴포넌트가 많아지게 되면 그에 따라 프로퍼티가 거쳐가야 하는 컴포넌트가 많아지게 된다. 이러한 경우, 코드가 매우 복잡해지며 prop drilling으로 인해 아래와 같은 문제들이 발생한다.
 
  • 필요한 프로퍼티보다 많은 Props를 전달하다 컴포넌트 분리 과정에서 필요치 않은 프로퍼티가 계속 남거나 전달된다.
  • 프로퍼티 전달이 누락되면서 Prop의 디폴트 값이 사용되어 문제 파악이 어려워진다.
  • 프로퍼티의 이름이 전달 중 변경되어 데이터 추적이 어려워진다.
 

컴포넌트 구조

화면
화면
로그인 전 구조
로그인 전 구조
로그인 후 구조
로그인 후 구조
 
위의 리액트 데모 앱(로그인 화면)의 isLoggedIn 상태와 Login 함수가 대표적인 예시다. 이 리액트 데모 앱의 모든 곳에서 isLoggedIn 상태와 Login 함수가 필요하며 이 앱의 모든 곳에서 필요로 하기 때문에 isLoggedIn 상태를 상위 컴포넌트인 App 컴포넌트까지 끌어올렸다.
MainHeader 컴포넌트에 isAuthenticated 프롭으로 로그인 상태를 전달하며, 해당 컴포넌트에서 onLogout 프롭의 값(함수)인 logoutHandler로 로그아웃을 할 수 있다.
 
요약하자면 로그인 상태는 앱의 거의 대부분의 위치에서 필요하거나 사용된다는 것이다.
 
하지만 MainHeader 컴포넌트에서는 Navigation 컴포넌트로 다시 전달하는 용도로만 logoutHandlerisAuthenticated 프롭을 사용하고 있다. 이런 식으로 직접 사용하지 않고 프로퍼티를 전달하기만 하는 역할을 한다. 앱이 커질 수록 전달하는 경로가 매우 길어진다.
 
notion image
 
위 그림은 쇼핑몰 앱을 가정한 컴포넌트 트리와 컴포넌트 디펜던시에 따른 프로퍼티의 이동 과정 그림이다. 물론 이렇게 해도 제대로 동작한다면 괜찮다. 딱히 나쁜 것이 아니지만, 앱이 커질수록 불편해진다. 이렇게 하는 대신 프로퍼티를 실제로 필요한 데이터를 부모로부터 받는 컴포넌트에만 사용할 수 있다면 더 좋을 것이다.
 

리액트 Context


이를 위해 컴포넌트 전체에 사용할 수 있는 리액트 내장 상태 저장소가 있으며 리액트 컨텍스트(Context)라고 하는 개념이다.
 
리액트의 Props와 State는 상위 컴포넌트와 하위 컴포넌트 혹은 한 컴포넌트 안에서 데이터를 다루기 위해 사용되며 리액트의 단방향 데이터 바인딩이라는 특징에 따라 위에서 아래, 상위에서 하위 컴포넌트로 데이터가 흐르게 된다.
 
이처럼 컴포넌트 사이에 공유되는 데이터를 위해 매번 공통 상위 컴포넌트를 수정하고 하위에 있는 모든 컴포넌트에 데이터를 Props로 전달하는 것은 매우 비효율적이다. 이 문제를 해결하기 위해 리액트에서는 Flux라는 개념을 도입하였고 Context API를 제공하기 시작했다.
 

Context API

컨텍스트는 상위 컴포넌트로부터 자식 컴포넌트로 전달되는 데이터의 흐름과는 상관없이 전역적인 데이터를 다룰 때 사용한다. 전역 데이터를 컨텍스트에 저장한 뒤 데이터가 필요한 컴포넌트에서 해당 데이터를 불러와 사용할 수 있게 된다.
 
가까운 자식 컴포넌트에 Context로 데이터 뿌리기
가까운 자식 컴포넌트에 Context로 데이터 뿌리기
멀리 있는 자식 컴포넌트에 Context로 데이터 뿌리기
멀리 있는 자식 컴포넌트에 Context로 데이터 뿌리기
 
리액트 앱에서 Context를 사용하기 위해서는 Context API를 사용해야 한다.
 

상태 관리 라이브러리들

기존의 리액트 Context는 리액트 버전에 따라 정말 많이 변경을 거쳐온 API다. 한 때는 사용하지 말 것을 공식문서에서 권장하기도 했다. prop drilling에 따른 문제를 해결하기 위해 최초의 리액트 상태 관리 라이브러리인 Redux가 나왔다. 그러다 리액트 개발 팀에서 죽어있던 Context API를 새로 되살려 내면서 Redux를 Context API로 대체하는 개발자들도 생겼다. 허나 Context API에도 단점은 있으며, 가장 최근 개발된 상태 관리 라이브러리인 Recoil이 떠오르며 Redux와 Recoil 두 라이브러리가 많이 사용되고 있다.
 
 
📌
Context API를 먼저 학습하여 데이터를 관리하는 데모 앱을 개발해보고, 그에 대한 대안으로 가장 많이 사용되고 있는 상태 관리 라이브러리 Redux를 학습하여 상태를 관리해본다. 강의에서는 Redux를 활용하는 부분까지 제공된다. 이후에 Recoil을 따로 학습해보도록 하자.