React 를 만났다.

수딩·2022년 6월 15일
0
post-thumbnail

리액트란

사용자 인터페이스를 만들기위한 자바스크립트 라이브러리
( = 사용자와 웹사이트의 상호작용을 돕는 인터페이스를 만들기위한 자바스크립트 기능모음집 )

라이브러리 :
자주 사용되는 기능들을 정리해 모아 놓은 것

사용자 인터페이스
(User Interface, UI)
흔히 보는 버튼도 인터페이스

UI 라이브러리 : 회면을 만들기 위한 기능들을 만들어 놓은 것

프레임워크 vs 라이브러리
프로그램의 흐름에 대한 제어 권한
프레임워크는 프레임워크 자신에게 있음
라이브러리는 개발자가 필요한 부분만 사용할 수 있음. 즉, 개발자에게 있음

웹사이트의 작동원리와 흐름을 함께 이해하는 것이 중요!

리액트의 장점과 단점
장점

  • 빠른 업데이트 (virtual DOM => 가상의 돔)
    돔 : 웹페이지에 대한 정보를 담고있는 큰 그릇.
    리액트에서 사용하는 돔은 virtual DOM . 업데이트할 최소의 부분만 찾아서 변경, 랜더링
  • Component-based 모든 페이지가 컴포넌트로 되어있음. 레고블록 조립하듯 컴포넌트를 모아서 개발

    => 재사용성 (Reusability): 다시 사용이 가능한 성질
    재활용 != 재사용
    재사용은 계속 사용이 가능 . (소프트웨어 분야에서만 사용하는 단어)

    다른 모듈의 의존성을 낮추고 호환성문제를 생각해서 개발해야 한다
    => 개발 기간이 단축된다
    => 유지보수가 용이하다 (각 부분들이 잘 분리되어있어서 버그 쉽게 찾을 수 있음)

단점

  • 방대한 학습량 , 새로운 개념이 많음, 계속 바뀜(버전업데이트가 지속되고있음)
  • 높은 상태관리 복잡도

JSX

JSX란 : A Syntax extansion to JavaScript 자바스크립트의 확장 .
JacaScript + XML/HTML

const ele = <h1>hello</h1>

JSX의 역할
내부적으로 XML/ HTML 로 작성한 코드를 JS 로 변환한다.

리액트에서 JSX를 사용하는건 필수는 아니지만 JSX를 사용하면 가독성이 좋기 떄문에 편리함!
JSX 장점

  • 간결한 코드
  • 가독성 향상 > 버그를 발견하기 쉬움
  • Injection Attacks 방어

JSX 사용법
XML/ HTML 을 쓰다가
자바스크립트를 쓰고 싶으면 {중괄호} 를 쓰면 됨

태그의 속성(attribute)에 값을 넣는 방법

//큰따옴표 사이에 문자열을 넣거나 
const element = <div tabIndex="0"></div>;

//중괄호 사이에 자바스크립트 코드를 넣으면 된다
const element = <img src={user.avatarUrl}></img>;

자식 (children) 을 정의하는 방법

const element = (
  <div>
    <h1>자식을 정의하는 방법</h1>
      <h2>JSX 신기해</h2>
  </div>
)

Rendering Elements

Element 란? 어떤 물체를 구성하는 성분
React Elements 란 리액트를 구성하는 가장 작은 요소.
'Elemnets are the smallest buliding blocks of React apps'

리액트 엘리먼트는 돔 엘리먼트의 가상 표현이라 보면 된다.
화면에서 보여지는 것을 기술.

자바스크입트 객체 형태로 존재

type: "button",
  props: {
    classNace: "bg-green",
    children: {
      type: "b",
      props: {
        children: "Hello, element",
      },
    },
  }

위 엘리먼트가 실제로 랜더링 된다면 아래와 같은 돔 엘리먼트가 된다

<button class="bg-green">
  <b>
    Hello, element!
  </b>
</button>

