react component 설계 패턴 연도별 정리

처음 리액트를 접하면 “와, 컴포넌트 진짜 편하다!” 싶다가도, 프로젝트 규모가 조금만 커지면 “이 코드를 어디에 둬야 하지?”라는 고민에 밤잠 설친 적 있을 거야. 나도 처음엔 그랬거든. 컴포넌트 하나에 API 호출, 데이터 가공, 스타일까지 다 때려 넣었다가 나중에 수정하려고 보니 코드가 500줄이 넘어가서 멘붕 왔던 기억이 나네.

오늘은 내가 그동안 겪었던 시행착오들과 함께, 리액트 생태계가 발전해 오면서 어떤 식으로 react component 설계 패턴이 변해왔는지 연도별로 아주 쉽게 설명해 주려고 해. 특히 초보 개발자 친구들이 “이 패턴은 왜 쓰는 거지?”라고 궁금해할 만한 포인트들을 콕콕 집어줄게. 자, 커피 한 잔 마시면서 편하게 들어봐!


1. 2013년~2015년: 리액트의 탄생과 아토믹 디자인(Atomic Design)의 등장

리액트가 세상에 처음 나왔을 때 사람들은 충격에 빠졌어. “HTML이랑 자바스크립트를 같이 쓴다고?(JSX)”라며 다들 의아해했지. 하지만 곧 컴포넌트 기반 개발의 매력에 빠져들었어. 이때 가장 먼저 화두가 된 건 “어떻게 컴포넌트를 쪼갤 것인가?”였어.

이 시기에 브래드 프로스트(Brad Frost)가 제안한 아토믹 디자인 패턴이 리액트 진영에서도 큰 인기를 끌었지. 이건 화학 시간에 배운 원자 이론을 디자인에 접목한 건데, 아주 작은 단위부터 차근차근 쌓아 올리는 방식이야.

  • 원자(Atoms): 더 이상 쪼갤 수 없는 최소 단위야. 예를 들어, 우리 ‘커피 주문 앱’을 만든다고 치면 ‘가격 표시 텍스트’나 ‘작은 아이콘 하나’가 원자가 되겠지.
  • 분자(Molecules): 원자들이 모여서 의미 있는 기능을 하는 거야. ‘커피 사진’과 ‘커피 이름’, ‘가격’이 합쳐진 ‘메뉴 아이템 카드’ 정도가 되겠네.
  • 유기체(Organisms): 분자들이 모여서 더 복잡한 영역을 만들어. 여러 개의 ‘메뉴 카드’가 모인 ‘커피 메뉴 리스트’가 바로 유기체야.
  • 템플릿(Templates) & 페이지(Pages): 이것들이 모여서 실제 우리가 보는 화면의 레이아웃과 데이터가 채워진 완성본이 되는 거지.

이 패턴의 핵심은 재사용성이야. 한 번 잘 만들어둔 ‘원자’ 버튼은 어디서든 쓸 수 있거든. 하지만 실제로 써보면 “이게 분자인가 유기체인가?” 헷갈릴 때가 많아서 팀원들이랑 회의하다가 시간이 다 가기도 해. 나도 예전에 이거 구분하느라 동료랑 한 시간 넘게 토론했던 적이 있는데, 지금 생각하면 좀 웃기기도 하다.


2. 2015년~2018년: 관심사의 분리, Presentational & Container 패턴

프로젝트가 좀 더 커지면서 개발자들은 새로운 문제에 직면했어. “UI 그리는 코드랑 데이터를 가져오는 로직이 섞여 있으니까 너무 복잡해!”라는 거였지. 이때 혜성처럼 나타난 분이 리덕스(Redux)를 만든 댄 아브라모프(Dan Abramov)야. 그가 제안한 방식이 바로 Presentational & Container 패턴이지.

이 패턴은 역할을 딱 두 개로 나눠.

  1. Presentational 컴포넌트: “어떻게 보일 것인가”에만 집중해. 데이터가 어디서 오는지 관심 없고, 그냥 props로 받은 걸 예쁘게 보여주기만 해. 스타일시트(CSS)도 주로 여기서 관리해.
  2. Container 컴포넌트: “어떻게 동작할 것인가”를 담당해. API로 데이터를 가져오고, 상태(state)를 관리하고, 비즈니스 로직을 처리한 다음 Presentational 컴포넌트에 데이터를 넘겨주는 역할을 하지.

예를 들어 ‘여행 일정 플래너’ 앱을 만든다면, 일정을 서버에서 받아오는 건 ScheduleContainer가 하고, 그 데이터를 받아서 화면에 리스트로 그려주는 건 ScheduleList라는 Presentational 컴포넌트가 하는 식이야.

이렇게 나누니까 코드가 훨씬 깔끔해졌어. 로직만 수정하고 싶으면 Container를 보고, 디자인만 바꾸고 싶으면 Presentational을 보면 됐으니까. 하지만 단점도 있었어. 컴포넌트 파일이 두 배로 늘어나고, props를 계속 아래로 전달해야 하는 ‘Props Drilling’ 문제가 심해졌지. 결국 댄 아브라모프도 나중에는 “이 패턴 너무 맹신하지 마세요”라고 말하기까지 했어.


