JS

[JS] JSX, 엘리먼트

easy-6 2025. 3. 15. 00:15

○  엘리먼트 

어떤 물체를 구성하는 성분 즉 리액트의 엘리먼트는 리액트 앱을 구성하는 요소이며, 리액트 앱을 구성하는 가장 작은 블록들을 엘리먼트라고 부름 .

* 리액트 엘리먼트는 DOM 엘리먼트의 가상 표현 

* 리액트 엘리먼트는 자바스크립트 객체 형태로 존재

예시로 들 수 있자면 컴포넌트 유형(예시 : button )과 속성 ( 예시 :  color)

리엑트 엘리먼트 -> DOM 엘리먼트 

// 엘리먼트 

{
 type : 'button',
 	props{
 		className: 'bg-green',
 		childredn :{
        	type: 'b',
            props: {
            children: "Hello, element!"
            }
 		}
 	}
 
}

// 엘리먼트가 렌더링 된 모습

<button class='bg-green'>
	<b>
    	Hello, element! 
    </b>
</button>

○ 엘리먼트의 특징 

불변성 :: 말 그대로 변하지 않는 성질

리액트에서 엘리먼트를 생성 후 children이나 attributes를 바꿀 수 없음 

 

예시 :: 붕어빵 틀을 만든 후 붕어빵이 구워져 나오는 것을 본 뒤 붕어빵의 모습은 바뀌지 않음 

 

꼬리 질문 :: 그렇다면 화면에 변경된 엘리먼트는 어떻게 보여줘???? 

>> 새로운 Virtual DOM을 생성하고, 이전 Virtual DOM과 비교하여 변경된 부분만 실제 DOM에 업데이트한다

 

개인적 생각 :: 아마 React의 SPA(Single Page Application)특징과 비슷한 것 같다 

SPA는 한 페이지에서 component를 사용해서 해당 component의 내용을 보여준다. 

결국 새로운 엘리먼트를 만든 후 변경할 엘리먼트와 교체한다는 부분은 SPA에서 component만 바꿔 사용한다는게 비슷해 보이긴 한다. 

 

ㄴ> 하지만 찾아본 결과 위의 개인적 생각은 오해를 부를 수 있는 생각이였다.
AI를 통해 질문한 결과 "필요한 부분만 업데이트한다"는 점에서는 유사해 보일 수 있지만, 그 의미와 적용 범위는 다르다는 답변이 나왔다.

 

핵심 공통점 정리

  • 두 기술 모두 전체 페이지를 다시 로드하지 않고 변경된 부분만 업데이트한다는 점에서 공통점이 있다.( 부분 업데이트 )

핵심 차이점 정리

리엑트의 Virtual DOM Diffing (엘리먼트 교체)

[Render Cycle]

이전 Virtual DOM:
         A
       /   \
      B     C
           / \
          D   E

새 Virtual DOM:
         A
       /   \
      B     C
           / \
          D   F

Diffing 결과:
- E가 F로 변경되었음

실제 DOM 업데이트:
- 오직 E → F로 변경된 부분만 업데이트

 

 

SPA (Single Page Application)의 Component 업데이트

[전통적인 Multi-Page App]
사용자 클릭  → 전체 HTML 페이지 새로고침

[SPA]
사용자 클릭  → 클라이언트 사이드 라우팅 발생
           → 필요한 컴포넌트(뷰)만 동적으로 교체
           → 페이지의 나머지 부분(헤더, 사이드바 등)은 그대로 유지

 

  • React의 Virtual DOM Diffing:
    • 목적: UI의 세부 요소를 아주 정밀하게 비교해서 변경된 부분만 실제 DOM에 반영.
    • 적용 범위: 단일 렌더링 사이클 내의 Virtual DOM 비교 및 최소 DOM 조작.
  • SPA의 Component 업데이트:
    • 목적: 전체 페이지를 새로 로드하지 않고, 사용자의 내비게이션에 따라 필요한 뷰(컴포넌트)만 동적으로 교체.
    • 적용 범위: 애플리케이션 전체의 페이지 전환 및 라우팅 방식.

 

React는 불변성을 가진 엘리먼트를 매 렌더링 시 새로 생성하고, 이전 가상 DOM과 비교하여 변경된 부분만 실제 DOM에 반영합니다. 이 과정은 React 내부의 최적화 전략으로, SPA에서 전체 페이지를 다시 로드하지 않고 필요한 컴포넌트만 업데이트하는 개념과는 구분

 

두 개념은 "변경된 부분만 업데이트한다"는 공통점이 있지만, React의 diffing은 UI 업데이트의 세부 기술이고, SPA는 애플리케이션 전반의 구조 및 내비게이션 방식이라는 점에서 구분

 

 

 

○  JSX 

JSX는 영어로 A Syntax extension to JavaScript 라는 의미를 갖고 있다. 

문장을 해석하면 JavaScript의 확장 문법이라는 뜻이다. 

 

그렇다면 JSX는 JavaScript와 XML/HTML을 합친 것이라고 한다. 

 

○ JSX의 역할