컴포넌트는 엘리먼트의 속성들은 아래 코드와 같다.

React.createElement(
  type,
  [props], 
  [...children]
)

컴포넌트 rendering 위해 모든 컴포넌트가 createElement 를 통해 엘리먼트로 변환된다는 것을 기억하자!

React Elements의 특징

  • 불변성 imnnutable
    한 번 elements 생성 후에는 children 이나 attributes를 바꿀 수 없다.

우리 눈에 보이는 것을 기술한다고 햇는데 element가 불변하다면 화면갱신이 안되는 것 아닌가?
'한 번 elements 생성 후에는 children 이나 attributes를 바꿀 수 없다.' 를 다시 보면

붕어빵을 예로 들면 component 는 붕어빵 틀, element는 붕어빵이다.
구워져 나온 붕어빵은 엘리먼트 생성이 끝난거이기 때문에 바꿀 수 없는거라고 생각하면 쉽다.
구워져 나오는 과정은 엘리먼트를 생성하는 것.

그렇다면 화면에 변경된 엘리먼트를 보여주기 위해서는??
=> 기존의 엘리먼트를 변경하는 것이 아니라 새로운 엘리먼트를 만들어 기존의 엘리먼트와 바꿔침

렌더링하기

Root DOM Node

<div id="root"></div>


root div 에 실제로 렌더링 하기 위해 아래 코드처럼 작성한다.

const element = <h1>안녕</h1>;
ReactDOM.render(element, document.querySelector('#root'));

이 코드는 먼저 엘리먼트를 생성하고 생성된 엘리먼트를 root 에 렌더링 하는 코드.
렌더링 위해 ReactDOM.render 을 사용 =>
첫번째 parameter 에 있는 react element를 두번째 parameter의 Html 엘리먼트, 즉 DOM element에 렌더링 하는 역할을 한다.
여기서 한번 더 짚고 넘어가자면 react element는 리액트 버츄얼 돔에 있고 DOM 엘리먼트는 실제 브라우저의 돔에 존재한다.
렌더링 한다는 말이 리액트 버추얼 돔에서 실제 돔으로 이동하는 과정이라고 할 수 있다.

렌더링된 Elements를 업데이트 하기

엘리먼트는 불변성을 갖고 있기 때문에 엘리먼트를 업데이트 하기 위해서는 다시 생성해야 한다.

function tick() {
  const element = (
    <div>
      <h1>hi</h1>
      <h2>what time? {new Date().toLocaleTimeString()}</h2>
    </div>
  );

  ReactDOM.render(element, document.querySelector("#root"));
}

setInterval(tick, 1000);

Components and Props

이해될때까지 연습하기

Component-Based

리액트 컴포넌트는
작은 컴포넌트가 모여 하나의 컴포넌트를 구성하고 또 이런 컴포넌트들이 모여서 전체 페이지를 구성한다.
이랙트 컴포넌트를 하나의 함수 라고 생각해도 된다.
근데 입려과 출력이 자바스크립트의 함수와 다르다 .

자바스크립트 객체 형태로 존재.

Props

: 컴포넌트에 전달할 다양한 정보를 담고있는 자바스크립트 객체

리액트 컴포넌트의 입력으로 들어감 .
Property 를 줄여서 prop이라고 한다.
property 는 사전적으로 속성 이라는 뜻이다.
무엇의 속성? => component의 속성

붕어빵으로 생각하면 이해가 쉬움.

같은 리액트 컴포넌트에서 눈에 보이는 글자는 색 바꿔줄 수 있는 재료 라고 생각하기

네가지 다 같은 컴포넌트로 생성되었지만, 그 속성이 다름을 볼 수 있는데 그걸 Props를 이용해서 바꿔주는 것이다 .

Props 특징

Props는 Read-Only 이다.
읽을 수만 있다 = 값을 변경 할 수 없다.
(마치 붕어빵을 다 구웠는데, 속재료를 바꿀 수 없음을 생각하면 된다,.)
그럼 값을 바꿔주고 싶다면? => 새 element를 생성!

