카테고리 없음
리액트 기초
김딸기*
2024. 11. 12. 17:13
- 페이스북에서 만든 웹 UI를 작성하기 위한 자바스크립트 라이브러리
- SPA의 단점을 보완하는 몇가지 기술을 도입
- SPA의 단점
- 모든 기능을 한 페이지에서 다 구현하다 보니 상태(데이터) 관리가 어려움
- 자바스크립트에서 HTML 코드를 생성해야 하므로 개발 생산성 저하
- 브라우저의 DOM을 자주 갱신하다보면 성능 저하 발생 (처음부터 렌더링하는걸 반복하면 성능저하)
- SPA의 단점을 보완하는 React의 특징
- 컴포넌트 별로 상태 관리가 가능하고 전역 수준의 상태 관리를 지원하는 서드파티 라이브러리가 많음
- JSX를 이용해서 HTML 생산성이 높음
- 가상 DOM을 이용해서 성능 저하 최소
- 화면의 일부 UI를 만드는 컴포넌트 단위로 개발
- 컴포넌트는 자바스크립트로 개발하며 재사용성이 뛰어남
- 각각의 컴포넌트 내부에서 상태 관리 기능 제공
- 전역 수준의 상태 관리를 위한 라이브러리(Context API, Redux, MobX, Recoil, Zustand 등)를 사용할 수 있음
- 상태가 변경되면 뷰(UI, HTML)를 즉시 렌더링
- 단방향 데이터 바인딩: State -> View, View -> Event Handler -> setState() -> State
- View의 변경이 직접 State를 변경시키지 않고 Event Handler를 통해서만 변경 가능하게 구현해야 하므로 상태가 변경되는 과정에 대한 예측과 추적이 용이함
- HTML 마크업과 비슷한 문법을 사용해서 UI 정의하면 Babel 같은 변환 도구에 의해 자바스크립트 코드로 변환됨
<div class="todolist"> <ul> <li>두부</li> <li>계란</li> <li>라면</li> </ul> </div>
/*#__PURE__*/_jsx("div", { class: "todolist", children: /*#__PURE__*/_jsxs("ul", { children: [/*#__PURE__*/_jsx("li", { children: "\uB450\uBD80" }), /*#__PURE__*/_jsx("li", { children: "\uACC4\uB780" }), /*#__PURE__*/_jsx("li", { children: "\uB77C\uBA74" })] }) });
- 상태가 변경되어서 뷰를 렌더링할때 브라우저 DOM에 바로 적용하지 않고 브라우저 DOM과 유사한 트리구조의 가상 DOM(자바스크립트 객체)을 먼저 수정한 후 수정전의 가상 DOM과 수정후의 가상 DOM을 비교해서 바뀐 부분만 브라우저 DOM에 실제 반영
- DOM API를 이용한 화면 갱신 방법
- 수정된 부분만 찾아서 갱신
- 장점: 화면 렌더링을 최소화 하기 때문에 성능에 좋음
- 단점: 기존 데이터와 새로운 데이터를 비교해서 새로운 데이터가 기존 데이터의 어느 부분과 달라졌는지 확인하고 해당 요소를 DOM에서 찾아 갱신해야 하므로 코드가 복잡해짐
- 관련 영역 전체를 갱신
- 장점: 기존 요소를 지우고 새로운 데이터로 전체를 교체하면 되므로 기존 데이터와 비교 작업이 필요 없고 수정될 부분만 찾아서 DOM을 갱신할 필요가 없으므로 코드가 간결해짐
- 단점: 하나만 수정해서 갱신하면 될 것을 관련 영역 전체를 다시 렌더링 하므로 성능 이슈 발생
- 가상 DOM 이용
- 새로운 데이터를 가지고 만들어진 가상 DOM과 기존 DOM을 비교해서 바뀐 부분만 찾아서 브라우저 DOM을 갱신하므로 성능에 좋음
- 바뀐 부분만 찾아서 리렌더링 하는 작업은 리액트가 담당하므로 코드가 간결해짐
- 수정된 부분만 찾아서 갱신
순수 자바스크립트와 DOM API 사용
<body>
<div id="root"></div>
<script type="text/javascript">
function App() {
//<h1>hello HTML</h1> ->DOM api을 이용해 js로 html만들기
const h1 = document.createElement("h1");
const txt = document.createTextNode("hello DOM");
h1.appendChild(txt);
return h1;
}
document.getElementById("root").appendChild(App());
</script>
</body>
- <div id="root"></div>: 이 div는 HTML 문서에 포함된 빈 컨테이너입니다. 여기에서 우리가 생성한 내용이 추가될 위치가 됩니다.
- function App(): App 함수는 <h1>hello DOM</h1> 태그를 자바스크립트를 통해 만들어 반환하는 함수입니다.
- document.createElement("h1"): <h1> 태그를 자바스크립트로 생성합니다.
- document.createTextNode("hello DOM"): <h1> 태그 안에 넣을 텍스트 "hello DOM"을 생성합니다.
- h1.appendChild(txt): 텍스트를 <h1> 태그 안에 추가합니다.
- document.getElementById("root").appendChild(App()): root라는 div 안에 App() 함수가 반환하는 <h1> 태그를 추가하여 화면에 표시합니다.
이렇게 하면 HTML 없이 자바스크립트만으로 <h1>hello DOM</h1>을 생성하여 웹페이지에 표시하는 것입니다.
React와 ReactDOM 사용
<body>
<div id="root"></div>
<script type="text/javascript">
function App() {
//<h1>hello HTML</h1> ->DOM api을 이용해 js로 html만들기
return React.createElement("h1", null, "Hello React");
}
ReactDOM.createRoot(document.getElementById("root")).render(
React.createElement(App, null)
);
</script>
</body>
- <div id="root"></div>: 이 div는 우리가 React로 만든 내용을 삽입할 컨테이너입니다.
- function App(): App 함수는 <h1>Hello React</h1> 요소를 생성하여 반환하는 React 컴포넌트입니다.
- React.createElement("h1", null, "Hello React"): 이 구문은 <h1>Hello React</h1> 태그를 React 방식으로 생성하는 코드입니다.
- "h1": 생성할 태그 이름.
- null: 속성(props)이 없는 경우 사용됩니다.
- "Hello React": <h1> 태그 안에 들어갈 텍스트입니다.
- React.createElement("h1", null, "Hello React"): 이 구문은 <h1>Hello React</h1> 태그를 React 방식으로 생성하는 코드입니다.
- ReactDOM.createRoot(document.getElementById("root")).render(...): root라는 div에 App 컴포넌트를 렌더링하여 표시합니다.
- ReactDOM.createRoot(...): React의 root를 설정하는 코드입니다.
- .render(...): 설정된 root에 컴포넌트를 렌더링하여 보여줍니다.
이 코드는 React 라이브러리를 사용하여 <h1>Hello React</h1>를 화면에 출력합니다.
JSX를 사용한 React 컴포넌트
<body>
<div id="root"></div>
<script type="text/babel">
function App() {
//<h1>hello HTML</h1> ->DOM api을 이용해 js로 html만들기
return <h1>hello JSX</h1>;
}
ReactDOM.createRoot(document.getElementById("root")).render(<App />);
</script>
</body>
- <div id="root"></div>: React에서 만든 컴포넌트를 넣을 빈 컨테이너로, React가 이 div를 기준으로 내용을 렌더링합니다.
- function App(): App이라는 이름의 React 컴포넌트를 정의합니다.
- return <h1>hello JSX</h1>;: JSX 문법으로 <h1> 요소를 반환하며, 여기에는 텍스트 "hello JSX"가 포함됩니다. 이 방식은 JavaScript로 HTML 요소를 직접 만드는 것보다 간편합니다.
- ReactDOM.createRoot(document.getElementById("root")).render(<App />);:
- ReactDOM.createRoot(...): React가 이 root를 기준으로 렌더링을 시작합니다.
- .render(<App />): App 컴포넌트를 root에 렌더링하여 화면에 표시합니다.
이 첫 번째 코드에서는 간단히 <h1>hello JSX</h1> 요소를 렌더링하여 웹 페이지에 나타냅니다.
여러 개의 React 컴포넌트 정의 및 재사용
<div id="root"></div>
<script type="text/babel">
//컴포넌트를 만들어서 재사용하려면?
//1. 독립적인 파일로 작성(모듈)
//2.범용성(타이틀 값을 각 페이지 별로 다르게 전달받아 출력)
function Title() {
return (
<div>
<h1>Simple Todo List - react component :()</h1>
<hr />
</div>
);
}
//todo목록을 전달받아 출력
function TodoList() {
return (
<ul className="todolist">
<li>React 공부 - 진행중</li>
<li>Nodejs 공부 - 완료</li>
<li>Javascript 공부 - 완료</li>
</ul>
);
}
function App() {
return (
<div id="app">
<div>
<Title />
<TodoList />
</div>
</div>
);
}
ReactDOM.createRoot(document.getElementById("root")).render(<App />);
</script>
- <div id="root"></div>: root라는 div에 React 컴포넌트를 삽입하여 렌더링할 준비를 합니다.
- function Title(): Title이라는 React 컴포넌트를 정의합니다.
- return (...): JSX를 사용해 <h1> 요소와 <hr /> 요소를 반환하며, Title 컴포넌트는 페이지의 제목과 구분선을 나타냅니다.
- 이렇게 Title 컴포넌트를 별도로 만들어서 다른 페이지나 컴포넌트에서 재사용이 가능합니다.
- function TodoList(): TodoList라는 React 컴포넌트를 정의합니다.
- return (...): 목록(<ul>)과 항목들(<li>)을 JSX로 작성해 반환합니다.
- 이 컴포넌트는 할 일 목록을 화면에 표시합니다.
- function App(): App 컴포넌트는 페이지의 전체 구조를 나타내며, Title과 TodoList 컴포넌트를 포함합니다.
- <Title /> 및 <TodoList />: App 컴포넌트에서 Title과 TodoList 컴포넌트를 각각 호출하여 사용합니다. 이렇게 하면 App이 페이지의 전체 틀을 구성하게 됩니다.
- ReactDOM.createRoot(document.getElementById("root")).render(<App />);:
- ReactDOM.createRoot(...): root를 기준으로 React가 렌더링을 시작합니다.
- .render(<App />): App 컴포넌트를 root에 렌더링하여 Title과 TodoList가 화면에 표시됩니다.
요약
두 번째 코드는 재사용 가능한 컴포넌트를 정의하고, 이를 App 컴포넌트 안에 배치하여 전체 페이지 구조를 만듭니다. 이렇게 각 기능을 별도의 컴포넌트로 만들면 코드가 더 깔끔해지고, 필요한 곳에서 쉽게 사용할 수 있어 React 개발에서 매우 유용한 패턴입니다.