3. 2018년~현재: 혁명적인 변화, Custom Hook 패턴의 시대

2018년 말, 리액트에 Hook(훅)이 도입되면서 react component 설계 패턴은 완전히 뒤바뀌었어. 클래스형 컴포넌트가 지고 함수형 컴포넌트가 대세가 되었지. 그러면서 Container 컴포넌트가 하던 역할을 Custom Hook이 대신하기 시작했어.

내가 가장 좋아하는 방식이기도 한데, 로직만 쏙 뽑아서 별도의 함수(훅)로 만드는 거야. 예를 들어 ‘음악 플레이어’를 만든다고 해보자.

// 재생, 정지 로직을 담은 커스텀 훅
function useMusicPlayer() {
  const [isPlaying, setIsPlaying] = useState(false);
  const togglePlay = () => setIsPlaying(!isPlaying);
  // ...더 복잡한 재생 로직들
  return { isPlaying, togglePlay };
}

// UI를 담당하는 컴포넌트
function MusicPlayerUI() {
  const { isPlaying, togglePlay } = useMusicPlayer(); // 훅 하나로 로직 가져오기!
  return (
    <div>
      <button onClick={togglePlay}>{isPlaying ? '멈춤' : '재생'}</button>
    </div>
  );
}

어때? Container 컴포넌트를 따로 만들 필요 없이 로직만 따로 관리할 수 있어서 파일 구조가 훨씬 단순해졌지. react component 설계 패턴 중에서 현재 가장 많이 쓰이고 권장되는 방식이야. 로직을 재사용하기도 너무 편해졌어. 다른 컴포넌트에서도 useMusicPlayer만 불러오면 똑같은 기능을 쓸 수 있으니까!


4. UI 개발의 극단적인 분리: VAC(View Asset Component) 패턴

최근에는 UI 개발자와 로직 개발자의 협업을 더 극대화하기 위해 VAC 패턴이라는 것도 쓰이곤 해. 이건 로직이 들어있는 컴포넌트에서 아예 JSX(마크업)를 제거해 버리는 방식이야.

로직 컴포넌트에서는 데이터랑 이벤트 핸들러를 싹 모아서 객체(Props Object)로 만들어. 그리고 그걸 그대로 VAC라고 부르는 순수 UI 컴포넌트에 전달하는 거지.

예를 들어 ‘운동 기록 관리’ 컴포넌트라면:

  • 로직 컴포넌트는 오늘 운동한 시간 계산, 서버 저장 함수 등을 준비해.
  • 이 정보들을 vacProps라는 이름으로 묶어서 WorkoutView 컴포넌트에 넘겨.
  • WorkoutView는 받은 데이터를 뿌려주기만 해. 여기엔 if 문이나 map 같은 복잡한 제어 로직도 최소화하려고 노력하지.

이 패턴의 장점은 디자인 수정이 들어왔을 때 로직 개발자를 건드릴 필요가 거의 없다는 거야. UI 개발자가 마크업만 슥슥 고치면 되거든. 다만 소규모 프로젝트에서는 오히려 관리가 더 힘들 수도 있어. 나도 큰 규모의 협업 프로젝트에서는 써봤는데, 확실히 역할 분담은 명확해지더라고. 하지만 작은 토이 프로젝트라면 배보다 배꼽이 더 커질 수 있으니 주의해야 해!


5. 마치며: 어떤 패턴이 정답일까?

자, 지금까지 react component 설계 패턴의 역사를 훑어봤는데 어떤가요? “그래서 지금 당장 뭘 써야 해?”라는 질문이 목 끝까지 차올랐을텐데…

솔직히 말하면 정답은 없습니다. (이게 제일 어려운 말이지? 미안해!) 프로젝트의 규모, 팀원들의 숙련도, 그리고 디자인 시스템의 존재 여부에 따라 최적의 선택은 달라져.

내가 추천하는 순서는 이거야.

  1. 일단 컴포넌트를 만들고 기능 구현에 집중해 봐.
  2. 그러다 코드가 너무 길어지면 Custom Hook으로 로직을 분리해 봐. (이것만 해도 80%는 해결돼!)
  3. 공통으로 쓰이는 UI 요소가 많아지면 아토믹 디자인의 원리를 빌려와서 공통 컴포넌트(Common Components) 폴더를 만들어 관리해 봐.
  4. 협업 규모가 엄청 크고 UI와 로직의 충돌이 잦다면 그때 VAC 같은 패턴을 고민해 보는 거지.

사실 나도 2024년 이후에 나오고 있는 최신 서버 컴포넌트(Server Components) 기반의 패턴들에 대해서는 아직 공부 중이야. 리액트는 정말 빠르게 변하더라고. 내가 모르는 부분도 아직 많지만, 우리가 오늘 이야기한 이 역사적인 흐름만 잘 이해하고 있어도 새로운 기술을 습득하는 데 큰 도움이 될 거야.

오늘 내 이야기가 네 리액트 여행에 작은 나침반이 되었으면 좋겠다. 코딩하다 막히면 언제든 물어봐! 우리 같이 즐겁게 개발하자고. 파이팅!

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다