목차
React 는 "프레임워크"일까 ? "라이브러리"일까 ?
라이브러리
: 개발자가 특정 기능을 수행할 수 있도록 미리 만들어진 코드 모음으로, 개발자가 직접 호출하며 프로그램의 흐름을 개발자가 제어한다.
프레임워크
: 재사용 가능한 일반적인 구조와 기능을 제공하며, 그 구조 안에서 코드를 작성하도록 유도하는 소프트웨어로, 프로그램의 제어 흐름을 프레임워크가 주도하며, 개발자는 특정 지점에서만 코드를 삽입한다.
즉, 라이브러리는 도구상자, 프레임워크는 앱의 뼈대와 흐름을 제공하는 틀이라는 공식적 정의 기준의 차이이다.
그렇다면, 리액트는 프레임워크일까 ? 라이브러리일까 ?
바로, 라이브러리이다.
리액트 (React) 는 사용자 인터페이스 (UI)를 구성하는 컴포넌트 단위의 화면을 만든다. 즉, 프로그램 전체의 흐름이나 데이터 관리를 하지 않고, 버튼, 입력폼, 리스트, 페이지 같은 화면 요소를 조립하고 랜더링하는 역할만을 수행한다.
라우팅, 상태관리, 데이터 요청, 빌드 도구 등은 React가 제공하지 않아 이는 외부 라이브러리로 해결한다.
라우팅은 react-router, 상태관리는 zustand / Redux, HTTP 요청 및 데이터 패칭은 axios / react-query 를 사용한다.
이처럼 리액트는 화면을 구성하는 역할만 담당하기 때문에, 페이지 이동이나 화면 갱신과 같은 기능은 별도의 라이브러리를 활용해야 한다.
이때 주로 만들어지는 웹 앱 구조가 SPA (Signle Page Application) 이다.
SPA (Signle Page Application) 이란 ?
SPA (Single Page Application)는 한 번 로드한 페이지 안에서 화면만 교체하며 동작한다. 즉, 페이지를 이동할 때 전체 HTML을 새로 받지 않고, 필요한 부분만 갱신하므로 화면 전환이 빠르고 앱처럼 자연스럽게 동작한다.
하지만, SPA에도 단점이 존재한다. SEO (Search Engine Optimization, 검색 엔진 최적화) 측면에서, 검색엔진이 초기 HTML만 보고 콘텐츠를 충분히 인덱싱하지 못할 수 있다. 이를 보완하기 위해 등장한 것이 SSR (Sever Side Rendering)과 SSG (Static Site Generation)이다.
SSR (Server Side Rendering)
: 브라우저가 요청을 보내면, 서버에서 해당 페이지의 HTML을 동적으로 생성해서 전달하는 방식이다.
브라우저가 특정 URL로 요청을 보내면, 서버는 React 같은 라이브러리를 사용해 페이지를 미리 렌더링하여 완성된 HTML을 만들어 전달한다. 브라우저는 이 HTML을 즉시 화면에 표시하고, 필요한 자바스크립트를 내려받아 페이지를 동적으로 조작하며 인터랙티브하게 만든다.
검색 엔진 크롤러가 HTML을 바로 읽을 수 있도록 한다는 장점이 있지만, 서버가 매 요청마다 HTML을 생성해야 하기 때문에 서버의 부하가 증가할 수 있다. 또한, 빌드 시점이 아닌 요청 시점에 렌더링하기 때문에 실시간 데이터 처리에는 좋지만 캐싱 전략이 필요하다.
SSG (Static Site Generation)
: 페이지를 미리 생성하여 정적 파일로 배포하는 방식이다. 이는 서버 요청이 있어도 HTML은 이미 생성되어 있는 파일이다.
개발자가 사이트를 빌드할 때, 각 페이지를 HTML 파일로 미리 생성한다. 배포 시 서버에는 정적 HTML 파일만이 존재한다. 이 상태로 브라우저가 요청을 보내면, 서버는 미리 만들어진 HTML을 바로 전달하고, 필요시 자바스크립트가 로드되어 SPA처럼 인터랙티브하게 작동한다.
서버의 부하가 거의 없고, HTML이 이미 완성되어 있어 검색 엔진이 쉽게 인덱싱될 수 있다는 장점이 있지만, 변경사항이 존재하면 재빌드를 해주어야 하기 때문에 실시간 데이터 반영이 어렵다는 단점이 있다.
-> SSR은 요청 시 서버가 HTML을 생성하고, SSG는 미리 HTML을 생성해 배포하는 차이이다.
위에서 말했듯, React에서 화면을 구성하는 기본 단위는 컴포넌트이다. 요즘은 특히 함수형 컴포넌트가 주로 사용된다.
함수형 컴포넌트와 상태 / 속성
함수형 컴포넌트는 말 그대로 자바스크립트 함수이다. 이 함수는 입력으로 props를 받고, 출력으로 JSX를 반환한다.
쉽게 말해, 주어진 데이터를 받아서 화면에 어떤 모양으로 보여줄지 계산해 돌려주는 역할이다.
상태 (state)
컴포넌트가 기억해야 하는 값이다.
예를 들어, 버튼 클릭 횟수, 입력 폼 내용 등 변할 수 있는 값을 state로 관리한다.
useState 를 이용하여 state를 만들고, setter 함수를 호출하면 React가 리렌더링을 트리거 해 화면을 다시 그려준다.
속성 (props)
부모 컴포넌트가 자식으로 내려오는 읽기 전용 데이터를 말한다.
자식 컴포넌트는 이 값을 변경할 수 없고, 화면 표시용으로만 사용한다.
그렇다면, 언제 리렌더링될까 ?
- 내 state가 변경될 때
- state 는 컴포넌트 내부에서 기억하고 있는 값이다. 이러한 값이 바뀌면 React가 리렌더링을 수행한다.
- 부모가 리렌더링 되어 새 props가 내려올 때
- 부모가 다시 렌더링되어 props가 바뀌면, 자식 컴포넌트도 새 데이터로 다시 렌더링된다.
- 구독한 Context값이 바뀔 때
- context는 전역 상태처럼 여러 컴포넌트에서 공유할 수 있는 데이터이다. 이 값이 바뀌면 그 값을 구독하고 있는 컴포넌트들이 자동으로 리렌더링된다.
- context를 구독한다 = 커포넌트가 context가 바뀌면 알림을 받고, 반응하도록 등록되어 있다.
- key가 바뀔 때
- key는 React가 리스트나 컴포넌트를 구분하는 값으로, 완전히 바뀌면 React는 이전 컴포넌트를 버리고 새로운 컴포넌트로 교체한다.
리렌더링은 Virtual DOM 을 상요해 효율적으로 화면을 업데이트 한다.
Virtual DOM
: 화면의 현재 상태를 담은 설계도(스냅샷)라고 생각하면 된다. 상태가 바뀌면 렌더링 단계에서 새 설계도 (Virtual DOM)을 만들고, React가 이전 설계도와 새 설계도를 비교해서 바뀐 부분 (Diff) 만 실제 DOM에 반영하게 된다. 매번 전체를 갈아엎지 않고, 필요한 최소 조각만을 업데이트 하니 매우 효율적이라고 볼 수 있다.
이때, 리스트를 렌더링한다면 이전/다음 항목을 정확히 매칭해서 최소 변경만 하는 것이 효율적이기 때문에 고유한 id 값인 key를 사용하는 것을 권장한다.
리액트의 동작 방식
- 상태 및 props 가 변경되었음을 감지
- 렌더링 단계 : 함수형 컴포넌트를 실행해 새 JSX (=VDOM 설계도)를 생성한다.
- 비교 단계 :이전 VDOM과 Diff를 찾는다.
- 커밋 단계 : 바뀐 곳만 실제 DOM을 패치하고, 브라우저를 다시 업데이트 한다.
- 효과 실행: useEffect / useLayoutEffect 를 이용하여 이전 효과를 정리하고, 새 효과를 실행한다.
React의 일반적인 폴더 구조
많은 리액트 프로젝트에서 참고하는 기본 구조에 대해서 살펴보자.
src/
┣ assets/
┣ components/
┣ pages/
┣ hooks/
┣ context/
┣ utils/
┣ types/
┣ apis/
┣ App.tsx
┗ main.tsx
- assets/ : 이미지, 아이콘, CSS와 같은 정적 파일
- componets/ : 재사용 가능한 작은 단위의 UI 공용 컴포넌트
- pages/ : 라우팅과 연결되는 페이지 단위의 큰 화면 컴포넌트
- hooks/ : 재사용 가능한 로직 (커스텀 훅)을 함수로 묶어둔 폴더
- context/ : context API로 전역 데이터(상태)를 관리
- utils/ : 자주 쓰이는 공통 함수 관리
- types/ : TypeScript 프로젝트라면 탕입 정의를 모아두는 폴더
- apis/ : 서버와 통신하는 코드 (axios, fetch 등)를 모아두는 폴더
- App.tsx : 앱의 뼈대 (루트 컴포넌트) 역할을 한다.
- main.tsx : React 앱의 진짜 시작점으로, App.tsx 를 DOM에 붙여준다.
'Language & Framework > React' 카테고리의 다른 글
| [T/S] Navbar에서 로그인 상태에 따른 isPending 동작 오해 (React Query 상태 혼동) (0) | 2025.11.07 |
|---|