모든 리액트 컴포넌트는 그들의 Props에 관해서는 Pure 함수같은 역할을 해야 한다.

Pure 함수란? 같은 입력값에 대해 항상 같은 결과값을 보여주는 함수

function add(a,b) {
	return a+b
}

이해하기 쉽게 말하면!
모든 리액트 컴포넌트는 Props를 직접 바꿀 수 없고, 같은 Props에 대해서는
항상 같은 결과(react element)를 return 할 것이라는 말이다.

Props 사용법

function App(props) {
  return <Profile name=""
   introduction="hi i'm su"
    viewCount={1000} />;
}

이렇게 하면 이 속성의 값들이 모두 profile 컴포넌트의 Props로 전달되며
Props 함수는 아래와 같은 자바스크립트 객체가 된다.

{
  name:'수',
  introduction : "hi i'm su",
  viewCount : 1000
}

중괄호를 사용해서 props값에 컴포넌트도 넣어줄 수 있다.

function App(props) {
  return (
    <Layout
      width={2560}
      height={1000}
      header={<Header title="리액트연습중" />}
      footer={<Footer />}
    />
  );
}

jsx 를 사용하는 경우 간단하게 컴포넌트에 props 를 넣을 수 있다.

component 만들기

컴포넌트는 Function Component / Class Component 가 있다.
Class Component가 불편해서 만든게 Function Component 이고, 함수 컴포넌트를 개선해서 만든게 Hook 이다.

Function Component

모든 리액트 컴포넌트는 pure 한 역할을 해야 한다.
이 말은 결국 리액트 컴포넌트를 하나의 함수 라고 생각해야 한다는 말이다

이 코드를 보면

function Welcome(props) {
  return <h1>안녕, {props.name}</h1>
}

하나의 props 를 받아서 하나의 리액트 엘리먼트를 리턴하기 떄문에 리액트 컴포넌트라고 볼 수 있다.
그리고 이런 형태를 함수 컴포넌트라고 할 수 있다.

Class Component

함수컴포넌트와의 가장 큰 차이점은, 리액트의 모든 클래스 컴포넌트는 React.Component를 상속받아 만든다.

위 함수형 컴포넌트의 코드와 동일한데, Class 컴포넌트를 이용하면 이렇게 작성해야 한다.

class Welcome extends React.Component {
  render() {
    return <h1>안녕, {this.props.name}</h1>;
  }
}

컴포넌트 이름은 항상 대문자로 시작!

예를 들면

const element = <div/> 

이렇게 작성하면 HTML div 태그로 인식하고
대문자로 작성을 하면,

const element = <Welcome name="수수"/> ;

Welcome 이라는 리액트 Component 로 인식한다.

component rendering

DOM 태그를 사용한 element

const element = <div/> 

사용자가 정의한 Component를 사용한 element

const element = <Welcome name="수수"/> ;

이걸 렌더링하기 위한 실제 코드

function Welcome(props) {
  return <h1>안녕,{props.name}</h1>;
}

const element = <Welcome name="" />;
ReactDOM.render(element,
   document.querySelector("#root")
   );

Component 합성

Component 안에 또 다른 Component를 쓸 수 있다
복잡한 화면을 여러개의 Component로 나눠서 구현이 가능하다

function App(props) {
  return (
    <div>
      <Welcome name="Mike" />
      <Welcome name="Steve" />
      <Welcome name="Jane" />
    </div>
  );
}

Welcome 컴포넌트로 컴포넌트 합성을 하는 코드이다.
Props의 값을 다르게 해서 Welcome 컴포넌트를 여러개 쓰고 있음.
여러개의 컴포넌트를 합쳐서 App 컴포넌트를 만들었음.

Component 추출

