[TIL]210112

슬지로운 개발생활·2021년 1월 12일
0

TIL

목록 보기
56/73
post-thumbnail

React 1

What is React?

현재 웹페이지

  • 요즘 웹페이지는 단순히 데이터만 보여주는 것이 아니라 유저와 인터렉션이 일어난다.
    → 많은 인터렉션이 일어나려면 수많은 상태관리가 필요하다.
    • 예시 : 배경 이미지를 바꾸는 버튼을 눌렀을 때
      1. 바꿀 이미지 DOM을 찾는다.
      2. 이미지의 DOM의 소스를 바꿀 이미지로 바꿔준다.
      3. 바뀐 이미지를 화면에 다시 띄워준다.
  • 사용자와의 인터렉션이 많이 없다면 HTML과 CSS만으로도 충분하다.
    BUT! 인터렉션이 많아질 수록 즉, 관리해야될 DOM이 많아질 수록 이 모든걸 관리하는건 힘들다.
  • 귀찮고 복잡한 돔 관리와 상태값 관리를 최소화 해주고, 오직 기능개발에만 집중할 수 있는 방법을 고민했다.
    → 프론트앤드 라이브러리 / 프레임 워크가 만들어졌다.
    • React, Angular, Vue

React

  • 리액트는 컴포넌트라는 개념에 집중하고 있는 프론트엔드 라이브러리이다.
    • Component : 하나의 의미를 가진 독립적인 단위 모듈
      → 쉽게 말해, 나만의 HTML Tag라고 말할 수 있다.
  • 리액트는 컴포넌트 단위로 개발을 진행한다.

ES6 & JSX

ES6

  • 하기 코드와 같이 리액트는 기본적으로 ES6를 사용하고 있다.
    → ES6문법에 익숙해야 한다.
    • Destructuring
    • Spread Operator
    • Rest Parmeters
    • Default parameters : 값이 없거나 undefinded가 전달될 경우 이름붙은 매개변수를 기본값으로 초기화 할 수 있다.
    • Template literals
    • Arrow function
    • for of loop

JSX

자바스크립트의 확장 문법

  • 작성한 리액트 컴포넌트를 화면에 보여주기 위해 사용
    - 이미지와 같이 리액트 컴포넌트에서는 반드시 JSX를 리턴해주어야 한다.

  • JSX는 얼핏보면 HTML처럼 보일 수 있지만 JSX는 자바스크립트의 확장 문법이다.

  • JSX를 안쓰면 코드가 복잡해지고 가독성이 떨어진다.

    React.createElements('header', {className: 'App-container'}...);
    React.createElements('p', {className:'body'}...);
  • JSX를 써서 간편하고 가독성 좋게 코드를 만들수 있다.
    하기 코드와 같이 JSX문법을 사용하여 작성하면 Babel이 위와 같은 코드로 변환해 준다.

    <header className = 'App-container'>...</header>
    <p>...</p>
  • 주의할 점

  1. 반드시 하나의 엘리먼트로 감싸야 한다.
    오른쪽 이미지와 같이 하나의 엘리먼트 블록으로 구성해야 한다.

  1. 자바스크립트 코드를 적용할 땐 {} 안에 작성한다.

    class App extends Component {
      render() {
        const name = 'walli';
        return (
          <div>
            hello{name}!
          </div>
        )
      }
    }
  2. JSX 내부에선 if문을 사용할 수 없다.

    IIFE or 삼항연산자 사용

    <div>
    {
    (1 + 1 === 2) ? (<h1>정답</h1>) : (<h1>탈락</h1>)
    }
        </div>
  3. 엘리먼트의 클래스 이름을 적용할 때, className을 사용.
    → ES6문법에 class라는 keyword가 있어 className을 사용한다

Create React App

  • React proj를 시작하기 적합한 npm 패키지가 있다.
  • Create React App을 이용해 React Boilerplate(상용구) 코드를 생성한다.
    모든 명령이 완료되면, my-app 디렉토리에 React 프로젝트가 생성이 되며, 실행 후 http://localhost:3000 주소를 통해 실행 결과를 확인 할 수 있다.
    npx create-react-app my-app
    cd my-app
    npm start

    Create React App - Getting Started

Component와 Props

Component란 하나의 작은 tag(custom tag)와 같다.

Tweets.js 에 있는 Tweets라는 함수를 index.js에서
custom tag로 쓰고 있다.

import React from "react";
import ReactDOM from "react-dom";

import Tweets from "./App";

const rootElement = document.getElementById("root");
ReactDOM.render(
  <React.StrictMode>
    <Tweets />
  </React.StrictMode>,
  rootElement
);

이와 같이 우리가 새로운 컴포넌트를 만들 수 있다.

import React from "react";
import "./styles.css";

const comment = {
  author: {
    avatarUrl:
      "data:cat image url",
    name: "Hannah"
  },
  comment: "It's very confused",
  date: new Date().toLocaleDateString()
};

function AvatarImg(prop) {
  //이미지
  return (
    <div className="image-frame">
      <img src={prop.author.avatarUrl} alt={prop.author.name} width="100px" />
    </div>
  );
}

