노트Presentational·Container 컴포넌트
Presentational and Container Components
프론트엔드#react#pattern · 연결된 개념 9개
쉽게 말하면
Presentational·Container 패턴은 무대 위 배우와 무대 뒤 스태프를 나누듯, 화면을 그리는 컴포넌트와 데이터를 가져와 넘기는 컴포넌트를 따로 두는 방식이에요. 화면은 데이터 출처를 몰라도 돼서 재사용하기 쉬워요.
비유의 한계 저자 본인도 훅이 나온 뒤로는 억지로 나눌 필요가 없다고 덧붙였어요. 지금은 커스텀 훅이나 서버 컴포넌트가 데이터 쪽을 맡고, '표현과 동작을 섞지 않는다'는 생각이 남았어요.
Presentational·Container 패턴은 컴포넌트를 "어떻게 보이는가"를 맡는 쪽과 "어떻게 동작하는가"를 맡는 쪽으로 나누는 방식이다. Dan Abramov가 2015년 글로 널리 알렸다.
- Presentational: 마크업과 스타일 담당. 데이터는 props로만 받고, 데이터를 어디서 어떻게 가져오고 바꾸는지 모른다. UI 상태 외의 state는 거의 없다
- Container: 데이터와 동작 담당. 데이터를 불러오고 콜백을 만들어 presentational 컴포넌트에 넘긴다. 감싸는 div 정도 외에는 마크업이 없다. 당시에는 고차 컴포넌트(Higher-Order Component, HOC)로 많이 만들었다
- 얻는 것: 관심사 분리(Separation of Concerns). 화면은 데이터 출처와 무관하게 재사용하고, 디자인과 로직을 따로 테스트한다. Storybook에 presentational 컴포넌트만 올려 보기도 쉽다(Storybook)
지금은
저자 본인이 훅이 나온 뒤로는 이렇게 억지로 나눌 필요가 없다고 글에 덧붙였다. 데이터 로직은 커스텀 훅이나 TanStack Query로 빼고, 서버 컴포넌트가 데이터를 가져와 클라이언트 컴포넌트에 넘기는 구조(React 서버 컴포넌트(RSC), 'use client'와 클라이언트 경계)가 그 역할을 이어받았다. 그래도 "표현과 동작을 섞지 않는다"는 생각 자체는 유효하다(응집도, MVC·MVP·MVVM).
출처: Dan Abramov - Presentational and Container Components
연결된 개념
이 노트를 가리키는 문서
뜻이 가까운 노트
- 구조적 공유
구조적 공유(Structural Sharing)는 새 버전의 데이터를 만들 때 바뀌지 않은 부분은 이전 버전의 객체를 그대로 가리키게 하는 기법이다. 바뀐 노드와 그 노드까지 올라가는 경로만 새로 만들고, 나머지 가지는 두 버전이 함께 쓴다. 불변 데이터를 다루면서도 매번 전체를 복사하지 않게 해 준다.
- 변수·컬렉션 캡슐화
넓은 범위에서 쓰이는 데이터에 직접 접근하지 못하게 하고, 읽고 쓰는 함수를 통해서만 다루게 하는 리팩터링. 데이터를 옮기거나 바꿀 때 고쳐야 할 곳이 접근 함수 한 곳으로 좁아진다.
- 하이드레이션
하이드레이션(Hydration)은 서버가 미리 렌더해 보낸 HTML(HyperText Markup Language)을 클라이언트에서 다시 만들지 않고, 그 DOM(Document Object Model)에 React 컴포넌트를 연결해 이벤트 핸들러와 상태를 붙이는 과정이다(hydrateRoot). Dan Abramov의 비유로는 "마른 HTML에 상호작용이라는 물을 주는 일"이다.
- Pages Router에서 App Router로
App Router는 Next.js 13에서 도입된 app/ 디렉터리 기반 라우터로, 서버 컴포넌트·중첩 레이아웃(Nested Layouts)·스트리밍을 기본으로 한다. pages/ 기반의 Pages Router에서 옮길 때 바뀌는 생각을 정리한다.
- loading 경계와 레이아웃 끌어올리기
Next.js App Router에서 loading.tsx는 같은 세그먼트의 page와 그 아래(하위 layout 포함)를 suspense로 감싸지만, **같은 세그먼트의 layout은 감싸지 않는다**. 그래서 데이터를 기다릴 필요가 없는 공통 UI(탭바, 필터 헤더)를 page에서 layout으로 끌어올리면 스켈레톤에 덮이지 않고 처음부터 실제 모습으로 보인다.