* React 공식 문서를 참고해 정리한 글로, v18.2.0을 따릅니다.
https://ko.legacy.reactjs.org/docs/introducing-jsx.html
01. JSX 소개
JSX는 UI가 어떻게 생겨야 하는지 설명하기 위한 JavaScript 확장 문법으로, 별도의 마크업 없이 컴포넌트로 관심사를 분리한다.
아래 코드는 함수 호출 결과인 formatName(user)을 element의 <h1>에 감싸 JSX안에 사용하였다.
JSX는 JavaScript에 가깝기에 ReactDOM은 camelCase를 사용한다.

주입 공격을 방지하는 JSX
기본적으로 React DOM은 JSX에 삽입된 모든 값을 렌더링하기 전에 이스케이프 하므로, 애플리케이션에서 명시적으로 작성되지 않은 내용은 주입되지 않습니다. 모든 항목은 렌더링 되기 전에 문자열로 변환됩니다. 이런 특성으로 인해 XSS (cross-site-scripting) 공격을 방지할 수 있습니다.
렌더링 전 이스케이프란 말의 의미가 무엇이고, 왜 XSS 공격을 방지할 수 있는건지 궁금해졌다.
이스케이프(Escape) 는 특정 문자를 브라우저가 코드로 해석하지 못하도록 안전한 문자로 변환하는 과정으로, 코드 실행을 막는것을 의미한다. HTML에서 문자는 태그나 코드로 해석이 된다.
| 기존 문자 | 이스케이프 후 문자 |
| < | < |
| > | > |
| " | " |
| ' | ' |
| & | & |
표처럼 바뀌게 되며 예로 <script> 입력 시 <script;> 로 브라우저가 인식하게 된다.
이렇게 되면 브라우저는 문자열이 아닌 텍스트로 인식하기 때문에 실행이 되지 않는다.
XSS(Cross-Site-Scripting)은 공격자가 웹 페이지에 악성 스크립트를 삽입하여 다른 사용자의 브라우저에서 실행되도록 하는 공격으로, 대표적인 웹 공격중 하나이다. 공격 코드가 서버에 저장되는 Stored XSS, URL 파라미터를 통해 실행되는 Reflected XSS, 클라이언트 JS 코드에서 발생되는 DOM Based XSS 공격이 있다.
공격자가 <script>document.cookie</script> 와 같이 입력하면 브라우저가 이를 실행하여 사용자의 쿠키를 탈취할 수 있는데,
React DOM은 렌더링 과정에서 이스케이프를 통해 스크립트를 안전한 문자로 변환하므로 특정 입력으로 HTML이나 스크립트로 실행되는 것을 방지할 수 있는 것이다.
✔️ dangerouslySetInnerHTML는 React의 자동 이스케이프를 처리를 우회하여 HTML을 직접 DOM에 삽입하는 기능이다.
예시로 마크다운과 같은 경우 입력 값을 그대로 렌더링해야 하는 상황이 존재한다. 보안 위험이 있기에 일반적으로 sanitize 과정을 거쳐 사용하며, 이 과정에서 <script> 태그나 onerror, onclick과 같은 이벤트 속성이나 URL 등 잠재적인 XSS 공격 요소가 제거된다.
02. 엘리멘트 렌더링
DOM에 엘리먼트 렌더링하기
엘리먼트는 React 앱의 가장 작은 단위로 화면에 표시할 내용을 기술한다.

React 프로젝트를 생성하면 HTML 파일에 <div id="root"></div>라는 요소가 존재한다.
React는 이 요소를 기준으로 렌더링되며, 이 DOM 노드를 Root DOM 노드라고 부른다.