function User(prop) {
  //이미지 & 유저네임을 갖고 있는 컴포넌트
  return (
    <div className="User-info">
      <AvatarImg author={prop.author} />
      <span className="User-name">{prop.author.name}</span>
    </div>
  );
}

function Tweet(props) {
  //트위터(코멘트) 컴포넌트
  return (
    <div className="Tweet-wrap">
      <User author={props.author} />
      <div className="Comment">{props.comment}</div>
      <time>{props.time}</time>
    </div>
  );
}

export default function Tweets() {
  // 최종 출력할 형태
  return (
    <div className="App">
      <h1>Fake Twitter</h1>
      <h2>Welcome to React</h2>
      {/*Comment / tweets places*/}
      <Tweet // 함수 호출과 같은 너낌;
        author={comment.author} // prop.author
        comment={comment.comment} // prop.comment
        time={comment.date} // prop.time
      />
    </div>
  );
}

Component

  • 함수 컴포넌트, 클래스 컴포넌트가 있다.
    • 함수 컴포넌트 : 단순히 함수를 만들고 끝난다. 리턴 값은 반드시 JSX Element로 해주어야 한다.
    • 주요 차이점은 함수형 컴포넌트에는 State, lifeCycle라는 기능이 없고, 초기 마운트 속도가 아주 미세하게 빠르고, 불필요한 기능이 없기 때문에 메모리 자원도 덜 사용한다.
      → 단순히 어떤 값을 받아와서 보여지기만하는 그런 용도일때 함수형 컴포넌트를 사용하면 추후 컴포넌트가 많아질 시 속도가 최적화 될수 있다.
  • 컴포넌트에는 Props라는 것이 존재한다.
    • Props : 임의의 입력, parmeter(입력값/input)이라고 보면 된다.
      • 속성을 나타내는 데이터
      • HTML에서 attribute(속성)예시 : class="btn", href=""...etc. 이런것처럼
        props도 name="김코딩"(name props), content="나의 새 트윗"(content props)라고 부른다
      • content도 Props로 보낼 수 있다.
  • 모든 컴포넌트는 render라는 함수가 있어야 한다.

Props

  • 부모 컴포넌트가 자식 컴포넌트한테 값을 전달할때 사용된다.
    - 나중에 컴포넌트를 만들게 되면 그걸 불러와서 사용할 수 있다.
    - 어떠한 값을 컴포넌트 렌더링 할 때 전달해주고 싶다.
    - 값을 넣어주는것을 Props라고 한다.
    <Child value="value" /> //value가 하나의 Props이다
  • 부모 컴포넌트가 자식 컴포넌트한테 값을 전달할때 사용된다.
    - 나중에 컴포넌트를 만들게 되면 그걸 불러와서 사용할 수 있다.
    - 어떠한 값을 컴포넌트 렌더링 할 때 전달해주고 싶다.
    - 값을 넣어주는것을 Props라고 한다.
    <Child value="value" /> //value가 하나의 Props이다

State and Lifecycle

  • 상태와 Lifecycle
    • 현실세계와 흡사하다

State (상태)

  • props와 유사하지만, 비공개이며 컴포넌트에 의해 완전히 제어된다.
  • 살면서 변할 수 있는 값 (기분이 바뀌는 것, 나이 : 일년이 지나면 변하는 값)
  • 컴포넌트 사용 중 컴포넌트 내부에서 변할 수 있는 값
  • State를 갖는 컴포넌트는 함수 컴포넌트로 만들수 없고, class컴포넌트로 만들어야한다.
  • State는 컴포넌트 내부에 있고 컴포넌트 내부에서 바뀔 수 있는 값이고, 이 값이 바뀔때마다 이 컴포넌트는 리렌더링이 된다.
    • 값을 바꿀때에는 setState()라는 함수를 사용해야 한다.

Props vs. State

  • Props : 외부로부터 전달받은 값
    • 위로부터 넘겨받는다 → 인자와 같이 넘겨받을 수 있다.
  • state : 내부에서 변화하는 값
    • 컴포넌트 안에서만 변화되는 값
  • In real life examples
    • Props : general한, 혹은 일반적인 생각에 바꿀 수 없는 것들 / 태어날때 결정나는 것들
      • 이름
      • 성별
      • 출신
    • State : 변할 수가 있는 값,
      • 나이 : 1년마다 바뀌는 것
      • 현재 사는 곳 : 이사할때마다 바뀐다.
      • 취업 여부
      • 결혼 / 연애 여부

