리액트란?
사용자 인터페이스를 만들기 위한 Javascript 라이브러리
리액트(React) 공식 홈페이지에 접속하면 위와 같은 문구로 리액트를 소개하고 있습니다. 리액트는 우선 자바스크립트 라이브러이이기 때문에 브라우저와 Node.js 환경에서 기본적으로 사용됩니다. 사용자 인터페이스, 즉 UI를 만드는 목적으로 사용하는 라이브러리이며 React(반응)라는 이름에서 알 수 있듯 사용자의 행동에 즉각적으로 반응하는 인터랙티브한 화면 개발에 효과적인 라이브러리입니다.
리액트라고 하면 웹에서 실행되는 ReactDom 기반의 일반적인 리액트를 말하는 것이고 제 블로그의 리액트 스터디 시리즈에서는 웹 UI 개발에 사용되는 React만 한정하여 설명합니다. 웹 UI 외에도 모바일 앱 개발을 위한 React Native가 있습니다.
리액트 라이브러리만 사용한다면 JQuery와 같은 라이브러리로 웹 애플리케이션에 부분적으로 포함해서 사용할 수 있지만 JQuery와 달리 한정된 특정 부분만 React만 사용해서 처리하기엔 까다롭고 난이도가 있는 편입니다. 그래서 보통 리액트 프로젝트에서는 리액트 개발을 쉽게 만들어 주는 JSX라는 자바스크립트 확장 문법을 사용하고 JSX를 자바스크립트로 컴파일해주는 babel이나 esbuild와 같은 번들러를 함께 사용한 패키지 형태로 사용합니다. 이런 경우 리액트를 라이브러리로 지칭하지 않고 패키지와 함께 프레임워크로 지칭합니다.
JSX가 뭐지?
JSX는 자바스크립트에 XML을 더한 자바스크립트 확장 문법입니다. 리액트와 함께 사용하면 자바스크립트만 사용하는 리액트에서 HTML과 같은 UI 요소를 작성하기 쉬워집니다. 자바스크립트만 사용하여 HTML을 추가하는 코드와 JSX를 사용하여 HTML을 추가하는 코드를 비교해보면 JSX를 React와 함께 사용할 때의 장점을 확실하게 알 수 있습니다.
function App() {
return React.createElement(
'h1',
{className: 'hello'},
'Hello, React!'
);
}
JavaScript
복사
Javascript만 사용한 경우
function App() {
return (
<h1 className="hello">Hello, React!</h1>
);
}
JavaScript
복사
JSX를 사용한 경우
JSX를 사용하면 위처럼 기존 HTML 작성하던 방법과 유사하게 작성하여 리액트에서 HTML 요소를 추가할 수 있습니다. 자바스크립트만 사용했을때 보다 훨씬 가독성이 좋죠?
제 블로그의 리액트 관련 모든 스터디에서는 이 JSX 문법 사용을 전제로 설명합니다.
리액트의 가상 DOM (Virtual DOM)
가상 DOM을 알아보기 전에 먼저 DOM에 대해서 알아봅시다. DOM이란, Document Object Model의 약자로 브라우저에서 HTML 코드를 화면에 랜더링하기 위해 아래와 같은 트리 형태의 구조로 변경한 것을 말합니다.
DOM 구조로 변경되면, <div>와 같은 HTML의 태그들은 DOM 트리의 하나의 노드로 위치하게 됩니다. DOM은 브라우저에서 API로 접근할 수 있기 때문에 각각의 노드들을 API를 통해 수정하거나 추가 및 삭제가 가능해집니다. 바닐라 자바스크립트로 개발할때 주로 사용하던 document.getElementById()와 같은 방식으로 말이죠.
DOM을 API로 직접 조작하여 다이나믹한 웹 앱을 만들 수 있겠지만 이런 방식은 데이터가 자주 변경되는 상황에서는 성능적인 문제가 발생합니다. 브라우저는 DOM의 노드나 구조가 변경될 때마다 화면 랜더링 작업을 다시 수행하기 때문입니다. 이러한 문제 해결을 위해 리액트의 가상 DOM은 아래와 같은 방법으로 처리합니다.
1.
실제 DOM을 그대로 본딴 가상 DOM을 만든다.
2.
데이터 변경이 감지되면, 가상 DOM에만 적용하고 실제 DOM과 차이점을 계산한다.
3.
계산된 최종 변경만 실제 DOM에 전달하여 적용한다.
리액트의 가상 DOM을 통해 많은 데이터 변경이 일어날때 랜더링을 반복 수행하지 않고, 계산된 최종 변경만 DOM에 적용해 단 한번만 랜더링 수행하도록 성능적인 이점을 가져갈 수 있습니다.
컴포넌트 기반 UI 개발
컴포넌트(component)란 프로그래밍에서 재사용하기 쉽게 만든 독립적인 모듈을 의미합니다. 리액트에서는 화면을 랜더링하는 요소들을 컴포넌트로 만들어서 관리하도록 짜여져 있습니다. 잘 만들어진 컴포넌트는 웹 페이지 화면 이 곳 저 곳에 재사용하여 배치할 수 있기 때문에 웹 UI 개발을 효율적으로 할 수 있도록 합니다. 최근 UI/UX 화면 디자인도 피그마나 XD에서 UI 요소를 컴포넌트 에셋으로 만들어 재사용해가며 디자인하는 추세이기 때문에 프론트엔드 개발자라면 컴포넌트를 잘 이해하고 활용할 수 있어야합니다.
React 앱은 최 상위 Root 컴포넌트와 아래에 많은 하위 컴포넌트의 조합으로 구성됩니다.
컴포넌트는 HTML로 구성되며 다른 컴포넌트를 포함 할 수 있습니다. 다른 컴포넌트를 포함할때 상위 컴포넌트와 하위 컴포넌트는 HTML처럼 부모와 자식간의 관계가 형성됩니다.
주의: 컴포넌트간에 부모 자식간의 관계를 형성한다고 해도 DOM 트리에도 부모 자식 관계가 똑같이 형성된다는 얘기는 아닙니다! 자식 컴포넌트의 구성 요소에 따라 DOM 부모 자식 관계는 달라질 수도 있습니다.
자식 컴포넌트에게 프로퍼티(props)를 할당해 데이터를 전달해 줄 수 있고 내부에 함수를 작성해 기능을 추가할 수도 있습니다. 리액트 프로젝트에서 웹 애플리케이션을 완성해 간다는 것은 각각의 컴포넌트를 만들고 배치하며 조합해가는 작업의 연속으로 생각할 수 있습니다.
싱글 페이지 애플리케이션
리액트에서는 개별 페이지(상세 페이지) 또한 컴포넌트로 만들고 함수로 링크를 연결합니다. 페이지가 전환될 때 실제로 웹 경로 이동이 되는 것이 아니라 페이지 컴포넌트를 다른 페이지 컴포넌트로 전환하여 처리합니다. 이 때문에 최상위 Root 컴포넌트에 모든 자료가 포함되어 있는 구조가 되고, 사용자는 이 Root 컴포넌트 하나만 다운받아서 랜더링하면 됩니다. 이런 웹 애플리케이션을 Single Page Application, 줄여서 SPA라고 부르죠.
보통 리액트나 Vue와 같은 웹 UI 프레임워크로 개발된 앱을 얘기할때 SPA라고 많이 부르는데 위와 같은 이유 때문입니다. SPA는 페이지 이동할때 서버에 다시 웹 리소스를 요청하지 않기 때문에 화면 전환이 끊김 없이 매끄럽게 진행됩니다. 이런 점은 사용자 경험(UX)에 좋은 영향을 끼치지만 초기 진입할때 모든 페이지 정보를 다운로드 하고 자바스크립트로 DOM을 만드는 과정이 필요하기 때문에 최초 로드되는 시간이 오래걸리는 단점이 있습니다. 이런 과정을 클라이언트측에서 랜더링을 수행한다고 해서 CSR(Client Side Rendering)이라고 합니다.
CSR의 경우 검색 엔진 최적화(SEO)와 같은 문제점이 부각되면서 최근 다시 전통적인 서버에서 랜더링하는 방식인 SSR(Server Side Rendering)이 주목받고 있습니다. 리액트도 Next.js나 Remix와 같은 프레임워크를 함께 사용하면 SSR 형태로 개발할 수 있습니다. React 18 버전 이상부터는 hydration을 사용한 CSR과 SSR을 복합적으로 사용하는 것도 가능합니다. 이러한 개념은 리액트를 시작하는 단계에서 중요한 내용이 아니므로 다른 시리즈에서 관련 내용을 자세하게 다뤄볼 예정입니다.