React를 React답게, Thinking in React(1): UI는 function

백동민·2026년 1월 10일

React 다시 읽기

목록 보기
1/1
post-thumbnail

디자인도 이쁘고 코드도 이쁘게 짤 순 없을까??

이 단순한 생각에서 이 글 시리즈를 작성하게 된 계기가 되었습니다!
(대 바이브코딩 시대에, 문서보고 코드짜는 멋쟁이가 되고 싶어...)

리액트를 직접 만든 사람들은 어떻게 생각하고 만들었을까?

React 공식 문서 Thinking in React를 단순히 ‘컴포넌트 나누는 방법’으로 보는 것이 아니라,

제가 열심히 해체 분석해보려 합니다!
shout out to sAewoo

React의 본질적 철학(순수 함수 UI, 책임 분리, 단방향 데이터 흐름, 예측 가능성)
관점에서 알아보려고 합니다.

이 관점을 기반으로 다음을 얻을 수 있습니다!:

  • React가 왜 이런 방식으로 UI를 구성하도록 가이드를 제시하는지 철학적 이유

  • 컴포넌트 설계가 ‘감’에서 ‘원리 기반 판단’으로 전환하기.(추구했던 바!!)


목차

  1. Thinking in React 5단계의 나만의 해석
  2. 상태 배치(State Architecture)를 판단하는 기준
  3. 단방향 데이터 흐름과 예측 가능성 확보

1. UI = f(state): 왜 이 식이 필요할까?

React를 진지하게 이해하려면, 먼저 이 한 줄을 이해해야 한다.

UI = f(state)

React 제작자 들이 하고 싶은 말은 단순하다.

“UI는 직접 조작하는 대상이 아니라,
상태(state)를 넣으면 계산되어 나오는 결과물이어야 한다.”

이 식이 왜 필요한지, 그리고 이게 무너지면 어떤 지옥이 펼쳐지는지부터 짚고 가자.


1.1 기존 UI 패턴이 왜 망가지는가: “상태 지옥”

전통적인 웹 UI는 대부분 이렇게 동작했었다.

  • DOM에서 요소를 찾고
  • 이벤트가 발생할 때마다
  • class를 붙였다 떼었다,
  • 텍스트를 바꾸고,
  • 여러 상태나 데이터를 “수동으로” 맞춘다.

문제는 상태가 한 군데에 모여 있지 않다는 점이다.

  • 서버 응답 결과 일부는 전역 변수에,
  • 일부는 DOM attribute에,
  • 일부는 컴포넌트 인스턴스 필드에,
  • 심지어 유저가 뭔가 조작하면 또 다른 곳에 복사본이 생긴다.

이렇게 되면 필연적으로 이런 상황이 온다.

  • 어떤 버튼은 활성화인데, 다른 영역은 여전히 비활성화로 보인다.
  • 모달은 닫혔는데, 오버레이는 남아 있다.
  • 토글 버튼 텍스트는 ON인데 실제 로직 값은 false다.

즉, “앱의 진짜 상태”와 “눈에 보이는 UI”가 서로 어긋나는 순간부터
디버깅은 감과 운에 의존하는 게임이 된다.

이게 React가 해결하려는 문제의 본질이다.


1.2 React의 관점: “UI를 단순 화면이 아니라 함수로 취급하자”

React는 여기서 접근을 통째로 바꾼다.

  • 더 이상 “UI를 어떻게 바꿀지(how)”를 작성하지 말고,
  • “지금 상태라면 UI가 어떻게 생겨야 하는지(what)”를 정의하라고 한다.

즉,

UI = f(state)
  • 입력: 현재 앱 상태(state)
  • 출력: 그 상태에서의 UI 트리(React element tree)

우리는 더 이상 DOM 조작 절차를 나열하지 않는다.
대신 state를 인자로 받아 UI를 반환하는 함수를 설계한다.

이게 “선언형 UI(Declarative UI)”.

“상태가 이렇게 생겼으면, 화면은 이렇게 보여야 한다”를
함수 정의로 고정해 두는 것.


1.3 순수 함수 UI의 세 가지 조건

React가 진짜로 원하는 건 “순수 함수처럼 보이는 UI”다.
순수 함수 UI는 최소한 아래 세 가지를 만족해야 한다.

  1. 같은 state == 항상 같은 UI

    • 랜덤, 시간, 전역 mutable 변수 등에 의해 결과가 바뀌지 않는다.
  2. UI는 오직 props와 state로만 결정된다

    • 컴포넌트 내부에서 몰래 전역 싱글톤을 직접 바꾸고 참조하는 패턴은 독이다.
  3. 렌더링 과정에는 side effect가 없다

    • DOM 직접 조작, 네트워크 요청, 로깅 등은 useEffect 같은 별도 단계에서 처리해야 한다.

