자바스크립트/러닝 리엑트

리액트의 작동 원리

막이86 2023. 11. 13. 11:30
728x90

러닝 리엑트을 요약한 내용입니다.

  • 리액트를 사용할 때는 JSX로 앱을 만들 가능성이 커진다.
  • JSX는 HTML과 아주 비슷해 보이는 태그를 기반으로 하는 자바스크립트 구문이다.
  • 리액트의 기본요소를 알아보고, 컴포넌트와 엘리먼트를 합성하는 커스텀 컴포넌트를 만드는 방법을 살펴봄으로써 리액트 컴포넌트에 대해 알수 있다.

4.1 페이지 설정

  • 리액트를 브라우저에서 다루려면 React와 ReactDOM 라이브러리를 불러와야 한다.
  • React는 뷰를 만들기 위한 라이브러리
  • ReactDOM은 UI를 실제로 브라우저에 렌더링할때 사용하는 라이브러리
  • 리액트를 사용하기 위한 최소한의 요구 사항 코드

4.2 리액트 엘리먼트

  • HTML을 브라우저가 문서 객체 모델인 DOM을 구성하기 위해 따라야하는 절차라고 간단히 말할 수 있다.
  • HTML 문서를 이루는 엘리먼트는 브라우저가 HTML 문서를 읽어들이면 DOM 엘리먼트가 되고, 이 DOM이 사용자 인터페이스를 화면에 표시한다.
  • HTML 계층 구조를 보기 위한 예제 코드
  • 어떤 조리법을 표시하기 위한 HTML 계층 구조 예제 코드
  • <!DOCTYPE html> <html> <head> <meta charset='utf-8'> <title>순수 리액트 예제</title> </head> <body> <section id="baked-salmon"> <h1>구운 연여</h1> <ul class="ingredients"> <li>연어 900그램</li> <li>신선한 로즈마리 5가지</li> <li>올리브 오일 2 테이블스푼</li> <li>작은 레몬 2 조각</li> <li>코셔 소금 1 티스푼</li> <li>다진 마늘 4 쪽</li> </ul> </section> <section class="instructions"> <h2>조리 과정</h2> <p>오븐을 190도로 예열한다.</p> <p>알루미늄 호일에 올리브 오일을 가볍게 두른다.</p> <p>연어를 호일에 올린다.</p> <p>로즈마리, 슬라이스한 레몬, 다진 마늘을 연어 위에 얹는다.</p> <p>완전히 익을 때까지 15~20분간 굽는다.</p> <p>오븐에서 그릇을 꺼낸다.</p> </section> </body> </html>
  • 전통적으로 웹사이트는 독립적인 HTML 페이지들로 만들어졌다.
    • 사용자가 페이지 사이를 내비게이션 함에 따라 브라우저는 매번 다른 HTML 문서를 요청해 로딩할수 있었다.
    • AJAX가 생기면서 단일 페이지 애플리케이션(SPA)이 생겼다.
      • SPA에서 처음에 브라우저는 HTML 문서를 하나 적재한다.
      • 사용자는 사이트를 내비게이션하지만 실제로는 같은 페이지 안에 계속 머문다.
      • 사용자가 애플리케이션과 상호작용하는 것에 맞춰 표시중인 인터페이스를 없애고 새로운 사용자 인터페이스를 만든다.
      • 사용자가 느끼기에는 다른 페이지로 이동한 것 같지만 실제로는 여전히 같은 HTML 페이지 안에 머물 뿐이다.
  • DOM API는 브라우저의 DOM을 변경하기 위해 자바스크립트가 사용할 수 있는 객체 모음이다.
    • document.createElement
    • document.appendChild
    • ... 등
  • 리액트는 브라우저 DOM을 갱신해주기 위해 만들어진 라이브러리 이다.
    • 리액트가 모든 처리를 대신 해주기 때문에 더 이상 SPA를 더 효율적으로 만들기 위해 여러 복잡한 내용을 신경쓸 필요가 없다.
    • 리액트에서는 코드로 DOM API를 직접 조작하지 않는다.
    • 리액트가 우리 명령에 맞춰 원소 랜더링을 조절해 준다.
  • 브라우저 DOM이 DOM 엘리먼트로 이뤄지는 것처럼, 가상 DOM은 리액트 엘리먼트로 이뤄진다. 리액트 엘리먼트는 개념상 HTML 엘리머트와 비슷하지만 실제로는 자바스크립트 객체다.
  • 리액트 엘리먼트는 실제 DOM 엘리먼트는 DOM API를 직접 다루는 것보다 자바스크립트 객체인 가상 DOM을 직접 다루는 편이 훨씬 더 빠르다
  • 가상 DOM을 변경하려면 리액트는 DOM API를 통해서 변경사항을 가장 효율적으로 렌더링 해준다.
  • React.createElement를 사용해 h1을 표현하는 리액트 엘리먼트를 만들 수 있다.
    • 첫 번째 인자는 엘리먼트의 타입
    • 두 번째 인자는 엘리먼트의 프로퍼티
    • 세 번째 인자는 엘리먼트를 여는 태그와 닫는 태그 사이에 들어가야할 자식 노드
    React.createElement("h1", { id: "recipe-0" }, "구운 연어")
    
    • 랜더링 과정에서 리액트는 실제 DOM 엘리먼트로 변환한다.
    <h1 id="recipe-0">구운 연어</h1>
    
    • 리액트 엘리먼트는 단지 리액트에게 DOM 엘리먼트를 구성하는 방법을 알려주는 자바스크립트 리터럴에 불과 하다
    {
    	$$typeof: Symbole(React.element),
    	"type": "h1",
    	"key": null,
    	"ref": null,
    	"props": {id: "recipe-0", children: "구운 연어"},
    	"_owner": null,
    	"_store": {}
    }
    
    <aside> 💡 React.createElement가 반환하는 객체를 살펴보았다. 하지만 리터럴을 직접 손으로 입력해서 엘리먼트를 만드는 경우는 결코 없다. 리액트 엘리먼트를 만들고 싶으면 항상 React.createElement 함수를 사용해야 한다.
  • </aside>

