리액트를 시작해보자

김서현·2022년 10월 13일
0

React.js

목록 보기
1/2

📌 [1장] 리액트 시작

1. 왜 리액트인가?

자바 스크립트

  • 이전) 웹 브라우저에서 간단한 연산을 하거나 시각적인 효과를 주는 단순한 스크립트 언어
  • 현재) 웹 어플리케이션의 핵심적 역할 + 서버 사이드, 모바일, 데스크톱 애플리케이션

    👉 데스크톱 애플리케이션 : 슬랙, 아톰, VS Code <- 일렉트론으로 개발
    ➕ 일렉트론 : JS로 데스크톱 애플리케이션을 만들 수 있는 프레임워크

    👉 크로스 플랫폼 애플리케이션 : 페이스북, 디스코드, 페이팔, 이베이 개발
    ➕ 크로스 플랫폼 애플리케이션 : 한 가지 개발 언어와 프레임워크로 안드로이드, iOS 네이티브 앱을 만드는 개발 방식

    👉 JS 프레임워크 : Angular, Backbone.js, Derby.js, Ember.js, Ext.js, > Knockback.s, Sammy.js, PureMVC, Vue.js
    👉👉 주로 MVC(Model-View-Controller) 아키텍처, MVVM(Model-View-View-Model) 아키텍처를 사용, AngularJS는 MVW(Model-View-Whatever) 아키텍처

    공통점 : 모델(Model)과 뷰(View)가 있다.

    • 모델 : 애플리케이션에서 사용하는 데이터를 관리하는 영역
    • 뷰 : 사용자에게 보이는 부분
    • 사용자 작업 -> 프로그램 -> 컨트롤러 -> 모델 데이터 조회, 수정 -> 뷰에 변경된 사항 반영

💬 페이스북 : 어떤 데이터가 변할 때마다 어떤 변화를 줄지 고민하지 말고 기존 뷰를 날려 버리고 처음부터 새로 렌더링하자!
👉 CPU 점유율도 크게 증가,, 메모리도 많이 사용,,

💬 페이스북 : 앞서 설명한 방식으로 최대한 성능을 아끼고 편안한 사용자 경험을 제공하면서 구현하자!!
👉 리액트 개발

1) 초기 렌더링

리액트

  • 자바스크립트 라이브러리
  • 사용자 인터페이스를 만드는 데 사용
  • 구조가 MVC, MVW 등인 프레임워크와 달리 오직 V(View)만 신경 쓰는 라이브러리.

컴포넌트

  • 특정 부분이 어떻게 생길지 정하는 선언체
  • 재사용이 가능한 API로 수많은 기능들을 내장함
  • 해당 컴포넌트의 생김새와 작동 방식을 정의

렌더링

  • 사용자 화면에 뷰를 보여 주는 것.

초기 렌더링

  • 맨 처음 어떻게 보일지를 정하는 초기 렌더링

함수 : render() { ... }

  • 컴포넌트가 어떻게 생겼는지 정의하는 역할
  • html 형식의 문자열을 반환하지 않고, 뷰가 어떻게 생겼고 어떻게 작동하는지에 대한 정보를 지닌 객체를 반환
  • 컴포넌트 내부에 또 다른 컴포넌트가 들어갈 수 있음.
  • 최상위 컴포넌트의 렌더링 작업이 끝나면 지니고 있는 정보들을 사용하여 HTML 마크업을 만들고, 이를 우리가 정하는 실제 페이지의 DOM 요소 안에 주입.

2) 조화 과정

리액트에서 뷰를 업데이트 할 때 : "조화 과정을 거친다"

  • 뷰가 변형되는 것, 업데이트한 값을 수정하는 것 ❌
    👉 새로운 데이터를 가지고 render 함수를 또 다시 호출하여 그 데이터를 지닌 뷰를 생성
    👉👉 이전에 render 함수가 만들었던 컴포넌트 정보와 현재 render 함수가 만든 컴포넌트 정보를 비교
    👉👉👉 자바스크립트를 사용하여 두 가지 뷰를 최소한의 연산으로 비교 후 둘 차이를 알아내 최소한의 연산으로 DOM 트리를 업데이트