Lifecycle

  • 생명주기
  • 인생과 같다
    • 인생에 있어 중요한 순간은?
      • 태어날 때, 처음 학교에 갈 때, 성인이 될 때, 결혼을 할 때, 아이를 가질 때, 죽음을 앞두고 있을 때
  • 컴포넌트에 있어서 중요한 순간은?
    - 매 중요한 순간마다, 컴포넌트는 새로 렌더링(render)된다.
    - 생성
    - 생성될 때
    - 화면에 등장한(mount)후 : componentDidMount
    - 업데이트
    - 새로운 props를 받을 때
    - 새로운 상태를 가질 때
    - 새로운 상태를 갖고 난 후 : componentDidUpdate
    - 제거
    - 화면에서 사라지기(mount) 전 : componentWillUnmount
  • 클래스 컴포넌트에 적용시킬 수 있다.
    1. 처음 mount가 됐을때 비동기 요청을 보낼때가 많다.(fetch 혹은 setTimeout을 떠올리면 된다)
    2. Component안에서 비동기 요청을 보낼때 render나 constructor에서 비동기 요청을 호출할 수 없다.
      • constructor, render는 async / await으로 사용할 수 없다는 의미
    3. DidMount, DidUpdate일 때 비동기 요청을 할 수 있다.
    4. WillUnmount인 경우 복잡한 작업을 했는데 메모리를 비워줘야된다던지, 혹은 다 정리하고 싶을때 WillUnmount에서 추가해주면 깔끔하게 사라질 수 있다.
      • 구체적으로 clearTimeout이나, removeEventListener 등이 필요할 때 사용할 수 있다.

React에서의 데이터 흐름

  • React의 개발 방식의 가장 큰 특징은 페이지 단위가 아닌, 컴포넌트 단위로 시작한다는 점이 큰 특징이다.

    • 컴포넌트는 한가지 일만 한다.
  • 컴포넌트를 만들고, 페이지 조립(데이터를 어디에 둘지 결정)을 한다.

    • 상향식(bottom-up)으로 앱을 만든다.
      → 장점: 테스트가 쉽고, 확장성이 좋다.
      • 기획자, PM, 또는 UX 디자이너로부터 앱의 디자인을 전달받고 나면, 이를 컴포넌트 계층 구조로 나누는 것이 가장 먼저 해야 할 일이다.
  • 컴포넌트는 컴포넌트 바깥에서 props를 이용해 데이터를 마치 인자(arguments) 혹은 속성(attributes)처럼 전달 받을 수 있다.

    • 데이터를 전달하는 주체는 부모 컴포넌트가 된다.

      → 데이터 흐름이 하향식(top-down)임을 의미한다. : 단방향 데이터 흐름(One-way data flow)

    • 컴포넌트는 props를 통해 전달받은 데이터가 어디서 왔는지 전혀 알지 못한다.

State 끌어올리기(Lifting State Up)

데이터 정의

애플리케이션에서 필요한 데이터가 무엇인지 먼저 정의한다.

  • 예시
    • 전체 트윗 목록
    • 사용자가 작성중인 새로운 트윗 내용
  • 이 중 변하는 값(state)과 변하지 않는 값은 무엇인가요?
    • 사용장 입력 : 이벤트에 따라 얼마든지 변할 수 있다.
    • 트윗 목록 : 새 트윗 추가라는 기능을 염두해 두고 있기 때문에 state이다.
  • 어떠한 데이터를 상태로 두어야 하는지
    • 상태는 최소화 하는 것이 가장 좋다.
      → 상태가 많을 수록 애플리케이션은 복잡해진다.
    • 부모로부터 props를 통해 전달됩니까? → state가 아니다
    • 시간이 지나도 변하지 않나요? → state가 아니다.
    • 컴포넌트 안의 다른 state나 props를 가지고 계산이 가능한가요? → state가 아니다.

상태 위치 정하기

  • 상태가 특정 컴포넌트에만 유의미하다면, 특정 컴포넌트에만 두면 된다.
  • 만일 하나의 상태를 기반으로 두 컴포넌트가 영향을 받는다면 이때에는 공통 소유 컴포넌트를 찾아 그곳에 상태를 위치해야 한다.
    • 두 개의 자식 컴포넌트가 하나의 상태에 접근하고자 할 때는 두 자식의 공통의 부모 컴포넌트에 상태를 위치해야 한다.

역방향 데이터 흐름 추가

  • 상태 위치를 전부 정하고 나서 생각해보니, 부모 컴포넌트에서의 상태가 하위 컴포넌트에 의해 변하는 것을 발견할 수 있다.
    • 예시 : 새로운 트위 추가 → 부모의 상태를 변화시켜야 한다.
  • State 끌어올리기(Lifting state up)로 부모 컴포넌트의 상태를 바꿀 수 있다.

상태 끌어올리기

  • 단방향 데이터 흐름이라는 원칙에 따라, 하위 컴포넌트는 상위 컴포넌트로부터 전달받은 데이터의 형태 혹은 타입이 무엇인지만 알 수 있다.
  • 데이터가 state로부터 왔는지, 하드 코딩으로 입력한 내용인지는 알지 못한다.
    • 하위 컴포넌트에서의 어떤 이벤트로 인해 상위 컴포넌트의 상태가 바뀌는 것은 마치 "역방향 데이터 흐름"과 같이 조금 이상하게 들릴 수 있다.
      → React가 제시하는 해결책:
      상위 컴포넌트의 "상태를 변경하는 함수"그 자체를 하위 컴포넌트로 전달하고, 이 함수를 하위 컴포넌트가 실행한다.
    • 단방향 데이터 흐름 원칙에 부합하는 해결방법이다.
      → 이것이 '상태 끌어올리기'이다.

0개의 댓글