main.jsx에서 createRoot()를 통해 Root DOM 노드를 생성 후, render() 메서드를 사용해 React 엘리먼트를 화면에 렌더링한다.
<StrictMode>는 개발 모드에서 잠재적 버그를 탐지하여 사이드 이팩트를 검증하고, 버전에 따른 deprecated API를 경고해주는 역할로 개발에 도움이 된다.
렌더링 된 엘리먼트 업데이트 하는 법
엘리먼트 생성 이후는 해당 자식이나 속성을 변경할 수 없다. 따라서 새로운 엘리먼트를 생성하고 root.render()로 전달해야한다.
React DOM은 해당 엘리먼트와 그 자식 엘리먼트를 이전의 엘리먼트와 비교하여 필요한 경우만 DOM을 업데이트한다. 라고 이론적으로 말하고 있다.
03. Componenets와 Props
컴포넌트를 통해 UI를 재사용 가능한 개별적인 여러 조각으로 나눌 수 있는데, props로 임의의 입력을 받은 후 React 엘리먼트를 반환하여 화면에 표시한다.
props는 속성을 나타내는 데이터로, JS 함수를 작성하여 함수 컴포넌트를 정의할 수 있다.
컴포넌트 렌더링
<div> 와 같은 DOM 태그만을 사용했는데, React 엘리먼트는 사용자 정의 컴포넌트로도 나타낼 수 있다.

React는 {name: 'GilDong'}을 props로 하여 Welcome 컴포넌트를 호출하며 Welcome 컴포넌트는 <h1>Hello, GilDong</h1> 엘리먼트를 반환한다. 이후 React DOM은 <h1>Hello, GilDong</h1> 엘리먼트와 일치하도록 DOM을 업데이트한다.
Welcome을 여러 번 렌더링할수도 있다.
읽기 전용인 props
모든 React 컴포넌트는 자신의 props를 다룰 때 반드시 순수 함수처럼 동작해야한다.
순수 함수는, 동일한 입력값에 대해 항상 동일한 결과를 출력하는 함수이다.
04. State와 생명주기
함수 컴포넌트를 클래스로 변환하기
React.Component를 확장하는 동일 이름의 ES6 class 생성하기
render()라는 빈 메서드 추가 후 함수를 해당 메서드로 이동
render()안의 props를 this.props로 변경
남아있는 빈 함수 선언 삭제
React 생명주기
컴포넌트가 생성되고, 업데이트되고, 제거될 때까지의 과정을 뜻하며 총 3단계로 이루어져 있다.
1. 마운트(mount)
컴포넌트가 처음 생성되어 화면에 나타나는 단계이다. 컴포넌트 생성 > DOM 생성> 화면 렌더링 단계로 진행이 된다.
2. 업데이트(Update)
컴포넌트가 다시 렌더링되는 단계이다. state, props 변경이나 부모 컴포넌트의 렌더링이 될 때 발생한다.
3. 언마운트(Unmount)
컴포넌트가 화면에서 제거되는 단계이다.
React Hooks에는 useEffect로 생명주기를 처리하는데,
useEffect는 렌더링 이후 실행되며 DOM 업데이트 이후 필요한 작업들을 처리하기 위해 사용된다.
| mount | useEffect(() => {}, []) |
| update | useEffect(() => {}}) |
| unmount | useEffect cleanup (return 함수) |

컴포넌트 생성 > 마운트 실행 > 컴포넌트 제거 > cleanup 실행 순으로 이루어진 코드의 예시이다.
05. 이벤트 처리하기
React는 JSX를 사용하여 문자열이 아닌 함수로 이벤트 핸들러를 전달합니다. e는 합성 이벤트입니다.
이벤트 핸들러(Event Handler)는 사용자 이벤트가 발생했을 때 실행되는 함수로, 버튼이나 클릭이 이에 해당한다.
React에서는 camelCase로 작성되며 button 이벤트 발생 시 handleClick 함수가 실행된다.

합성 이벤트(Synthetic Event)는 브라우저의 다양한 이벤트 시스템을 하나로 통일한 React 이벤트 객체이다.
크롬과 사파리 등 각 브라우저마다 이벤트 구현이 다르기에 이를 해결하기 위해 나온 시스템이며,
브라우저 이벤트 실행 시 React 합성 이벤트를 실행해 동일한 API를 제공한다.

