🪁react/react 이론정리

React의 상태관리(데이터 변경)[csr ,ssr 코드 비교를 통한 이해]

하얀성 2024. 1. 12. 07:42

결론.

 

csr [ 클라이언트에서 부모 컴포넌트가 상태관리(db관리)

/ 바뀌는상태 값만 관리 대상이고, html 요소 즉 jsx 들은 안바뀌고 가상돔이 차이나는 상태만 새로 렌더링]

 

ssr[ 서버에서 db관리 , db값 받아와서 값 원하는대로 변형해서 사이드인 ejs로 전송

/ejs는 html 사용을 위한 판데기일 뿐. 랜더링 때, 그 페이지에 데이터값과 html요소 전채 재 랜더링 실시]


 

React의 데이터 흐름 원칙

  1. 단방향 데이터 흐름 (One-Way Data Flow): React에서 데이터는 부모 컴포넌트에서 자식 컴포넌트로만 흐릅니다. 자식 컴포넌트는 받은 props를 직접 수정할 수 없습니다. 대신, 자식 컴포넌트는 부모 컴포넌트에게 변경을 요청할 수 있습니다.
  2. Props는 읽기 전용 (Props are Read-Only): 컴포넌트가 자신의 props를 변경하는 것은 React의 기본 원칙을 위반하는 것입니다. 이러한 행위는 예측할 수 없는 버그를 발생시킬 수 있습니다.

근데 값을 props로 받아서 content를 받아왔다면 content 를 재정의 해주는 것도 안되는가?

 

답: 안된다.

React에서 props로 받은 값을 재정의하는 것은 권장되지 않습니다. 이는 React의 핵심 원칙 중 하나인 "props는 읽기 전용"에 위배되기 때문입니다. props는 부모 컴포넌트에서 전달된 값으로, 자식 컴포넌트에서는 이 값을 변경할 수 없습니다.

 

클라이언트 사이드 렌더링(CSR)에서의 데이터 처리 (React 사용 시)

  • 데이터 처리 위치: CSR에서는 데이터 처리가 주로 클라이언트 측, 즉 브라우저에서 이루어집니다. React의 경우, 상태 관리는 컴포넌트 내부에서 이루어지거나 상위 컴포넌트(예: App.js)에서 관리됩니다.
  • 상태 관리: React에서 데이터 값에 +1과 같은 연산은 상태(state)를 사용하여 수행합니다. 이러한 상태 변경 로직은 상위 컴포넌트(예: App.js)에서 정의되고, 필요한 경우 자식 컴포넌트로 함수 형태로 전달될 수 있습니다.

 

React (클라이언트 사이드 렌더링)

 

 

부모 컴포넌트

import React, { useState } from 'react';
import ChildComponent from './ChildComponent';

function ParentComponent() {
  const [content, setContent] = useState("초기 내용");

  const handleUpdateContent = (newContent) => {
    setContent(newContent);
  };

  return (
    <div>
      <h1>부모 컴포넌트</h1>
      <ChildComponent content={content} onUpdateContent={handleUpdateContent} />
    </div>
  );
}

export default ParentComponent;

자식 컴포넌트

import React, { useState, useEffect } from 'react';

function ChildComponent({ content, onUpdateContent }) {
  const [localContent, setLocalContent] = useState(content);

  useEffect(() => {
    setLocalContent(content);
  }, [content]);

  const handleChange = (event) => {
    setLocalContent(event.target.value);
  };

  const handleSubmit = () => {
    onUpdateContent(localContent);
  };

  return (
    <div>
      <h2>자식 컴포넌트</h2>
      <textarea value={localContent} onChange={handleChange} />
      <button onClick={handleSubmit}>수정하기</button>
    </div>
  );
}

export default ChildComponent;

 


React와 Node.js/EJS 간의 데이터 관리UI 렌더링 방식비교해보기

 

두 방식 모두 웹 애플리케이션에서 중요한 역할을 하지만, 기본적인 접근 방식에서 차이가 있습니다.