큰 컴포넌트를 쪼갬!
재사용성 up 개발속도 up

  1. Avatar 추출

    지금 이 Comment 컴포넌트에서 Avatar 이라는 별도의 컴포넌트를 추출해보자
function Avatar(props) {
  return (
    <img
      className="avatar"
      src="{props.user.avatarUrl}"
      alt="{props.user.name}"
    />
  );
}

이렇게 Avartar 컴포넌트를 추출했으니, 다시 Comment 컴포넌트에 넣어야한다.

  1. userInfo 추출하기

    이 부분을 별도의 컴포넌트로 만들면
function UserInfo(props) {
  return (
    <div className="user-info">
      <Avatar user={props.user} />
      <div className="user-info-name">{props.user.name}</div>
    </div>
  );
}

위에서 만든 Avatar 컴포넌트도 같이 추출

Comment 컴포넌트는 이렇게 변하고

그림으로 살펴보면 이렇게 된다.

State and Lifecycle

state 는 이해될 때까지 공부하기
state : 상태 , react component의 변경가능한 데이터
사전에 정해져 있는게 아니라 개발자가 정의한다.
state 를 정의할 때 중요한 점은
렌더링이나 데이터 흐름에 사용되는 값만 state 에 포함시켜야 함!
왜냐면 state 가 변경 될 경우 컴포넌트가 재렌더링되기 때문에 렌더링과 데이터흐름에 관련없는 값을 포함하면 불필요한 경우에 컴포넌트가 재실행 => 성능저하로 이어짐

state 는

  • JavaScript 객체이다.
  • 직접 수정할 수없다. 수정 하면 안된다!
// state를 직접 수정 (잘못된 사용범)
this.state = {
  name: "su",
};
// setstate 함수를 통한 수정 (정상적인 사용법)
this.setState({
  name: "su",
});

꼭 setState 를 통해 변경해야 함 !

Lifecycle

Component 가 계속 존재하는 것이 아니라,
시간의 흐름에 따라 생성되고 업데이트 되다가 사라진다.

상위컴포에서 하위 컴포를 사용하지 않을때 Unmounting 이 된다.

Notifiaction 에서 눈여겨봐야할 부분은 state 선언이다.
처음 생성된 notifications 라는 빈 배열을 state 에 넣어줬다.

이처럼 생성자에서는 앞으로 사용할 데이터를 state 에 넣어서 초기화 한다!

import React from "react";
import Notification from "./Notification";

const reservedNotifications = [
  {
    message: "안녕하새요, 오늘 일정을 알려드립니다.",
  },
  {
    message: "점심식사 시간입니다",
  },
  {
    message: "이제 곧 미팅이 시작됩니다.",
  },
];

let timer;

class NotificationList extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      notifications: [],
    };
  }

  componentDisMount() {
    const { notifications } = this.state;
    timer = setInterval(() => {
      if (notifications.length < reservedNotifications.length) {
        const index = notifications.length;
        notifications.push(reservedNotifications[index]);
        this.setState({
          notifications: notifications,
        });
      } else {
        clearInterval(timer);
      }
    }, 1000);
  }

  render() {
    return (
      <div>
        {this.state.notifications.map((notification) => {
          return <Notification message={notification.message} />;
        })}
      </div>
    );
  }
}

export default NotificationList;

클래스 컴포넌트의 생명주기 함수 중 하나인 componentDidMount 함수는 자바스크립트의 setInterval함수를 사용하여 매 1000ms 마다 정해진 작업을 수행하고 있다.
이 작업은 미리 만들어 둔 알림 데이터(reservedNotifications)로부터
데이터를 하나씩 가져와서 state 에 있는 notifications 에 넣고 업데이트 하는 것

주의해야 할 부분은

setState 를 사용했다는 것!

즉, Class Component 에서 상태를 업데이트 하기 위해서는 반드시 setState를 사용해야 한다.

참고 및 출처 : 인프런 처음만난 리액트

profile
Front-End Developer ✨

0개의 댓글