2. 리액트의 특징

1) DOM(Document Object Model)

  • 객체로 문서 구조를 표현하는 방법.
  • XML이나 HTML로 작성
  • 트리 형태 -> 특정 노드 찾기, 수정, 제거, 삽입 가능

  • 동적 UI에 최적화되어 있지 않다.
  • HTML : 정적임 -> js로 동적이게 만듬!

DOM은 느린가?

❌ NO!
DOM 자체는 빠름
변화가 일어나면 웹 브라우저가 CSS를 다시 연산하고, 레이아웃을 구성하고, 페이지를 리페인트 하는 과정에서 시간이 허비됨.

🔑 해결법
Virtual DOM 방식 사용


2) Virtual DOM

  • 실제 DOM에 접근하여 조작 ❌
  • 추상화한 JS 객체를 구성하여 사용 (마치 실제 DOM의 가벼운 사본)

실제 DOM을 업데이트 할 때

1. 데이터를 업데이트하면 전체 UI를 Virtual DOM에 리렌더링
2. 이전 Virtual DOM에 있던 내용과 현재 내용을 비교
3. 바뀐 부분실제 DOM에 적용

✔ 오해
Virtual DOM을 사용한다고 무조건 빠른 것 X

"우리는 다음 문제를 해결하려고 리액트를 만들었습니다."
"지속적으로 데이터가 변화하는 대규모 애플리케이션 구축하기"

  • 코드 최적화를 열심히 하면 DOM 작업이 느려지는 문제 개선 가능.
  • 작업이 매우 간단하면 오히려 사용 안 하는 편이 나은 성능을 보이기도

👉 적절한 곳에 사용해야 진가를 발휘!

  • 리액트와 Virtual DOM이 언제나 제공할 수 있는 것 : 업데이트 처리 간결성

3) 기타 특징

  • 리액트는 프레임워크가 아니라 라이브러리

  • 리액트는 뷰만 신경쓰는 라이브러리이므로 기타 기능은 직접 구현하여 사용해야 함!

    라이브러리

    라우팅 - 리액트 라우터(react-router)
    Ajax 처리 - axios, fetch
    상태 관리 - 리덕스(redux), MobX
    SockJS, socket.io, superagent, Relay, redux-sega, redux, redux-thunk, rezt-enroute ...

  • 다른 웹 프레임워크나 라이브러리와 혼용도 가능
    Backbone.js, AngularJS

3. 작업 환경 설정


📌 [2장] 리액트 시작

1. 코드 이해하기

📁 src/App.js

import logo from './logo.svg';
import './App.css';

import 구문 : 특정 파일을 불러오는 것

  • 원래 브라우저에는 모듈을 불러와서 사용하는 기능이 없었다!
    👉 Node.js에서 지원하는 기능.
    👉 참고) Node.js에서는 require 구문으로 패키지를 불러올 수 있음

  • 브라우저에서 사용하기 위해 번들러를 사용

번들러(bundler)

  • 파일을 묶듯이 연결해줌
  • ex) 웹팩, Parcel, browserify
    리액트는 주로 웹팩 사용.
  • import로 모듈을 불러왔을 때 불러온 모듈을 모두 합쳐서 하나의 파일을 생성해 줌.
  • src/index.js를 시작으로 필요한 파일을 다 불러와서 번들링함.

웹팩의 로더(loader)

  • 파일들을 불러오는
  • create-react-app이 대신 설정해주기 때문에 별도의 설정 필요 X
  • css-loader : CSS 파일을 불러옴.
  • file-loader : 웹 폰트나 미디어 파일 등을 불러옴.
  • babel-loader : JS 파일들을 불러오면서 최신 JS 문법으로 작성된 코드를 바벨이라는 도구를 사용하여 ES5 문법으로 변환해줌.

    ❔ 왜 변환하는가?

    ES5 : 이전 버전의 js
    버전 웹 브라우저는 최신 js 문법이 실행되지 않기 때문에 사전에 꼭 변환하여 호환해야 함.
    JSX도 정식 js 문법이 아니므로 ES5 형태의 코드로 변환해야 함.

