React: CRA, husky, lint-staged

Create React App


CRA

react, react DOM 라이브러리와는 별개로 이것들을 편하게 사용할 수 있도록 프로젝트를 생성해주는 역할을 한다.
단순히 프로젝트를 생성하는 것이 아니라 개발하면서 필요한 여러가지 기능들을 제공한다.

  • react 프로젝트 만들기

    npx create-react-app 파일명
    

    해당 명령어를 통해 react 프로젝트를 만드는 데 필요한 여러 패키지들이 다운된다.

  • react-scripts

    package.json 파일을 확인하면 react-scripts를 확인할 수 있다.
    해당 라이브러리는 CRA 라이브러리이다. 해당 프로젝트를 개발환경에 띄운다던가 배포를 위한 빌드작업을 하는 등의 역할을 한다.

husky


git hook을 쉽게 사용할 수 있도록 해준다.
hook은 git으로 인해 어떤 액션이 발생할때 무언갈 추가로 해주고 싶은 것을 처리해주는 도구이다.

husky는 꼭 git을 설치하고 난 후, 설치해야 한다. (아니면 오류가 발생할 수도..)

# husky 설치
npm i husky -D

# husky에서 git hook을 활성화 시키기 (git hook 설치)
npx husky install

package.json 파일에 해당 코드 추가

"scripts": {
	"prepare": "husky install",
	...
}
# hook 추가하기
npx husky add ./husky/이름 "npm test"
  • 해당 기능은 언제 사용할까?

    커밋이 되기 직전에 코드를 점검할 때 사용한다.
    husky는 커밋전에 확인해서 정리가 안되면 커밋을 시키지 않아 강제로 뭔가를 처리할 수 있도록 하기 때문에 점검할 때 유용하게 사용할 수 있다.
    따라서 커밋이 되었다는 것은 점검을 마쳤다는 것으로 볼 수 있다.

lint-staged


husky, lint-staged를 사용하자( sub : ESLint 자동화하기 )

lint-staged는 stage 상태의 git 파일에 대해 lint와 우리가 설정해둔 명령어를 실행해주는 라이브러리다. 즉, eslint, prettier, husky를 자동화 해주는 거랄까?!

여기서 stage 상태란, 파일들이 git add로 커밋 대상이 된 상태를 말한다.

# hook 추가하기 (husky 설치 후)
npx husky add ./husky/이름 "lint-staged"

# lint-staged 설치
npm i lint-staged -D

package.json 파일에 lint-staged 설정을 추가할 수 있다.
해당 확장자를 가진 것 혹은 특정 파일이 커밋될 때, 무언갈 하겠다는 의미이다.

"lint-staged": {
	"**/*.js": [
		"eslint --ifx",
		"git add"
	]
}

해당 코드는 어느 파일에서든 js 확장자를 가진 파일이 커밋된다면 eslint를 통해 fix하고 git에 add를 하겠다는 의미이다.

추가로 prettier도 사용한다면 prettier 패키지 설치 후 prettier —write 명령어를 추가 작성해주면 된다.

React: Component Lifecycle

Component Lifecycle


[React.js] 리액트 라이프사이클(life cycle) 순서, 역할, Hook

Component – React