이게 지켜져야 다음이 가능해진다.

  • 상태만 보면 UI가 어떻게 생겼는지 예측 가능
  • 특정 state를 주입해서 화면을 테스트 가능 (그래서 TDD를?)
  • UI 변경 이력을 추론 가능(“왜 이렇게 보이는지” 설명 가능)

즉, 테스트 가능하고, 예측 가능하고, 리팩터링 가능한 UI의 최소 조건이 바로 이거다.


1.4 이 식이 설계에 강제하는 구조적 결과

UI = f(state)를 진지하게 받아들이면,
설계는 어쩔 수 없이 다음과 같이 바뀐다.

  1. 상태는 함수 밖에서 관리하고, arg로 주입한다.

    • 컴포넌트는 “현재 상태를 기반으로 UI를 그리는 기계”가 된다.
  2. 렌더링 로직은 side effect에서 분리된다.

    • 그리는 것(render)과 “반응하는 것(effect)”을 분리해야 순수성이 유지된다.
  3. 자식 컴포넌트는 함수 합성처럼 다뤄진다.

    • 부모가 state → UI로 계산한 결과 일부를 props로 넘긴다.
    • 자식은 받은 props를 다시 UI로 매핑하는 작은 함수다.

즉, 전체 React 앱은 거대한:

AppUI = f(globalState)

를 작은 함수 여러 개의 합성으로 분해한 것에 불과하다.

이 관점이 잡히면, 컴포넌트 나누기, props 구조, state 위치 선정은
전부 이 식을 깨지 않기 위한 아키텍처 작업으로 이해할 수 있다.


1.5 UI = f(state)가 깨질 때 벌어지는 사고들

반대로, 이 원칙을 무시하면 어떤 일이 생길까?
대표적인 실패 패턴 몇 가지를 보자.

  1. 렌더링 중 전역으로 읽고/수정하는 컴포넌트

    • 테스트 환경에서 상태 주입이 안 된다.
    • 어디서 값이 바뀌는지 추적이 불가능해진다.
  2. derived state를 또 다른 state로 중복 저장하는 패턴

    • 예: itemsfilteredItems를 둘 다 state로 들고 있기
    • 둘의 동기화를 계속 맞춰야 한다는 건, 결국 언젠가 틀어진다.(디버깅시 매우 까다로워진다.)
    • 사실 filteredItems = f(items, filter)로 매번 계산하는 게 맞다.
  3. 렌더링 안에서 DOM을 직접 건드리는 코드

    • React의 렌더링 사이클과 충돌한다.
    • “분명히 상태는 false인데, DOM은 여전히 열려 있음” 같은 모순 발생.

이 모든 문제는 한 줄로 정리된다.

“UI가 state의 함수가 아닐 때, UI와 state는 언젠가 반드시 어긋난다.”

1.6 Thinking in React

이제 “왜 UI = f(state)가 필요한가”는 어느 정도 명확해졌다.
그럼 공식 문서의 5단계는 어디에 위치할까?

  • UI를 컴포넌트로 나누기
  • 정적 버전 만들기
  • 최소한의 상태 찾기
  • 상태를 어디 둘지 정하기
  • 단방향 데이터 흐름 구성하기

이건 전부 메타 수준에서 보면 한 가지 목적.

“앱 전체를 UI = f(state) 구조에 맞게 재조직하는 절차”

  • 정적 버전 만들기는, 순수 함수 UI 먼저 확보
  • 최소 상태 찾기는, f의 입력을 필요 최소한으로 압축
  • 상태 위치 정하기는, f가 어디서 정의되는지, 책임 단위로 배치
  • 단방향 데이터 흐름는, 입력이 어디서 왔는지 추적가능하게 만들기

그래서 이 글 전체의 구조도 이렇게 잡아보자.

  1. 1장: UI = f(state) — 왜 이 식이 필요한가 (지금 읽고 있는 부분)
  2. 2장: 상태관리와 책임 단위 — f(state)에서 state를 어디서 관리할 것인가
  3. 3장: 단방향 데이터 흐름 — state -> UI -> 이벤트 -> state로 이어지는 루프를 어떻게 닫을 것인가

이제 다음 장에서 다룰 질문은 명확하다.

“좋다, UI = f(state)인 건 알겠다.
그럼 그 state는 어디에 둬야 예측 가능한 시스템이 되나?

그게 바로 2장의 주제,
“상태관리 및 책임 단위(State Architecture)”이다.

출처 :
https://overreacted.io/the-two-reacts/
https://www.youtube.com/watch?v=x7cQ3mrcKaY
https://overreacted.io/a-complete-guide-to-useeffect/
https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0

profile
Developer보단 Engineer로 될래

0개의 댓글