1. ReactDOM
ReactDOM.render( <h1>Hello, World!</h1>, document.getElementById('root') );
ReactDOM 은 DOM 상호작용을 하는 메소드들을 모아놓은 패키지 입니다. 주로 리액트 엘리먼트의 삽입이나 업데이트와 관련이 있습니다.
render()
리액트와 DOM이 가장 처음 상호작용을 하는 메소드.
사용자가 직접 <Calculator/> 라는 리액트 엘리먼트를 정의했다고 했을때,
컨테이너로 작용 할 엘리먼트가 ID 값 container라면 다음과 같은 예시로 사용자 정의 리액트 엘리먼트를 컨테이너안에서 렌더링 할 수 있습니다.
ReactDOM.render(<Calculator/>, document.querySelector("#container"));
NOTE: 만약 <Calculator/> 사용자 리액트 엘리먼트가 이미 div 엘리먼트에 마운트가 되어 있을때 다시 한번 호출을 하게 된다면 전과 후의 DOM 을 비교해서 업데이트를 하게 됩니다.
위에서 생성한 코드는 결과값으로 참조값을 반환합니다.
만약 함수형 컴포넌트를 사용한다면 null을 반환합니다.
NOTE: render함수의 리턴값은 legacy 로 정의됩니다. component를 비동기 적으로 render을 하는 미래의 버전에서는 사용되지 않을 수 있습니다.
render() 파라미터
ReactDOM.render(element, container, callback)
ReactDOM.render() 메소드는 최대 3개의 값을 파라미터로 받습니다.
- element : 렌더링 할 JSX 표현식 or React Element
- container : element를 자식으로 받아 렌더링을 시켜 줄 대상
- callback : (optional) 렌더링 완료 후 실행 될 콜백 함수
Tree Structure
리액트 엘리먼트는 tree structure로 정의됩니다. 즉 각각의 엘리먼트들은 어떠한 React element의 자식이라는 뜻입니다. 하지만 root element는 HTML코드로 만든 컨테이너 element 안에 만들어 주어야 합니다.
위의 다이어그램을 보면 <Calculator /> 가 root React element 라는 것을 확인할 수 있습니다. 그리고 이것은 HTML code 인 div를 container 삼아 렌더링 되었습니다
위의 다이어그램을 코드로 보면 이렇습니다.
function Calculator() {
return (
<>
<Display />
<KeyPad />
</>
);
}
function KeyPad() {
return (
<>
<NumKeys />
<FunctionalKeys />
<Operators />
</>
);
}
참고 자료
- https://www.geeksforgeeks.org/reactjs-reactdom/
- https://www.newline.co/@KumailP/a-closer-look-at-reactdomrender-the-need-to-know-and-more--891fed64
- https://medium.com/react-native-seoul/react-리액트를-처음부터-배워보자-02-react-createelement와-react-component-그리고-reactdom-render의-동작-원리-41bf8c6d3764
- https://levelup.gitconnected.com/a-journey-through-reactdom-render-e8fc5edc11fd
2. JSX
const element = <h1>Hello, world!</h1>;
위 코드의 태그 문법은 문자열도, HTML도 아닌 JavaScript를 확장한 JSX 라는 문법입니다.
JSX 특징
- JSX는 내부적으로 React.createElement() 함수를 사용합니다.
- JavaScript 코드 안에서 UI 관련 작업을 할 때 시각적으로 도움이 될 수 있기에 사용합니다.
- JSX의 중괄호 안에는 유효한 모든 JavaScript 표현식을 넣을 수 있습니다.
- 컴파일이 끝나면 JSX 표현식은 정규 JavaScript 함수 호출이 되고 JavaScript 객체로 인식됩니다.
- 즉, JSX를 if 구문 및 for loop 안에 사용하고, 변수에 할당하고, 인자로서 받아들이고, 함수로부터 반환할 수 있습니다.
function getGreeting(user) {
if (user) {
return <h1>Hello, {formatName(user)}!</h1>;
}
return <h1>Hello, Stranger.</h1>;
}
NOTE : JSX는 HTML보다는 JavaScript에 가깝기 때문에, React DOM은 HTML 어트리뷰트 이름 대신 camelCase 프로퍼티 명명 규칙을 사용합니다. 예를 들어, JSX에서 class는 [className] 이 되고 tabindex는 [tabIndex] 가 됩니다.
Babel 은 JSX를 React.createElement() 호출로 컴파일 합니다. 다음 두 예시는 동일합니다.
const element = (
<h1 className="greeting">
Hello, world!
</h1>
);
const element = React.createElement(
'h1',
{className: 'greeting'},
'Hello, world!'
);
which eventually becomes ...
const element = {
type: 'h1',
props: {
className: 'greeting',
children: 'Hello, world!'
}
};
기본적으로 React DOM은 JSX에 삽입된 모든 값을 렌더링하기 전에 이스케이프 하므로,
애플리케이션에서 명시적으로 작성되지 않은 내용은 주입되지 않습니다. 모든 항목은 렌더링 되기 전에 문자열로 변환됩니다.
이런 특성으로 인해 XSS (cross-site-scripting) 공격을 방지할 수 있습니다.
NOTE: 이스케이프란?
특정 문자를 HTML로 변환하는 행위
리액트의 이스케이프
React 메뉴얼의 "Dangerously Set innerHTML" 페이지에 따르면, React에서는 cross-site scripting(CSS) 공격을 막기 위해 렌더링 메소드 내부에서 html 태그가 담겨있는 string 형태를 렌더링 하면 태그가 안먹히고 문자열 그대로 렌더링 하게 된다 합니다.
render() {
let codes = "<b>Will This Work?</b>";
return (
<div>
{codes}
</div>
);
}
/*
result is ...
<b>Will This Work?</b>
*/
만약 저 문자열에 태그가 적용된 상태로 렌더링이 된다면 스크립트 공격을 할 수 있는 취약점이 생깁니다.
React 에서는 이 취약점을 원천 하단하기 위해 무조건 텍스트 형태로만 렌더링 하게 설정 되어있습니다.
만약 그럼에도 불구하고 태그를 적용하고 싶다면
render() {
let codes = "<b>Will This Work?</b>";
return (
<div dangerouslySetInnerHTML={ {__html: codes} }>
</div>
);
}
};
/*
result is ...
Will This Work?
*/
dangerouslySetInnerHTML 라는 속성을 사용하면 됩니다.
참고 자료
3. Element Rendering
<div id="root"></div>
HTML 파일 어딘가에 id 값이 root 인 <div> 태그가 있다고 가정한다면 이 안에 들어가는 모든 엘리먼트를 ReactDOM에서 관리하기 때문에 이것을 root DOM Node 라고 부릅니다.
React Element 는 불변객체 입니다. 엘리먼트를 생성한 이후에는 해당 엘리먼트의 자식이나 속성을 변경 할 수 없습니다.
NOTE: 불변객체의 장점은?
불변 객체는 하나의 상태만을 갖고 있으므로, 데이터를 신뢰할 수 있다. ( mutable 객체는 메모리 주소를 참조하기 때문에 값을 변경했을 경우 해당 값을 사용하고 있는 모든 곳에서 side effect (부수 효과, 부작용)이 발생하여 예상치 못한 버그를 유발할 수 있습니다. 하지만 immutable 은 객체의 메모리 주소가 불변하기 때문에 내부적으로 구조를 유지할 있고 side effect를 감소시킬 수 있습니다. )Thread-Safe 하므로 멀티 스레드 환경에서 안전하게 사용할 수 있다. (멀티스레드 환경에서)
변경된 부부만 업데이트 하기
ReactDOM은 해당 엘리먼트와 그 자식 엘리먼트를 이전의 엘리먼트와 비교하고
DOM을 원하는 상태로 만드는데 필요한 경우에만 DOM을 업데이트 합니다.
NOTE: Real DOM 과 가상 DOM의 비교. Reconciliation phase, Commit phase 를 거친다
참고 자료
4. Components and Props
사용자 정의 컴포넌트
React 엘리먼트는 사용자 정의 컴포넌트로도 나타낼 수 있습니다.
const element = <Welcome name="Paul" />;
React가 사용자 정의 컴포넌트로 작성한 엘리먼트를 발견하면 JSX 어트리뷰트와 자식을 해당 컴포넌트에 단일 객체로 전달합니다. 이 객체를 props 라고 합니다.
사용자 정의 컴포넌트의 이름은 항상 대문자로 시작합니다.
'Web > React.js' 카테고리의 다른 글
[STUDY] 컨텍스트 (0) | 2021.03.13 |
---|---|
[STUDY] 에러 경계 (0) | 2021.03.12 |
[STUDY] 코드분할 (0) | 2021.03.10 |
[STUDY] 접근성 (0) | 2021.03.09 |
Virtual DOM 을 왜 빠르다고 하는가 (0) | 2020.06.11 |
댓글