생성(mounting) → 업데이트(updating) → 제거(unmounting)
리액트 컴포넌트는 라이프 사이클 메서드를 사용하며, 함수형 컴포넌트는 Hook을 사용한다.

  • Mount

    컴포넌트가 생성될 때

    • constructor

      컴포넌트 생성자 메서드로, 컴포넌트가 생성되면 가장 먼저 실행되는 메서드이다.
      props, state에 접근이 가능하며 리액트 요소를 반환한다.

    • getDerivedStateFromProps

      props로부터 파생된 state를 가져온다. (props로 받아온 것을 state에 넣어주고 싶을때 사용한다.)

    • render

      컴포넌트를 랜더링한다.

    • componentDidMount

      컴포넌트 출력물이 DOM에 랜더링 된 후에 실행된다. 즉, 첫번째 랜더링을 마치면 호출된다.
      해당 메서드가 호출된다면 화면에 컴포넌트가 이미 나타난 상태이다.

  • Updating

    컴포넌트가 업데이트 될때

    • getDerivedStateFromProps

      props나 state가 바뀌었을 때 호출된다.
      시간 흐름에 따라 변화되는 Props에 state가 의존하는 드문 경우를 위해 존재한다고 생각하면 된다.

    • shouldComponentUpdate

      컴포넌트가 리랜더링 할지 말지를 결정한다.

    • getSnapshotBeforeUpdate

      render가 되고 실제로 DOM에 적용되기 직전에 호출된다.
      DOM에 적용되기 직전의 상태를 기억했다가 DOM에 적용된 직후에 조절할 것이 있을 때 사용한다.

    • componentDidUpdate

      컴포넌트가 업데이트 되고 난 후에 발생한다.

  • Unmount

    unmount는 컴포넌트가 화면에서 사라졌을 때를 말하는데 생명주기는 죽기 직전까지이므로, 화면에서 사라지기 직전을 의미한다.

    • componentWillUnmount

      컴포넌트가 화면에서 사라지기 직전에 호출된다.
      DOM에 등록했던 이벤트를 제거하거나 setTimeout을 사용했다면 clearTimeout을 사용하여 제거한다.

  • ComponentDidCatch

    에러 경계(Error Boundaries) – React

    component의 에러를 캐치한다.
    해당 라이프사이클이 일어난 하위 컴포넌트에서 문제가 발생했을 때, 부모 컴포넌트에서 에러 화면이 아닌 다른 화면을 보여줄 수 있도록 한다.

    에러가 발생했다는 화면은 개발환경에서만 보여지고 실제 유저에게 보여지는 화면은 빈 화면이 나오게 된다. 이런 상황에서 혼란을 방지하기 위해서 에러가 발생했을 때, 빈 화면이 아닌 에러가 발생했다는 문구의 화면을 보여줄 수 있도록 하는 것이 해당 메서드이다.

React: JSX, props and state, event handling

JSX


JSX 소개 – React
Babel

babel이 html 문법으로 작성한 형태를 React createElement 형태로 변환시켜준다. 즉, 어렵게 작성하지 않고 html 형태로 작성해도 된다.

const element = (
  <div>
    <h1>Hello!</h1>
    <h2>Good to see you here.</h2>
		<h1 className="greeting">
    Hello, world!
	  </h1>
  </div>
);
  • JSX 사용 이유

    React.createElement 보다 가독성이 훨씬 좋다.
    babel과 같은 컴파일 과정에서 문법적 오류를 인지하기가 쉽다.

  • JSX 규칙

    최상위 요소가 하나여야 한다. (최상위 요소가 두개 존재하면 error)
    만약! 같은 최상위 요소를 두개 만들고 싶다면? Fragment를 사용한다.
    <></> 태그를 최상위 요소로 사용하는 것이다.

    중괄호{}를 사용하여 자바스크립트 표현식을 사용한다. (중괄호 안에 문자열, 변수 등)

    if문은 사용할 수 없다.
    삼항 연산자 혹은 &&를 사용한다.

    class 대신에 className을 사용해서 class를 적용한다.

    자식요소가 있다면 꼭 닫아야 하며, 자식요소가 없으면 열면서 닫아야 한다.

Props와 State


  • props

    컴포넌트 외부에서 컴포넌트에게 주는 데이터이다.

    class Component extends React.Component {
      render() {
        return (
        <div>{this.props.message}</div>
        )
      }
    }
      
    ReactDOM.render(
      <Component message="Hello" />
    );
    
  • state

    컴포넌트 내부에서 변경할 수 있는 데이터이다.

    class Component extends React.Component {
      state = {
        count: 0
      }
      
      render() {
        return (
        <div>{this.state.count}</div>
        )
      }
    }
    

