본문 바로가기
C.W.K.
Stream
Lesson 01 of 08 · published

React는 라이브러리일 뿐, 프레임워크는 아니야

~22 min · React, Next.js, framework

Level 0호기심
0 XP0/68 lessons0/11 achievements
0/120 XP to next level120 XP to go0% complete

React가 책임지는 범위부터 보자

React는 화면을 컴포넌트로 나누고, 상태가 바뀌면 필요한 부분을 다시 그리는 방법을 제공해. 여기까지는 아주 강력하지. 하지만 주소에 따라 화면을 고르는 일, 서버에서 HTML을 만드는 일, 데이터를 언제 다시 읽을지 정하는 일, 코드를 묶어 배포하는 일은 React의 책임이 아니야. 작은 예제에서는 이 빈자리가 잘 안 보이지만, 제품을 만들기 시작하면 바로 튀어나와.

빈자리를 직접 메우면 생기는 일

  • 라우팅 도구를 고르고 중첩 레이아웃 규칙을 정해야 해.
  • 서버 렌더링과 hydration 경계를 직접 연결해야 해.
  • 데이터의 로딩·캐시·무효화 규칙을 팀이 새로 만들어야 해.
  • 빌드와 배포 환경까지 하나의 운영 체계로 묶어야 해.

각 도구가 나쁜 게 아니야. 문제는 도구 사이의 계약을 프로젝트마다 다시 발명해야 한다는 거지. 한 사람이 떠나면 그 계약을 설명해 줄 사람도 함께 사라질 수 있어.

Next.js가 가져가는 책임

Next.js는 그 빈자리에 강한 관례를 둬. 폴더가 주소가 되고, 컴포넌트는 기본적으로 서버에서 실행되며, 데이터와 이미지와 글꼴을 위한 기본 도구가 함께 움직여. 대신 프레임워크의 방식부터 배워야 해. 이건 자유를 빼앗는 거래가 아니라, 이미 잘 알려진 문제를 매번 다시 풀지 않기 위한 거래야.

라이브러리와 프레임워크의 진짜 차이

라이브러리는 필요할 때 내가 불러. 프레임워크는 정해진 자리에 코드를 놓으면 그쪽에서 나를 불러. 제어가 뒤집히는 만큼 팀 전체가 같은 구조를 상속받아. 객체지향 관점에서 보면 Next.js의 핵심 가치는 기능 목록보다 이 상속 구조에 있어.

새 요구가 생길 때마다 패키지부터 찾지 말고, 라우팅·렌더링·데이터·배포 가운데 어느 책임인지 먼저 이름 붙여 봐. Next.js가 이미 맡은 책임이면 내장 관례로 풀고, 정말 비어 있는 자리일 때만 외부 도구를 들여와. 도구를 고른 사람보다 그 도구 사이의 계약을 계속 돌볼 사람이 누구인지가 더 중요한 질문이야. 관례가 많다고 항상 큰 앱에만 맞는 건 아니야. 작은 앱도 인증과 배포가 들어오는 순간 같은 결정을 만나. 반대로 화면 하나짜리 실험이라면 프레임워크 초기 학습비가 더 클 수 있어. 기능 수가 아니라 반복해서 떠안을 통합 책임의 수로 판단해.

같은 요구를 React만으로 조립한 작은 예와 Next.js 관례로 만든 예를 나란히 놓고, 코드 줄 수보다 결정 목록을 비교해 봐. 라우터·빌드·서버 렌더링·배포의 주인이 각각 누구인지, 새 팀원이 문서 없이 찾을 수 있는지 확인하면 프레임워크가 줄인 통합 비용이 보여.

Code

React만 사용했을 때의 빈자리·tsx
import { useState } from 'react';

// React는 컴포넌트와 다시 렌더링하는 방법만 제공해.
export function App() {
  const [count, setCount] = useState(0);
  return <button onClick={() => setCount(c => c + 1)}>{count}</button>;
}

// 답이 없는 것:
//   - 이 HTML이 hydration 전에 어떻게 브라우저에 도착해?
//   - /about으로 어떻게 이동해?
//   - 서버에서 데이터는 어떻게 읽어?
//   - 번들링은 어떻게 해?
//   - 배포는 어떻게 해?
같은 컴포넌트를 Next.js 앱에 넣었을 때·tsx
// app/page.tsx — Next.js가 위 질문에 모두 답해
import Counter from './Counter';

export default async function Page() {
  const initial = await fetch('https://api.example.com/count', {
    next: { revalidate: 60 },
  }).then(r => r.json());

  return <Counter initial={initial.value} />;
}

External links

Exercise

작은 Vite+React 앱을 Next.js로 옮긴다고 가정해. 라우팅·렌더링·데이터·빌드·배포 가운데 넘길 책임 다섯 개와 각각을 받는 Next.js 파일이나 관례를 적어 봐.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.