📁 src/App.js

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}
  • App이라는 컴포넌트를 만듬.
  • function() ▶ 함수 컴포넌트
  • 컴포넌트를 렌더링하면 함수에서 반환하고 있는 내용을 나타냄.

2. JSX란?

JSX

  • JS 확장 문법이며 XML과 매우 비슷하게 생김.
  • 브라우저에서 실행되기 전에 코드가 번들링되는 과정에서 바벨을 사용하여 일반 JS 형태의 코드로 변환됨.

💻 JSX

function App() {
  return (
    <div>
      Hello <b>react</b>
    </div>
  );
}

🔽🔽🔽

💻 JS

function App() {
  return React.createElement("div", null, "Hello ", React.createElement("b", null, "react"));
}

JSX는 자바스크립트 문법이다?

NO!
공식적인 자바스크립트 문법이 아니다



3. JSX의 장점

1. 보기 쉽고 익숙하다
2. 더욱 높은 활용도
HTML 태그를 사용할 수 있고, 컴포넌트도 JSX 안에서 작성 가능.

📁 src/index.js

import ReactDOM from 'react-dom';
import './index.css';
import App from './App';

ReactDOM.render(
  <React.StrictMode>
    <App/>
  </React.StrinctMode>,
  document.getElementById('root')
);

📝 ReactDOM.render

  • 컴포넌트를 페이지에 렌더링하는 역할
  • react-dom 모듈을 불러와 사용할 수 있음.
  • 첫 번째 파라미터 : 페이지에 렌더링할 내용을 JSX 형태로 작성
  • 두 번째 파라미터 : 해당 JSX를 렌더링할 document 내부 요소를 설정.

📁 src/index.js

import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

📝 ReactDOM.createRoot

  • React 18은 더 이상 render를 사용하지 않고 createRoot를 사용하기를 권장
  • state나 props 변화가 있을 때, container가 변경되지 않더라도 계속 렌더링할 때 container를 전달했어야 했는데, 새로운 root API인 createRoot는 데이터 구조의 최상위 레벨에 있는 container를 전달하지 않아도 된다.

🔸 ReactDOM.render

const container = document.getElementById('app');

// Initial render.
ReactDOM.render(<App tab="home" />, container);

// During an update, React would access
// the root of the DOM element.
ReactDOM.render(<App tab="profile" />, container);

🔸 ReactDOM.createRoot

const container = document.getElementById('app');

// Create a root.
const root = ReactDOM.createRoot(container);

// Initial render: Render an element to the root.
root.render(<App tab="home" />);

// During an update, there's no need to pass the container again.
root.render(<App tab="profile" />);

📝 React.StrictMode

  • 리액트 프로젝트에서 리액트의 레거시 기능들을 사용하지 못하게 하는 기능.

    레거시 기능 : 더 이상 쓰지 않는 낡은 기능


  • 문자열 ref, componenetWillMount 등 나중에는 완전히 사라지게 될 옛날 기능을 사용했을 때 경고를 출력.

▶ createRoot를 사용한 곳에서 StrictMode를 사용하면, react-router-dom v5를 사용할 경우 제대로 작동하지 않으므로 최신 버전을 사용하거나 StricMode를 사용하지 않으면 됨.


4. JSX 문법

1) 감싸인 요소

  • 컴포넌트에 여러 요소가 있다면 반드시 부모 요소 하나로 감싸야 함.

📝 왜?

Virtual DOM에서 컴포넌트 변화를 감지해 낼 때 효율적으로 비교할 수 있도록 컴포넌트 내부는 하나의 DOM 트리 구조로 이루어져야 한다는 규칙이 있기 때문입니다.

  • div 요소를 사용하고 싶지 않다면?
    👉 Fragment 기능
import { Fragment } from 'react';

function App() {
  return (
    <Fragment>
    	<h1>리액트 안녕!<h1>
    	<h2>잘 작동하니?<h2>
    </Fragment>
  );
}