preventDefault()는 브라우저의 기본 동작을 막는 함수이다.
브라우저는 특정 요소에서 자동으로 실행되는 기본 동작(Default action)이 존재한다.
<form>을 제출하면 페이지 새로고침되고, <a> 태그 시 해당 URL로 페이지가 이동하며 <input type="checkbox">면 체크 상태가 변경된다. 이러한 기본 동작을 막아 개발자가 의도한 로직을 실행할 수 있다.
✔️ 공식 문서는 function 방식을, 실제 React 코드에서 const 화살표 함수를 사용하는 이유?
두 방식 모두 함수로 동작한다는 점에서 동일하지만, JS 특성과 React 관례로 const를 선호하곤 한다.
가장 큰 차이점은 hoisting 여부로, function 선언은 함수 선언 이전에도 호출이 가능하지만, const 선언 함수는 선언 이후에만 사용이 가능하며 이전 호출 시 ReferenceError가 난다.
또한 React는 컴포넌트, 이벤트 핸들러, hooks 등을 같은 스타일로 관리하기 위해 const 화살표 함수 형태를 많이 사용한다.
이는 const handleClick = () => {} 형식으로 코드 스타일을 일관적으로 관리할 수 있다.
React를 사용할 때 DOM 엘리먼트가 생성된 후 리스너를 추가하기 위해 addEventListener를 호출할 필요가 없습니다.
대신, 엘리먼트가 처음 렌더링될 때 리스너를 제공하면 됩니다.
// 일반 JS
button.addEventListener("click", () => {
console.log("clicked");
});
// React
<button onClick={handleClick}>Click</button>
일반 JS에서는 DOM 생성 후 이벤트 리스너를 붙이는 반면, React에서는 컴포넌트 렌더링 후 DOM을 생성하고 이벤트를 연결한다.
React는 내부적으로 자동 처리하므로 addEventListener()를 호출할 필요가 없다는 의미이다.
이벤트 핸들러에 인자 전달하기
이벤트 핸들러에 추가 인자를 전달하고 싶은 경우 화살표 함수를 사용해 전달할 수 있다.
<button onClick={() => handleDelete(id)}>Delete</button>
06. 조건부 렌더링
React는 원하는 동작을 캡슐화하는 컴포넌트를 만들 수 있어 원하는 컴포넌트만 렌더링 할 수 있다.

공식 문서 예제를 참고하여 작성해본 코드이다.
사용자의 로그인 상태에 맞게 Greeting 컴포넌트를 만들고 isLoggedIn props에 따라서 다른 인사말을 렌더링한다.
if문 조건부 렌더링을 통해 state값에 따라 다른 엘리먼트를 반환할 수 있으며, state가 변경되면 리랜더링되어 UI도 업데이트된다.

논리 && 연산자로 If를 인라인으로 표현하기

JS에서 true && expression은 항상 expression으로 평가되고, false && expression은 항상 false로 평가된다.
따라서 && 뒤 엘리먼트는 조건이 true일때 출력이 된다. falsy는 falsy 표현식이 반환되며 해당 코드에서는 0이 반환될 것이다.
컴포넌트가 렌더링하는 것을 막기
렌더링 시 컴포넌트 자체를 숨기고 싶을 때, 렌더링 결과를 출력하는 대신 null값을 반환할 수 있다.
컴포넌트의 render 메서드로부터 null을 반환하는 것은 생명주기 메서드 호출에 영향을 주지 않는다.

<MessageBanner />가 unreadMessage 길이에 따라 렌더링되는데, 길이가 0이라면 null을 반환하며 렌더링되지 않는다.
'프론트' 카테고리의 다른 글
| 컴퓨터 구조: CPU, 메모리, 보조기억장치, 입출력장치 (0) | 2026.04.25 |
|---|---|
| 스크립트 언어(Script Language) vs 컴파일 언어(Compile Language) (0) | 2026.04.25 |
| [React] 리액트 주요 문법 정리(useEffect, useState, props, map ...) (0) | 2025.06.19 |
| [렌더링 아키텍처] SPA, MPA/SSR의 차이점 (0) | 2025.04.17 |