본문 바로가기
Archive/Java 풀스택 아카데미

[TIL] 3. 7월 4주차 - React (학습 중에 알게된 것들)

by Lseing 2025. 7. 27.
현대이지웰 자바 풀스택과정을 들으면서 배웠던 것들과 배우면서 들었던
나의 생각과 부족했던 점들을 돌아보면서

정리해보려고한다 이렇게 기록함으로써 좀 더 나은 개발자의 모습이 되었으면 희망한다.

 

React 파트

🤔 Context 왜 필요하나요?

React에서 데이터를 전달하는 가장 기본적인 방법은 부모 컴포넌트에서 자식 컴포넌트로 props를 전달하는 방법이다. 하지만 만약 컴포넌트 구조가 아주 깊다면 값을 전달할 때 많이 불편하지 않을까?

props가 필요하지 않은 컴포넌트들은 오직 전달을 위해서 props 사용해야한다.

이처럼 여러 계층의 컴포넌트를 거쳐서 props를 전달하는 비효율적인 현상을 props drilling이라고 부른다 

context는 이러한 현상을 막는데 도움을 준다고 한다.

 

간단한 예시를 보자

props drilling 예) Right3 컴포넌트 안에 존재하는 버튼을 누르면 Left3의 count가 올라감

 

구조는 대충 이러하다 Left1컴포넌트 안에는 Left2가 또 그안에는 Left3가 존재한다(Right도 마찬가지)

이때 props를 사용하여 Left3 까지 전달하기 위해 props를 전달한다.

props 를 사용하지 않는 컴포넌트는 props가 필요한 하위 컴포넌트에게 값을 넘겨주기 위해서 어쩔 수 없이 props를 사용을 하고 있다. 이런 방식은 컴포넌트의 구조가 깊으면 깊어질수록 props가 어디에 사용되는지 찾기도 힘들어지고 가독성도 떨어질 것이다.

 

이 문제를 해결하기 위해 context 사용해보자, 처음에 전역적으로 관리가 필요한 상태를 상위 컴포넌트에 등록해주면, 해당 상태가 필요한 컴포넌트에서 상태를 불러올 때 불필요하게 계속 컴포넌트들을 타고 내려가서 접근하는것이 아니라 바로 접근을 할 수 있다. 그렇다면 어떻게 가능할까?

비교 이미지 : props drilling(왼쪽 이미지), context (오른쪽 이미지)

 

context는 React 앱 내에서 일종의 전역 데이터 보관소를 만들어준다. props가 하나의 아주 긴 랜선이라고 하면 context는 Wifi 공유기와도 같다. 무슨 말이냐면 인터넷을 쓰지 않는 방들이 있는데, 단지 선(props)이 지나가야만 한다는 이유로 지저분하게 랜선(props)이 지나간다, 방 구조가 복잡해질수록 랜선은 길어지고, 어디가 꼬였는지 파악하기 힘들어질 것이다.

 

반면 context는 공유기를 설치하는 것과 같다

 

1. 공유기 설치(provider): 집의 중심(최상위 컴포넌트)에 공유기를 설치하면 이 공유기는 집 전체에 인터넷 신호를 뿌려준다.

2. 와이파이 신호(value): 공유기가 내보내는 보이지 않는 인터넷 신호(context가 전달하는 값)

3. 비밀번호 입력(useContext): 인터넷이 필요한 기기(컴포넌트)는 와이파이를 켜서 비밀번호를 입력(useContext)하기만 하면 중간에 어떤 방을 거치던 상관없이 바로 인터넷을 사용할 수 있음

 

🤔그러면 언제 사용하나요?

보통 한 번 설정하면 거의 바뀌지 않지만, 여러 곳에서 필요한 데이터에 사용된다.

예를 들어 테마 설정(다크/라이트 모드), 언어 설정 등이 있다.

리액트 사이트에서 테마와 언어 설정(우측 상단)을 확인할 수 있음(https://ko.react.dev/)

하지만 빈번하게 바뀌는 상태를 context에 넣는 것은 성능문제를 일으킬 수 있다. Provider의 value가 바뀔 때 마다 Context를 사용하는 모든 컴포넌트가 리렌더링 되기 때문이다.

Redux

빈번하게 바뀌는 상태를 context에 넣는것이 성능문제를 일으킬 수 있다고 언급했었다. 그렇지만 Redux를 사용한다면 이 문제를 해결할 수 있다.

우선 Redux는 React와는 별개로 존재하는 자바스크립트 상태 관리 라이브러리이다. 애플리케이션의 모든 상태를 'store'라는 한 곳에 모아두고, 정해진 규칙에 따라서만 상태를 수정할 수 있도록 하여 데이터의 흐름을 예측 가능하게 만든다.

 

비유를 들어 이해해보자

은행에서 금고에 들어가 돈을 함부로 만질 수 없기 때문에, 반드시 정해진 절차를 거쳐야 하는것과 같다.

(신청서 작성 -> 창구 제출 -> 은행원 처리)

 

우선 이 용어들을 알아야 한다.

1. Store(은행 금고)

  • 앱의 모든 상태(데이터)가 저장되는 단 하나뿐인 공간이다.
  • 앱에는 오직 하나의 store만 존재할 수 있다. 또한 이 금고안의 데이터는 직접 수정할 수 없다.

2. Action(거래 신청서)

  • 상태에 어떤 변화가 필요한지 설명하는 요청서(객체)이다. 입금/출금 같은 요청이다. 이 액션 개체는 반드시 타입이라는 속성을 가져야 한다. 예) { type: 'DEPOSIT', payload: 100000 } ( 100000 원을 입금해달라는 요청서)

3. Dispatch(신청서 제출하기)

  • 작성한 요청서(action)를 은행(store)에 제출하는 행위이다. dispatch(action)의 형태로 사용한다(상태 변경을 일으키는 유일한 값이다.)

4. Reducer(은행원)

  • dispatch를 통해 전달된 요청서(action)를 받고, 실제로 상태를 어떻게 바꿀지 결정하는 함수이다. (은행원이 요청서를 보고 금고의 장부를 업데이트 하는 것과 같음)
  • reducer는 현재 state와 action을 인자로 받아서 반드시 새로운 state를 반환해야만 한다. (기존 장부를 찢고 새 장부에 기록하는 것처럼 불변성을 지킴)

이런 느낌으로 동작한다

 

Context와는 이런 차이가 있다

구분 React Context Redux
목적 PropsDrilling 회피 및 간단한 전역 데이터 공유 복잡한 상태의 예측 가능한 관리 및 디버깅
구조 Provider, useContext Store, Action, Dispatch, Reducer
데이터 흐름 Provider의 value가 바뀌면 바로 전파 Action-Dispatch-Reducer-State변경의 엄격한 단방향 흐름
비유 와이파이 공유기 중앙 은행

 

🤔그러면 언제 사용하나요?

redux는 복잡한 애플리케이션에서 전역 상태 관리가 필요할 때 사용한다. 여러 컴포넌트에서 공유되는 데이터가 많거나 상태 변화의 추적이 중요할 때 등등 사용된다고 한다.

주의사항으로는 초기 설정의 복잡성이 존재하고, 과도한 사용은 지양해야한다(컴포넌트 내부에서만 사용되는 간단한 상태는 useState를 사용하는 것이 더 효율적일 수 있음)