프론트엔드/React

리액트의 기본 3요소 (Virtual DOM, JSX, 컴포넌트)

학습하는 청년 2024. 6. 1. 16:53

최종 수정 : 2024-06-01

리액트의 기본 3요소

1. Virtual DOM

# 패키지

리액트 프로젝트는 항상 react와 react-dom 패키지가 필요하다.

  • react : 리액트 앱이 동작하는 환경과 무관하게 공통으로 사용하는 기능을 제공한다.
  • react-dom/client 등의 렌더러 : 앱이 동작하는 환경(플랫폼)에 종속적인 기능을 제공하는 데 특화된 패키지

  • CSR(client-side rendering) 방식으로 동작하는 앱 : react와 react-dom/client 패키지 조합
  • SSR(server-side rendering) 방식으로 동작하는 앱 : react와 react-dom/server 패키지 조합

 

react와 렌더러 패키지의 경계에는 가상 DOM이라는 메커니즘이 자리 잡고 있다. 가상 DOM의 의미를 알려면 먼저 XML 마크업 언어를 알아야 한다.

 

# XML 마크업 언어

쉽게 작성할 수 있고, 컴퓨터도 그 의미를 쉽게 파악할 수 있는 특수한 형식의 텍스트를 마크업 언어(markup language)라고 한다.

 

웹 분야에서 문서(document)는 마크업 언어로 작성한 텍스트가 담긴 파일이나 인터넷 망을 통해 전송되는 스트림(stream)을 의미한다. 즉, XML 형식으로 작성한 문자열은 XML 문서, HTML 형식으로 작성한 문자열은 HTML 문서라고 한다. 이 문서들은 여러 가지 요소(element)로 구성된다.

 

# 문서 객체 모델(DOM, document object model)

웹 브라우저는 HTML 형식의 문자열을 하ㅘ면에 출력할 때 문자열을 분석(parsing)하여 어떤 특별한 형식의 자바스크립트 객체 조합으로 바꾼다. 이 특별한 형식의 자바스크립트 객체는 모두 자신의 특징에 맞는 인터페이스를 구현하는데, 이들을 총칭하여 문서 객체 모델(DOM)이라고 한다.

 

웹 브라우저의 자바스크립트 엔진은 window라는 이름의 전역 변수를 기본으로 제공한다. window는 웹 브라우저의 특정 웹 페이지를 의미하는 객체인데, window 객체는 Window 타입 객체로서 Window 타입을 브라우저 객체 모델(BCM, browser object model)이라고 한다.

 

1) document 객체

웹 페이지가 HTML 문서를 화면에 출력할 때 window 객체는 document라는 이름의속성 객체로 HTML 문서 기능을 사용할 수 있게 해준다. 오직 1개만 있어야 하므로, window.document(혹은 줄여서 document)는 html요소를 의미한다.

 

2) document.head와 document.body 객체

HTML 문서의 html 요소는 head와 body 태그를 1개씩만 가질 수 있다.

 

3) document.createElement 메서드

인터페이스는 객체가 제공해야 할 여러 기능을 구체적으로 정의한 규약이다. 웹 브라우저는 DOM의 다양한 인터페이스를 각각의 목적게 맞게 구현한 객체로 생성할 수 있도록 document.createElement 메서드를 제공한다.

 

4) HTMLElement 인터페이스

HTMLElement는 모든 종류의 HTML 요소가 구현하는 인터페이스이다. 이름이 얼핏 복잡해 보이지만 HTML요소명Element 형태의 이름 규칙을 발견할 수 있다.

 

자바스크립트로 HTML 요소를 웹 페이지에 나타나게 하려면 createElement와 appendChild 과정을 거쳐야 한다.

let p = document.createElement('p'); // <p> 요소 생성
// <p> 요소를 <body>의 마지막 자식 요소로 추가
document.body.appendChild(p); // 렌더링

createElement가 HTML DOM 요소 객체를 생성해 주는 역할을 한다면, appendChild는 생성된 DOM 객체를 웹 브라우저 화면에 출력해 주는 역할을 한다. DOM 객체를 웹 브라우저 화면에 나타나게 하는 것을 렌더링(rendering)이라고 한다.

 

# 리액트를 사용하는 프런트엔드 개발(가상 DOM)

웹 브라우저의 document.createElement와 유사하게 react 패키지는 createElement라는 함수를 제공한다.

const p = React.createElement('p');
const pVirtualDom = React.createElement('p', null, 'Hello world!');

root.render(pVirtualDOM)

리액트에서 pVirtualDOM이 화면에 나타나려면 document,body.appendChild가 아닌 다른 방법을 사용해야 한다. 바로, root.render 함수가 가상 DOM을 물리 DOM으로 전환해 주는 역할을 한다.

 