React (클라이언트 사이드 렌더링)

  • 상태 관리: React에서는 컴포넌트의 상태(state)와 props를 사용하여 데이터를 관리합니다. 상태는 주로 해당 컴포넌트 또는 최상위 컴포넌트(App.js 등)에서 관리됩니다.
  • 데이터 흐름: React는 단방향 데이터 흐름을 따르며, 데이터는 상위 컴포넌트에서 하위 컴포넌트로 흘러갑니다.
  • UI 렌더링: 사용자 인터페이스는 JSX를 사용하여 선언적으로 작성됩니다. 상태가 변경될 때마다 React는 Virtual DOM을 사용하여 필요한 부분만을 다시 렌더링합니다.

Node.js / EJS (서버 사이드 렌더링)

  • 데이터 관리: Node.js에서는 서버 측에서 데이터를 처리하고 관리합니다. 데이터베이스와의 상호작용이 이곳에서 이루어집니다.
  • 데이터 전달: 데이터는 서버에서 처리된 후, EJS 템플릿 엔진을 통해 HTML로 렌더링되어 클라이언트에 전달됩니다.
  • UI 렌더링: EJS는 HTML 템플릿에 서버에서 가져온 데이터를 삽입완전한 HTML 페이지를 생성합니다. 이 페이지는 클라이언트에 전체적으로 전송됩니다.

데이터 전달 및 UI 생성 비교(아래 위의 코드들 설명)

  • React: 예시에서 ChildComponent는 부모 컴포넌트로부터 content를 props로 받아 로컬 상태를 생성하고 관리합니다. 사용자가 UI를 통해 상태를 변경하면, 이 변경사항은 부모 컴포넌트에 반영됩니다.
  • Node.js/EJS: contactList 라우트에서, 서버는 contact 테이블의 데이터를 가져와 contactList 뷰로 전달합니다. EJS 템플릿에서는 이 데이터를 반복문을 통해 HTML로 변환하여 브라우저에 표시합니다. lists.forEach 구문은 서버에서 전달된 lists 배열을 순회하며, 각 항목을 HTML 테이블의 행으로 변환합니다.

결론

  • React는 클라이언트 사이드에서 상태를 관리하고, 상태 변경에 따라 UI를 동적으로 업데이트합니다.
  • Node.js/EJS는 서버 사이드에서 데이터를 처리하고, HTML을 생성하여 클라이언트에 전체 페이지로 전송합니다. 클라이언트에서는 동적인 상태 관리가 이루어지지 않으며, 상태 변경을 위해서는 서버와의 추가적인 통신이 필요합니다.

두 방식은 웹 애플리케이션을 구축하는데 있어 서로 다른 접근 방식을 제공하며, 각각의 장단점이 있습니다. React는 보다 동적인 사용자 경험을 제공하는 반면, Node.js/EJS는 전통적인 서버 사이드 렌더링 방식을 사용합니다.

 


 

Node.js / EJS (서버 사이드 렌더링)

 

server.js

app.get("/contactList", (req, res) => {
  let sql = `select * from contact`;
  connection.query(sql, function (err, results, fields){
    if(err) throw err;
    res.render('contactList',{lists:results})
  })
})

app.get("/login", (req, res) => {
  res.render("login")
})

 

contactList.ejs

<%-include('header.ejs')%>

  <h1>문의 받은 내용</h1>

  <table border="1">
    <tr>
      <th>idx</th>
      <th>성명</th>
      <th>연락처</th>
      <th>이메일</th>
      <th>문의내용</th>
      <th>등록내용</th>
      <th>삭제</th>
    </tr>

    <% lists.forEach(function(item){ %>
      <tr>
        <td>
          <%=item.idx%>
        </td>
        <td>
          <%=item.name%>
        </td>
        <td>
          <%=item.phone%>
        </td>
        <td>
          <%=item.email%>
        </td>
        <td>
          <%-item.memo.replaceAll("\n","<br>")%>
        </td>
        <td>
          <%=item.regdate%>
        </td>
        <td><a href="/contactDelete?idx=<%=item.idx%>" onclick="return confirm('정말 삭제할까요?')">삭제</a></td>
      </tr>
      <% }) %>
  </table>

  <%-include('footer.ejs')%>