- JSX로 작성된 코드는 모두 자바스크립트 코드로 변환

- 리액트는 JSX 코드를 모두 createElement() 함수를 사용하는 코드로 변환

 

○ JSX의 장점

- 코드가 간결해짐

- 가독성 향상

- injection Attack을 방어함으로써 보안성이 올라감 

 

○ JSX 사용법 

- 기본적으로 모든 자바스크립트 문법을 지원 

- 자바스크립트에 XML과 HTML을 섞어서 사용 

-  중괄호를 사용하여 자바스크립트 코드를 삽입 

 

 

또한 JSX의 X는 extension이라고 볼 수 있지만 실제로는 JavaScript and XML의 앞글자를 따서 JSX라고 부른 것이다. 

 

 

 

출처 : 소플의 처음 만난 리액트

 

예시

JSX 예시  const element = <h1> Hello world! {name} <h1/>

JSX 사용하지 않았을 때 , React.createElement('div', null , `Hello world! ,${name}`);

-- 이처럼 JSX를 사용하지 않았을 때
React.createElement ('type', props, children)의 형식으로 작성 


createElement('type', props, children)
*type :: 유효한 리엑트 컴포넌트 
  ex)  태그 이름 문자열 ('div','span')또는 React 컴포넌트 {함수, 클래스, Fragment(<> ... </>)}

* props :: 해당 요소에 전달할 속성 
  ex) HTML 속성(className, id)이나 이벤트(onlick)포함

* children :: props 객체의 특별한 속성, 해당 요소의 내부의 자식 요소들을 나타냄
이때 React.createElement()의 세번째 이후 인자들은 모두 children으로 취급이 됨 
  ex) :: JSX 사용하지 않았을 때 , React.createElement('div', null , `Hello world! ,${name}`);의 경우에
  children이 `Hello world! 와 ${name}이 children이라고 볼 수 있음

 

 

 


추가 설명 

DOM(Document Ogject Model)이란?

HTML 문서를 브라우저가 이해할 수 있는 트리 구조로 표현 

즉 웹 페이지의 각 요소 아래 코드에서는 <html> <body> <div> <p>등 각 요소가 노드(Node)라는 객체로 표현되며, 이 노드들이 계층적인 트리 형태로 연결된다. 

<html>
  <body>
    <div>
      <h1>안녕하세요!</h1>
      <p>React Fragment를 사용하지 않은 예시입니다.</p>
    </div>
  </body>
</html>
html
 └── body
      └── div        <-- 불필요한 래퍼(wrapper) 요소
           ├── h1
           └── p

 

이때 Fragment를 사용하면 DOM에 불필요한 노드가 추가되는 것을 방지하면서 여러 요소를 그룹화할 수 있다. 

(메모리를 효율적으로 사용할 수 있을듯 ??? )

 

* Fragment를 사용했을 때와 사용하지 않았을 때의 예시 

 

// Frawgment 사용 x 
function App() {
  return (
    <div>
      <h1>안녕하세요!</h1>
      <p>React Fragment를 사용하지 않은 예시입니다.</p>
    </div>
  );
}

DOM 구조 
body
 └── div          <-- 불필요한 추가 요소
      ├── h1
      └── p

 

* Fragment를 사용했을 때와 사용하지 않았을 때의 예시 

// Fragment를 사용한 경우 
1. <> ... </>
function App() {
  return (
    <>
      <h1>안녕하세요!</h1>
      <p>React Fragment를 사용한 예시입니다.</p>
    </>
  );
}


2. React.Fragment ... </React.Fragment>
function App() {
  return (
    <React.Fragment>
      <h1>안녕하세요!</h1>
      <p>React Fragment를 사용한 예시입니다.</p>
    </React.Fragment>
  );
}

Fragment를 사용한 DOM의 구조 

body
 ├── h1
 └── p

 

비유

Wrapper Element (div 등 )사용 :: 물건(요소)들을 담기 위해 보따리를 하나 사용 

보따리 안에는 물건이 들어가 있지만, 역으로 물건을 꺼내기 위해서는 보따리를 한 번 더 열어야하는 상황이 있음

 

Fragment 사용 :: 보따리 없이 물건을 바로 정리 할 수 있음 

즉 물건을 꺼낼 때 보따리를 열 필요 없이 바로 물건을 꺼낼 수 있음  

 


요약 

  • : HTML 요소들이 트리 형태로 구성된 구조로, 브라우저가 페이지를 렌더링하는 기본 틀입니다.
  • 불필요한 노드 문제: <div>와 같은 태그를 사용해 여러 요소를 감싸면, 실제 DOM 트리에 불필요한 추가 노드가 생겨서 구조가 복잡해질 수 있습니다.
  • React Fragment: 이러한 불필요한 DOM 노드를 만들지 않고, 여러 요소를 하나의 컴포넌트로 그룹화할 수 있게 해줍니다.

이처럼 React Fragment를 사용하면 DOM 구조를 깔끔하게 유지하여, 불필요한 중첩을 피할 수 있고, 유지보수나 스타일링 측면에서도 이점을 제공합니다.