4.3 ReactDOM

  • ReactDOM에는 리액트 엘리먼트를 브라우저에 렌더링하는 데 필요한 도구가 들어 있다.
  • ReactDOM에는 render 메서드가 들어 있다.
  • 렌더링 하기 위해서는 ReactDOM.render를 사용한다.
    • 렌더링된 리액트 엘리먼트
    <body>
    	<div id="root">
    		<h1 id="recipe-0">구운 연어</h1>
    	</div>
    </body>
    
  • var dish = React.createElement("h1", { id: "recipe-0" }, "구운 연어") ReactDOM.render(dish, document.getElementById("root"));
  • 리액트 16 이전 버전의 리액트에서는 DOM에서 한 엘리먼트만 랜더링 할 수 있었다.
  • 최근 버전은 배열을 렌더링 할 수 있다.

4.3.1 자식들

  • props.children을 사용해 자식 엘리먼트들을 렌더링한다.
  • ul과 자식으 React.createElement로 나타낼 수 있다.
  • React.createElement( "ul", null, React.createElement("li", null, "연어 900그램"), React.createElement("li", null, "신선한 로즈마리 5가지"), React.createElement("li", null, "올리브 오일 2 테이블스푼"), React.createElement("li", null, "작은 레몬 2 조각"), React.createElement("li", null, "코셔 소금 1 티스푼"), React.createElement("li", null, "다진 마늘 4 쪽") );
  • 조립법이 들어간 HTML을 리액트를 사용해서 만든 예제 코드<aside> 💡 HTML class 속성에 있는 엘리먼트는 class대신 className이라는 이름의 프로퍼티를 사용해야한다. class가 자바스크립트에서 예약어라서 HTML 엘리먼트의 class를 정의하려면 어쩔 수 없이 className을 사용해야만 한다.
  • </aside>
  • React.createElement( "section", {id: "baked-salmon"}, Reacte.createElement("h1", null, "구운 연어"), React.createElement( "ul", {"className": "ingredients"}, React.createElement("li", null, "연어 900그램"), React.createElement("li", null, "신선한 로즈마리 5가지"), React.createElement("li", null, "올리브 오일 2 테이블스푼"), React.createElement("li", null, "작은 레몬 2 조각"), React.createElement("li", null, "코셔 소금 1 티스푼"), React.createElement("li", null, "다진 마늘 4 쪽") ), React.createElement( "section", {"className": "instructions"}, Reacte.createElement("h2", null, "조리절차"), Reacte.createElement("p", null, "오븐을 190도로 예열한다."), Reacte.createElement("p", null, "알류미늄 호일에 올리브 오일을 가볍게 두른다."), Reacte.createElement("p", null, "로즈마리, 슬라이스한 레몬, 다진 마늘을 연어 위에 얹는다."), Reacte.createElement("p", null, "오븐에서 그릇을 꺼낸다.."), ) )