export defualt App;

또는

import { Fragment } from 'react';

function App() {
  return (
    <>
    	<h1>리액트 안녕!<h1>
    	<h2>잘 작동하니?<h2>
    </>
  );
}

export defualt App;

2) 자바스크립트 표현

  • 자바스크립트 표현식 : JSX 내부에서 코드를 { }로 감싸기
function App() {
  const name = '리액트';
  return (
    <>
      <h1>{name} 안녕!<h1>
    </>
  );
}

const와 let

  • const : 재선언 불가, 재할당 불가
  • let : 재선언 불가, 재할당 가능

  • var : scope - 함수 단위
function myFunction() {
  var a = "hello";
  if(true) {
    var a = "bye";
    console.log(a); // bye
  }
  console.log(a); //bye
}
myFunction();
  • if문 바깥 : "hello"
  • if문 내부 : "bye"
    함수 단위 -> if문 내부에서 새로 선언했음에도 if문 밖에서 a를 조회하면 변경된 값이 나타남.
  • let , const : scope - 블록 단위
function myFunction() {
  let a = 1;
  if(true) {
    let a = 2;
    console.log(a); // 2
  }
  console.log(a); // 1
}
myFunction();

블록 단위 -> if문 내부에서 선언한 a 값은 if 문 밖의 a 값을 변경하지 않음.

3) If 문 대신 조건부 연산자

  • JSX 내부의 자바스크립트 표현식에서 if문 사용 불가.
  • 조건에 따라 다른 내용을 렌더링해야 하는 경우
    1) JSX 에서 if 문을 사용하여 사전에 값을 설정
    2) { } 조건부 연산자(=삼항 연산자)를 사용
function App() {
  const name = '리액트';
  return (
    <div>
      {name === '리액트' ? (
        <h1>리액트입니다.</h1>
        ) : (
        <h2>리액트가 아닙니다.</h2>
        )}
      </div>
    );
}

export default App;

4) AND 연산자(&&)를 사용한 조건부 렌더링

조건을 만족하지 않을 때 아예 아무것도 렌더링하지 않아야 한다면?

  • 조건부 연산자 사용하기
    👉 null은 아무것도 나타나지 않음.
  • && 연산자 사용하기
    👉 리액트에서 false를 렌더링할 때는 아무것도 나타나지 않음.
    👉 주의) falsy한 값인 0은 예외적으로 화면에 나타난다.

5) undefined를 렌더링하지 않기

  • undefined만 반환하여 렌더링 -> ❗ 오류
    👉 OR(||)연산자 사용하기
function App() {
  const name = undefined;
  return name || '값이 undefined입니다.';
}
  • JSX 내부에서 undefined를 렌더링하는 것은 괜찮음.
function App() {
  const name = undefined;
  return <div>{name}</div>;
}

6) 인라인 스타일링

  • 스타일 적용 - 객체 형태로 넣어야 함.
  • 카멜 표기법(camelCase)
    background-colorbackgroundColor

7) class 대신 className

8) 꼭 닫아야 하는 태그

  • JSX에서는 태그를 닫지 않으면 오류가 발생함.
  • 태그 사이에 별도의 내용이 들어가지 않는 경우 :
<input></input>

self-closing 태그 : 선언하면서 동시에 닫을 수 있는 태그

<input/>

9) 주석

function App() {
  const name = '리액트';
  return(
    <>
      {/* 주석은 이렇게 작성합니다. */}
      <div
        className="react" // 시작 태그 여러줄이면 이렇게 작성 가능 ~
        >
        {name}
      </div>
      </>
    );
}
  • jsx 내부 : {/ - /}
  • 시작 태그 안 : //

5. ESLint와 Prettier 적용하기


6. 정리

JSX는 HTML과 비슷하지만 완전히 똑같지는 않습니다. 코드로 보면 XML 형식이지만 실제로는 JS 객체이며, 용도도 다르고 문법도 조금씩 차이가 납니다.

0개의 댓글