Skip to Content
WebReactReact 기초01. React는 왜 필요한가

이번 편의 결과물: (코드 없음) 카운터 예제로 명령형 DOM 조작과 선언적 UI의 차이를 비교해 이해합니다. · 다루는 개념: 명령형 DOM 조작의 한계, 선언적 UI, 컴포넌트란 무엇인가, React의 위치(SPA·프레임워크 맥락)

이 편에서 만드는 파일

이 편은 이론 편이라 로컬에 파일을 만들지 않습니다. bookshelf 프로젝트 생성은 03편에서 시작합니다. 아래 예제는 브라우저 안에서 바로 실행되는 코드로만 확인합니다.

개념 정리

명령형 DOM 조작

지금까지 브라우저에서 화면을 바꾸는 방식은 대부분 명령형(imperative)이었습니다. “어떤 상태가 되어야 하는가”가 아니라 “어떤 순서로 DOM을 조작해야 하는가”를 하나씩 지시합니다.

단계명령형 코드가 하는 일
1document.querySelector로 바꿀 요소를 찾는다
2현재 값을 변수나 요소 속성에서 읽는다
3계산한 새 값으로 textContent, className 등을 직접 갱신한다
4관련된 다른 요소가 있다면 그 요소도 각각 찾아서 똑같이 갱신한다

문제는 3~4번입니다. 화면에 같은 값을 보여주는 요소가 여러 개면, 하나를 빠뜨리고 갱신하지 않는 실수가 쉽게 생깁니다. 상태(값)와 화면(DOM)이 코드 곳곳에서 수동으로 동기화되기 때문입니다.

선언적 UI

선언적(declarative) 방식은 “지금 상태가 이렇다면 화면은 이런 모습이어야 한다”는 규칙만 적습니다. 상태가 바뀌면 그 규칙에 따라 화면을 다시 계산하는 일은 라이브러리(React)가 맡습니다. 개발자는 DOM을 직접 찾아가서 갱신하는 코드를 쓰지 않습니다.

구분명령형선언적(React)
화면 갱신 방법바뀐 부분을 직접 찾아 수정상태 → 화면 매핑 함수를 다시 실행
동기화 실수갱신 누락 가능상태 하나만 바꾸면 관련 화면 전체 갱신
코드가 답하는 질문”어떻게 바꿀까""지금 상태에서 무엇을 보여줄까”

컴포넌트란 무엇인가

컴포넌트는 입력(props)을 받아 화면 구조(JSX)를 반환하는 함수입니다. 버튼 하나, 카드 하나처럼 작은 단위를 함수로 만들어 두면 여러 곳에서 재사용할 수 있습니다. bookshelf 앱에서 책 한 권을 보여주는 카드가 좋은 예입니다. 책이 여러 권이어도 카드 컴포넌트 하나만 만들고 데이터만 다르게 넣어 재사용합니다.

React의 위치

React는 UI를 만드는 라이브러리입니다. 프레임워크와 달리 라우팅·상태 관리·데이터 요청 같은 기능을 기본 제공하지 않고, 필요한 부분만 다른 패키지(React Router, TanStack Query 등)로 조합합니다. 이 과목에서 만드는 bookshelf는 페이지 이동 없이 한 화면 안에서 모든 상호작용이 일어나는 SPA(Single Page Application) 구조입니다.

용어의미
라이브러리필요한 기능을 골라 가져다 쓴다(React)
프레임워크정해진 구조 안에서 코드를 채운다(Next.js 등)
SPA페이지 전체를 다시 불러오지 않고 한 문서 안에서 화면을 갱신하는 앱 구조

실습

브라우저에서 바로 실행되는 예제로 명령형 방식의 한계를 확인합니다.

let count = 0;

const countLabel = document.querySelector('#count-label');
const countStatus = document.querySelector('#count-status');
const incrementButton = document.querySelector('#increment');

function render() {
countLabel.textContent = count;
countStatus.textContent = count === 0 ? '시작' : count + '번 눌렀습니다';
}

incrementButton.addEventListener('click', () => {
count = count + 1;
render();
});

render();

count를 표시하는 곳이 countLabel, countStatus 두 곳입니다. render 함수 안에서 두 곳을 모두 갱신하도록 직접 챙겨야 합니다. 셋째 표시 위치가 생기면 render 함수를 또 고쳐야 합니다.

React라면 같은 화면을 아래처럼 “상태에 따라 무엇을 보여줄지”만 적습니다(아직 실행 환경이 없으므로 코드만 읽어봅니다. 실제 실행은 03편부터입니다).

function Counter() { const [count, setCount] = useState(0); return ( <div> <p>현재 값: {count}</p> <p>상태 요약: {count === 0 ? '시작' : `${count}번 눌렀습니다`}</p> <button onClick={() => setCount(count + 1)}>+1</button> </div> ); }

count 값이 바뀌면 Counter 함수가 다시 실행되어 반환하는 화면 전체가 새로 계산됩니다. countLabel, countStatus를 따로 찾아가서 갱신하는 코드가 없습니다. useState는 08편에서 다룹니다.

직접 해보기

  1. 위 명령형 카운터 예제에 “-1” 버튼을 추가해 값을 감소시켜 봅니다. 단, count가 음수로 내려가지 않게 합니다.
  2. 감소 버튼을 눌러 count가 0이 되면 countStatus가 다시 “시작”으로 보이는지 확인합니다.

정답 보기

<!-- index.html --> <div id="app"> <p>현재 값: <span id="count-label">0</span></p> <p>상태 요약: <span id="count-status">시작</span></p> <button id="increment">+1</button> <button id="decrement">-1</button> </div>
// index.js let count = 0; const countLabel = document.querySelector('#count-label'); const countStatus = document.querySelector('#count-status'); const incrementButton = document.querySelector('#increment'); const decrementButton = document.querySelector('#decrement'); function render() { countLabel.textContent = count; countStatus.textContent = count === 0 ? '시작' : count + '번 눌렀습니다'; } incrementButton.addEventListener('click', () => { count = count + 1; render(); }); decrementButton.addEventListener('click', () => { count = Math.max(0, count - 1); render(); }); render();

자주 하는 실수

증상원인고치는 법
값은 바뀌었는데 화면 일부만 갱신됨표시 위치 중 하나를 갱신 코드에서 빠뜨림상태를 표시하는 모든 요소를 한 render 함수 안에 모은다
React를 “무조건 빠른 라이브러리”로 오해선언적 방식의 장점을 성능으로만 이해핵심은 속도가 아니라 “상태-화면 동기화를 대신 처리”하는 점이다
React를 프레임워크로 부름라우팅·상태 관리가 기본 포함된 도구로 착각React는 UI 라이브러리이며 나머지는 별도 패키지로 조합한다

확인 문제

문제 14지선다
명령형 DOM 조작 방식의 한계로 가장 적절한 것은?
문제 24지선다
선언적 UI 방식에서 개발자가 주로 작성하는 것은?
문제 34지선다
React 컴포넌트를 가장 정확히 설명한 것은?
문제 44지선다
React와 프레임워크(예: Next.js)의 차이를 옳게 설명한 것은?

참고 자료

Last updated on