두가지 모두 변경이 발생하면 render가 다시 일어날 수 있다. 즉, 컴포넌트는 다시 그림을 그리려고 한다.

  • render()

    props와 state를 바탕으로 컴포넌트를 그린다.
    props와 state가 변경되면 컴포넌트를 다시 그린다. 컴포넌트를 그리는 방법을 기술하는 함수가 랜더함수이다.

    • React는 Virtual DOM을 사용해서 성능을 개선했다. DOM을 직접 조작하지 않고, 가상 돔 트리를 사용하여 변경된 부분만 바꿔준다.
    • CSR은 모든 JS 파일을 다운로드 받기 전까지 화면에 아무것도 출력하지 않는다. SSR은 JS 파일을 다운로드 받지 않아도 화면에 보이지만, 유저가 사용하지 못하다가 JS 파일을 모두 다운로드 받으면 사용 가능해진다.
    • React 컴포넌트는 함수로 이루어져 있으며, 인자로 props가 들어오고, 함수 안에서는 반드시 return을 해주어야 한다. React 컴포넌트는 React Element를 return해야 한다.
    • React는 Virtual DOM을 사용해서 성능을 개선했다. DOM을 직접 조작하지 않고, 가상 돔 트리를 사용하여 변경된 부분만 바꿔준다.
    • CSR은 모든 JS 파일을 다운로드 받기 전까지 화면에 아무것도 출력하지 않는다. SSR은 JS 파일을 다운로드 받지 않아도 화면에 보이지만, 유저가 사용하지 못하다가 JS 파일을 모두 다운로드 받으면 사용 가능해진다.
    • React 컴포넌트는 함수로 이루어져 있으며, 인자로 props가 들어오고, 함수 안에서는 반드시 return을 해주어야 한다. React 컴포넌트는 React Element를 return해야 한다.

Event Handling


HTML DOM에 클릭하면 이벤트가 발생하고, 그에 맞는 변경이 일어나도록 한다.

Event Handling은 camelCase로만 사용할 수 있다. (onClick, onMouseEnter)
이벤트에 연결된 자바스크립트 코드는 함수이다. (이벤트={함수}와 같이 쓴다.)
실제 DOM 요소들에만 사용이 가능하다. (리액트 컴포넌트에 사용하면, 그냥 props로 전달된다.)

function Component() {
	return (
		<button
			onClick={() => {
				console.log("clicked")
			}}
		>
			click!
		</button>
	)
}

React: React Component, React.createElement

React Component


  • Class 컴포넌트

    class 컴포넌트는 꼭 render를 해줘야 한다.

    import React from 'react';
      
    // 정의
    class ClassComponent extends React.Component {
      render() {
        return (<div>Hello</div>)
      }
    }
      
    // 사용
    <ClassComponent />
    
  • Function 컴포넌트

    import React from 'react';
      
    // 정의1
    function FunctionComponent() {
      return <div>Hello</div>
    }
      
    // 정의2
    const FunctionComponent = () => <div>Hello</div>
      
    // 사용
    <FunctionComponent />
    

React.createElement


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

    태그 이름 (문자열), 기존에 작성한 리액트 컴포넌트, React.Fragment

    • 태그 이름 (문자열) type

      ReactDOM.render(
        React.createElement("h1", null, `type이 "태그 이름 문자열"입니다.`)
      )
      

      type이 h1이고 데이터를 주입하지 않으며 자식으로는 해당 문자열(type이 블라블라)이 들어가는 react element를 만들었다.

      <h1>type이 “태그 이름 문자열”입니다.</h1>

    • 리액트 컴포넌트 type

      const Component = () => {
        return React.createElement(
          "p",
          null,
          `type이 "리액트 컴포넌트" 입니다.`
        )
      }
          
      ReactDOM.render(React.createElement(Component))
      // ReactDOM.render(React.createElement(Component,null, null))
      

      <p>type이 “리액트 컴포넌트”입니다.</p>

    • React.Fragment

      ReactDOM.render(
        React.createElement(
          React.Fragment,
          null,
          `type이 "React.Fragment"입니다.`,
          `type이 "React.Fragment"입니다.`,
          `type이 "React.Fragment"입니다.`
        )
      )
      

      React.Fragment는 DOM에 별도의 노드를 추가하지 않고 여러 자식을 그룹화할 수 있다.

      Fragments – React

  • props

    리액트 컴포넌트에 넣어주는 데이터 객체

  • children

    자식으로 넣어주는 요소들