화면에 무엇인가를 보이게 하는 것을 렌더링이라고 하는데, 리액트에서 가상 DOM 객체의 렌더링은 react-dom 렌더러가 수행한다.

 

document.getElementById 메서드

document 객체는 id 속성과 관련하여 getElementById 메서드를 제공하는데, 이 메서드는 이미 생성된 특정 물리 DOM 객체를 찾아주는 역할을 한다. 다음 코드는 id 속성값이 'root'인 DOM 객체를 찾아낸다.
let rootDiv = document.getElementById('root');

2. JSX

리액트가 널리 사용될 수 있었던 요인에는 JSX가 있다. JSX 코드는 자바스크립트 코드라기보다 HTML 처럼 보이는데, 이는 JSX가 자바스크립트 문법에 JSX라는 새로운 문법을 추가한 형태로 동작할 수 있도록 설계되었기 때문이다.

 

JSX는 'JavaScript XML'의 줄임말로서 XML 구문에 자바스크립트 코드를 결합하는 용도로 만들어진 구문이다. React.createElement 호출 코드를 간결하게 하려고 고안한 것으로, 자바스크립트 언어를 확장하는 방식으로 구현됐다. 즉, 반환값은 가상 DOM 객체이다. 따라서 변수나 배열에 담을 수 있다.


3. Component

객체지향 언어의 원조인 스몰토크(Smalltalk)에서 유래한 매우 오래된 용어이다. 스몰토크에서 컴포넌트는 화면 UI를 처리하는 클래스를 의미한다. 컴포넌트는 model-view-controller, MVC 설계 지침에 따라 구현된 클래스여야 한다.

  • Model : 앱의 데이터 부분
  • View : 모델을 활면에 렌더링하는 부분
  • Controller : 사용자의 키보드와 마우스 입력을 수신받아 모델과 뷰에 적절한 형태로 반영하는 역할을 하는 부분

리액트에서 컴포넌트 또한 스몰토크의 컴포넌트와 개념적으로 같다. 다만, 리액트는 16.8 버전 이후 '리액트 훅(react hooks)'이라는 새로운 메커니즘을 고안했다. 리액트 팀은 가능한 한 함수 컴포넌트와 리액트 훅을 사용하라고 권한다.

 

# 리액트 컴포넌트와 사용자 컴포넌트

리액트 컴포넌트

const h1 = <h1>Hello world!</h1>

JSX 문에서 h1은 HTML 태그가 아니라 리액트가 제공하는 h1 컴포넌트다. 이런 방식으로 설계한 이유는 HTML5 태그에 해당하는 컴포넌트 이름을 일일이 임포트하지 않게 하려는 의도가 있다.

 

사용자 컴포넌트

리액트 프레임워크는 사용자 컴포넌트를 구현할 수 있게 하는 '속성'이라는 기능을 제공한다.

 

# 속성이란?

객체지향 프로그래밍에서 속성(property)은 클래스의 멤버 변수를 의미한다. 컴포넌트 또한 화면 UI를 담당하는 클래스이므로 속성을 가질 수 있다. 수시로 값이 바뀔 수 있는 것을 '가변(mutable)하다'고 말하고, 다시는 바뀌지 않는 것을 '불변(immutable)하다'고 한다. 그런데 리액트에서의 속성은 객제지향 언어의 속성과는 다른 부분이 있다.

리액트에서의 속성은 부모 컴포넌트가 자식 컴포넌트 쪽에 정보를 전달하는 목적으로 사용되며, 객테 타입의 데이터로 전달된다. 이처럼 리액트에서 객체지향 관점의 속성은 '상태(state)'라고 한다. 
객체지향 프로그래밍에서 클래스의 속성은 값을 저장하고 변경할 수 있는 기능만 하지만, 리액트에서의 속성은 해당 컴포넌트를 다시 렌더링하여 수정된 속성 값을 화면에 반영하는 기능도 있다. 즉, 객체지향 프로그래밍 속성 + 재렌더링을 의미하는 '객체 타입 변수'이다.

 

# key, ref, children

1) key 속성

같은 이름의 컴포넌트가 어려 개일 때 이들을 구분하려고 리액트 프레임워크가 만든 속성이다.

 

2) children 속성

<div>처럼 자식 요소를 포함할 수 있는 컴포넌트에서만 사용할 수 있다. React 18버전부터는 FC 타입에서 children 속성을 제거했다. 그리고 PropsWithChildren이라는 제네릭 타입을 새롭게 제공하여 children?: ReactNode 부분을 PropsWithChildren 타입으로 대체했다.

 


참고 자료

리액트 모던 웹 개발 with 타입스크립트 (p.51-87, 93-97)