데이터를 가지고 엘리먼트 만들기

  • 리액트를 사용하는 경우 큰 장점은 UI엘리먼트와 데이터를 분리할 수 있다는 것이다.
  • 배열에 재료를 저장해두고 그 배열을 이렉트 엘리먼트로 map 할 수 있다.
    • 자바스크립트 배열로 간단히 표현할 수 있다.
    const items = [
        "연어 900그램",
        "신선한 로즈마리 5가지",
        "올리브 오일 2 테이블스푼",
        "작은 레몬 2 조각",
        "코셔 소금 1 티스푼",
        "다진 마늘 4 쪽"
    ]
    
    • map을 적용해서 엘리먼트를 생성할 수 있다.
    React.createElement(
        "ul",
        {"className": "ingredients"},
        items.map(ingredient => React.createElement("il", null, ingredient))
    )
    
    • 배열을 이용해서 이터레이션을 할경우 key 프로퍼티를 넣는 것을 권장한다.
      • 리액트는 key를 사용해 DOM을 더 효율적으로 갱신할 수 있다.
    React.createElement(
        "ul",
        {"className": "ingredients"},
        items.map((ingredient, i)=> React.createElement("il", { key: i }, ingredient))
    )
    
  • React.createElement( "ul", {"className": "ingredients"}, React.createElement("li", null, "연어 900그램"), React.createElement("li", null, "신선한 로즈마리 5가지"), React.createElement("li", null, "올리브 오일 2 테이블스푼"), React.createElement("li", null, "작은 레몬 2 조각"), React.createElement("li", null, "코셔 소금 1 티스푼"), React.createElement("li", null, "다진 마늘 4 쪽") ),

4.4 리액트 컴포넌트

  • 컴포넌트를 사용하면 서로 다른 조리법이나 서로 다른 데이터 집합에 대한 같은 DOM 구조를 재사용할 수 있다.
  • [그림 4-3]에서 표시한 각 부분인 재료, 조리절차 등을 컴포넌트로 만들 수 있다.
  • [그림 4-3]을 컴포넌트로 만들면 규모 확장이 쉽게 가능하다.
  • 순서가 없는 재료 리스트를 반환하는 함수를 만드는 예제 코드
    • 데이터를 컴포넌트 안에 하드 코딩했다는 부분에 문제가 있음
    function IngredientsList() {
        return React.createElement(
            "ul",
            { "className": "ingredients" },
            React.createElement("li", null, "연어 900그램"),
            React.createElement("li", null, "신선한 로즈마리 5가지"),
            React.createElement("li", null, "올리브 오일 2 테이블스푼"),
            React.createElement("li", null, "작은 레몬 2 조각"),
            React.createElement("li", null, "코셔 소금 1 티스푼"),
            React.createElement("li", null, "다진 마늘 4 쪽")
        );
    }
    
    ReactDOM.render(
        React.createElement(IngredientsList, null, null),
        document.getElementById("root")
    )
    
  • 데이터를 프로퍼티로 넘기는 예제 코드
    • 컴포넌트가 데이터를 동적으로 랜더링할 수 있다.
    const secretIngredients = [
        "연어 900그램",
        "신선한 로즈마리 5가지",
        "올리브 오일 2 테이블스푼",
        "작은 레몬 2 조각",
        "코셔 소금 1 티스푼"
    ];
    
    function IngredientsList({ items }) {
        return React.createElement(
            "ul",
            { "className": "ingredients" },
            items.map((ingredient, i) => React.createElement("li", { key: i}, ingredient))
        )
    }
    
    ReactDOM.render(
        React.createElement(IngredientsList, { items: secretIngredients }, null),
        document.getElementById("root")
    )
    

4.4.1 리액트 컴포넌트의 역사

  • 함수 컴포넌트가 등장하기 전에는 다른 방식으로 컴포넌트를 만들었다.
  • 시간에 따른 리액트 API 변화를 살펴 보자

첫 번째 정류장: createClass

  • 2013년 리액트가 처음 등장했을 때는 컴포넌트를 만드는 유일한 방법이 createClass 함수를 사용하는 것이 였다.
  •  
  • 리액트 15.5부터 createClass를 사용하면 경로를 표시하기 시작했다.
  • 리액트 16부터 React.createClass는 공식적으로 사용 금지 되었다.

두 번째 정류장: 클래스 컴포넌트

  • ES 2015에 클래스 문법이 도입되면서 리액트에도 리액트 컴포넌트를 만드는 새로운 방법이 도입되었다.
  • React.Component API를 사용하면 class 구문을 사용해 새로운 컴포넌트 인스터스를 만들 수 있다.
  •  
  • React.Component도 조만간 사용이 금지될 것으로 예상된다.
  • 이제부터는 함수만을 사용해서 컴포넌트를 만들고, 예정 방식은 참고를를 위해서 간략하게 보자
728x90