React: 시작하기

React Concept


  • Component

    img, div같이 이미 정해진 태그 이름이 아닌, 내가 직접 만든 태그이다. 즉, 내가 정의한 컴포넌트이다!

    src, class, name, props는 밖에서 넣어주는 데이터이다.
    html, css, js를 합쳐서 내가 정의한 이름으로 정의하여 남들도 사용할 수 있고 나도 재사용이 가능한 태그(같은 것)이다.

  • Virtual DOM

    react는 DOM을 직접 제어하지 않는다.
    가상의 돔 트리를 사용해서, 이전 상태와 이후 상태를 비교하여 바뀐 부분을 찾아 자동으로 바꿔준다.

    달라진 부분을 찾아서 diff로 달라진 부분과 해당 하위를 달라진 내용으로 변경해준다.

  • CSR (Client Side Randering)

    js가 전부 다운로드 되어 react 앱이 정상 실행되기 전까지 화면에 보이지 않는다. js가 전부 다운되어 react 앱이 정상 실행된 후, 화면이 출력되며 유저가 인터랙션이 가능해진다.

    html 다운 → js 다운 → js 안에서 react 앱을 실행 (아직 화면에 보이는 것 없음) → react 내부의 컴포넌트가 화면에 출력 → user에게 보임

  • SSR (Server Side Randering)

    js가 전부 다운되지 않아도 화면에 보인다. 하지만, 유저가 사용할 수는 없다. js가 전부 다운되어 react 앱이 정상 실행되면 유저가 사용이 가능하다.

    html 다운 → js 다운(과 동시에 이미 랜더링 된 html 파일이 화면에 보임, 단 동작은 되지 않음) → react 앱 실행 (js까지 다운된 화면 보임) → react 화면 출력 (완벽한 웹 사용 가능)

React 라이브러리

  • React 핵심 모듈

    // 1
    import ReactDom from 'react-dom';
    // 2
    import React from 'react';
    
    1. ReactDom은 리액트 컴포넌트로 HTMLElemnet와 연결한다.
    2. React는 리액트 컴포넌트를 만든다.
  • react 시작

    # npm 프로젝트 만들기
    npm init -y
      
    # 파일 서버처럼 관리
    npx serve
    
  • react CDN

    CDN 링크: React

  • react로 render

    바닐라 js는 값들이 변경될 때마다, render를 해줘야 한다.
    처음 초기화 할때와 값이 바뀔때마다 계속 render를 해줘야 하는데, react는 이걸 좀 더 간편하게 해준다.

    const Rㅣ액트컴포넌트이름 = props => {
      return React.creatElement(
        규정할 , 넣어줄 , 
        태그 안에 들어갈 
      );
      // 예시
      return React.creatElement(
        'p', 
        null, 
        `${props.message} : ${props.count}`
      );
    }
      
    ReactDOM.render(리액트 컴포넌트, 실제로 그려질 )
    // 예시
    ReactDOM.render(
      React.createElement(Component, {message: "init", count: "0"}, null),	
      document.querySelector('#root')
    );
    

    리액트 컴포넌트는 기본적으로 함수라고 생각하면 된다.
    인자로 props가 들어오고, 함수 안에서 꼭 return을 해줘야 한다. return을 할때, react의 element로 return이 돼야한다.
    react element는 실제 dom element가 아니고 react가 규정하는 방식으로 만들어진 element를 의미한다.