본문 바로가기

Education

[개발스터디] week3: Next.js로 서버 만들기 / React.js

반응형

2021-06-30 Week 3

스터디 내용

  • check week2 homework
  • Next.js로 Backend 만들기
  • React.js tutorial - main concepts

 

1. Check homework

  • 목표: '자바스크립트는 싱글 스레드인데, 어떻게 동시에 코드를 처리할 것인가?'에 대해 고민하기
  • API가 애초에 딜레이가 있도록 만들어졌기 때문에 4초 부근으로 나올 수 밖에 없다. 

1.1 code review

목표와 의도에 부합하게 코드를 잘 작성하였다. 특히나 잘못하면 콜백지옥에 빠질 수 있는데, 콜백지옥에 빠지지 않게 잘 작성하였다. 또한 Promise.all 메서드를 사용하면 여러 개의 프라미스를 동시에 실행시키고 모든 프라미스가 준비될 때까지 기다리기 때문에 소요되는 시간을 줄일 수 있었다.

 

1.2 콜백 함수를 사용하는 이유?

week 2 게시글에서도 작성했듯이, 코드를 동기적으로 처리하기 위해 사용한다.

자바스크립트는 싱글 스레드로 동작하기 때문에 코드를 비동기적으로 처리한다. 하지만 ajax 통신과 같이 결과값을 받을 때까지 기다려야하는, 순서대로 수행해야 하는 경우도 있으므로, 이러한 경우를 위해 코드를 동기적으로 처리하도록 하는 콜백함수를 사용한다.

 

(+) 이벤트 루프 개념도 함께 알아두자! ➡ 2021.04.07 - [Web/Node.js] - 1. 노드 시작하기

 

1.3 Async & Await

ES6에서 추가된 개념이다. Promise를 동기적으로 처리하도록 도와준다.

 

1.4 Promise.all()

Promise를 반환하는 여러 개의 함수들을 비동기적으로 병렬로 실행시킨다. 자세히 알고 싶다면 해당 사이트를 참고하자.

 

 

2. Next.js로 Backend 만들기

2.1 Base Url

baseUrl란?

baseUrl은 2010년에 최초로 추가되었고, 의도는 다음과 같다.

내부 웹서버를 이용하여 테스트하는 유저가 프로덕션에 배포될 때와 같은 baseUrl을 가지고 테스트를 할 수 있도록 하기 위해서.

 

-예제

출처: https://kairos03.github.io/jekyll/2017/09/11/learing-Up-Confusion-Around-baseurl.html

다음 예제에서 baseUrl은 '/example'이다. config.json에서 다음과 같이 작성했을 것이다.

baseUrl: '/example'

웹 사이트를 개발하고 서버를 실행시키면 보통 http://localhost:4000/와 같은 주소로 들어간다. 하지만 이렇게 작성하게 되면 http://localhost:4000/example/로 들어간다. 

baseUrl은 사이트가 존재하는 도메인에 상대적인 기본 경로를 지정한다. 만약 위의 상태에서 http://localhost:4000/에 접속한다면 에러 메시지가 뜬다. 이 상태에서 모든 링크를 올바르게 걸었다면, 경로의 시작 부분에 /example이 없는 url은 절대 볼 수 없을 거다. 

 

경로 매핑 (Path mapping)

가끔 모듈이 baseUrl 아래에 위치하지 않은 경우가 있다. 예로 들면 'jquery' 모듈의 import는 런타임에서 'node_modules/jquery/dist/jquery.slim.min.js'로 번역된다. 다음과 같이 번역되는 이유는, 로더가 런타임에 모듈 이름을 파일에 매핑하기 위해서 매핑 구성을 사용하기 때문이다.

위의 경우를 적용하는 예제를 살펴보자. 각 언어마다 파일 이름을 다르게 지정하는데, TypeScript 컴파일러는 tsconfig.json 파일 안에 'paths' 프로퍼티를 사용한 매핑의 선언을 지원한다. JavaScript는 jsconfig.json이다.

{
  "compilerOptions": {
    "baseUrl": ".", // "paths"가 있는 경우 반드시 지정되어야함.
    "paths": {
      "jquery": ["node_modules/jquery/dist/jquery"] // 이 매핑은 "baseUrl"에 상대적임.
    }
  }
}

여기서 'paths'는 'baseUrl'에 상대적으로 해석된다. 만약에 'baseUrl'을 '.'가 아니라 다른 디렉터리 값으로 설정하게 되면 이에 따라 매핑도 바뀌게 된다. 만약 이 예제에서 'baseUrl': './src'로 설정한다면, jquery는 '../node_modules/jquery/dist/jquery'로 매핑되어야 한다.

 

[실전] - baseUrl 설정하기

이전 수업에서 생성한 Next.js 프로젝트 내에서 진행한다. jsconfig.json 파일을 생성하고, 아래 코드를 입력한다.

{
    "compilerOptions": {
        "baseUrl": ".",
    },
}

그러면 모든 파일에서 다른 파일을 접근할 때 root(.)에서 절대적으로 접근할 수 있게 된다. pages 폴더 내에 하나하나가 모두 파일의 경로이므로, 이렇게 설정하게 되면 각 경로에 간편하게 접근할 수 있게 된다.

 

만약 프로젝트 구조가 다음과 같이 되어있다고 가정해보자.

root
   ㄴpages
      ㄴ1.js
      ㄴuser
         ㄴ2.js
   ㄴmain.js

만약 1.js와 2.js에서 main.js를 참조하고 싶다고 하자. 그럼 1.js에서는 ../../main.js 라고 작성하고, 2.js에서는 ../../../main.js 라고 작성해야 한다. 하지만 경로매핑을 이용하는 경우에는 두 파일 모두 동일하게 ./main.js라고 작성하면 된다.

또한 만약 1.js와 main.js에서 2.js 파일을 참조한다고 하자. 그럼 1.js에서는 ./user/2.js 라고 작성하고, main.js에서는 ./pages/user/2.js라고 작성한다. 경로매핑을 이용한다면 두 파일 모두 동일하게 ./pages/user/2.js라고 작성하면 된다.

이처럼 파일의 위치에 따라 달라지는 경로로 인해서 헷갈리는 경우가 많은데, 경로매핑 파일을 생성하게 되면 쉽고 깔끔하게 접근할 수 있다!

 

2.2 Next.js로 서버 만들기

<1>

pages/api 내에 오늘 날짜인 '20210629' 디렉터리를 생성하고, 그 안에 'helloworld.js' 파일을 생성하였다.

- pages/api/20210629/helloworld.js

export default (req, res) => {
    console.log(req);

    res.status(200).send('hello');
}

그리고 파일을 실행한다. 

$ npm dev run

▪ Postman 결과

웹 페이지 접속 결과 (Wifi 연결 및 이의 IPv4 주소에 접속): 172.30.1.20:3000/api/20210629/helloworld

172.30.1.20:3000/api/20210629/helloworld

 

<2>: 파라미터 req, res

Next.js는 서버를 만들기 위한 Node.js의 express 프레임워크가 내장되어 있다. python으로 치면 flask와 같은 개념으로 생각하면 된다. 위에서 작성한 코드를 다시 살펴보자.

export default (req, res) => {
    console.log(req);

    res.status(200).send('hello');
}

서버를 만드는 파라미터로는 req와 res가 있다. req는 request, res는 response다. 해당 코드는 res 즉 응답으로 'hello'라고 보내는 것이다. 또한 status로 성공적으로 응답했다는 의미로 숫자인 200번(=OK, success)를 보냈다. 이는 클라이언트와 서버간에 원활한 소통을 하기 위해 정한 규약이므로 외우자.

이렇게 작성하고 $ npm dev run 명령어를 입력하게 되면 내 컴퓨터에서 서버를 실행한다. 해당 도메인(172.30.1.20:3000/api/20210629/helloworld)으로 접속하는 것 자체가 req 요청을 보내는 것이므로, req 요청을 받고 res 응답을 보냄으로 웹 페이지에 'hello' 글자가 작성된다. 추가적인 설명으로, req 요청의 종류로는 GET, POST, PUT, DELETE가 있다.

또한 현재 코드에서 console.log(req)를 작성하였으므로 서버 터미널에서 request 패킷을 콘솔을 통해 볼 수 있다. (기므로 생략한다)

 

<3>: ip address

위에서 Wifi 연결을 했을 때 IPv4 주소로 웹 페이지에 접속하였다. 내 ip 주소는 어떻게 알 수 있을까?

cmd에서 ipconfig를 입력하자. 그럼 ip 주소를 알 수 있다.

ip address는 public ip address와 private ip address로 나뉘어 진다.

- ip address
    ㄴ public ip
    ㄴ private ip 

▪ public ip address

먼저 public ip부터 알아보자. http://ipconfig.co.kr/ 해당 사이트에 접속하면 현재 컴퓨터가 접속하고 있는 public ip를 알 수 있다.

현재 내 컴퓨터의 public ip 주소는 220.122.176.180 이다. 현재 Wifi와 같이 공유기로 연결되어 있으므로, 동일한 공유기로 연결한 사람들은 모두 나와 같은 public ip 주소를 가진다.

▪ private ip address

이전에 cmd에서 ipconfig 명령어를 작성하였을 때 나온 ip address가 바로 private ip 주소이다. 

이는 물론 컴퓨터마다 다른, 각자가 고유한 값을 가진다. 현재 나의 private ip 주소는 172.30.1.20이다. 

 

<4>

코드를 다음과 같이 입력해보자.

export default (req, res) => {
  // console.log(req);
  const ip = req.headers['x-forwarded-for'] || req.socket.remoteAddress;
  res.status(200).json({
    owner: '허다은',
    yourIP: ip,
  })
};

그러면 웹 페이지는 json 데이터를 전달받는다. 내 웹 페이지에 접속해보자.

다른 이의 로컬 서버로도 접속할 수 있다. 

 

 

 

3. React.js

위와 동일한 환경에서 pages/study/20210629/start.js 를 생성하고 시작하였다. 이후로는 React의 이론에 대해 스터디하였다.

 

3.1 React.js 란?

React.js란 Facebook에서 만든 자바스크립트 프론트엔드 라이브러리이다. UI를 만들기 위한 목적을 가지고 만들어졌다.

 

3.2 JSX

React.js는 자바스크립트 안에 HTML syntax를 쉽고 간편하게 작성할 수 있도록 도와주는 JSX가 있다. JSX는 HTML과 동일하게 작성한다.

위의 코드를 보시다시피, JSX는 엄청나게 직관적이다. 그리고 JSX는 optional일 뿐, not required이다.

 

3.3 Getting Started: MAIN CONCEPTS

1) Helloworld

codepen을 통해 코드를 실행해보았다.

ReactDOM.render(
  <h1>Hello, world!</h1>,
  document.getElementById('root')
);

HTML을 추가하려면 다음과 같은 구조로 작성한다.

ReactDOM.render( HTMLcode, HTMLelement);

 

 

2) Introducing JSX

이건 String도, HTML도 아닌 게 참 재밌게 생겼다. 이게 바로 JSX다! JSX는 하나의 표현식일 뿐이다.

이전에도 말했듯이 JSX는 엄청나게 직관적이다.

위에서 작성한 hello, world 코드에서, 다음과 같이 중괄호를 사용하여 변수를 넣어 동작하게 할 수도 있다.

또한 string을 return하는 함수를 사용하여 나타내면 더 직관적으로 보이게 할 수 있다.

▪ JSX syntax를 사용하는 조건

JSX를 사용하여 변수를 작성하는 경우에는 CamelCase로 작성해야 한다.

▪ JSX Represents Object

아래의 두 예시는 동일한 코드이다.

React는 Babel에서 compile하여 위의 코드를 아래 코드로 만들어준다. Babel은 React의 서버 사이드 렌더링 프레임워크인 Next.js에서 자동적으로 세팅되어 있기 때문에, 따로 다운로드하거나 신경써줄 필요가 없다.

 

 

3) Rendering Element

 

Elements are the smallest building blocks of React apps

 

React.js에서 가장 작은 단위의 block을 Elements 라고 부른다.

▪ Updating the Rendered Element

React.js의 elements는 값이 변하지 않는다는 특성을 가지고 있다. 즉, 한 번 렌더링 된 상태에서 다시 값을 바꿀 순 없다.

해당 예제는 1초 간격으로 계속하여 tick() 함수를 재렌더링하는 코드이다. element 값은 수정할 수 없으므로 tick() 함수를 새로 렌더링하여 페이지를 그린다.

▪ Virtrual DOM

자바스크립트에서는 계속하여 repainting, 즉 rendering을 하여 페이지를 처음부터 끝까지 다시 그려야했다. 이러한 단점을 보완하기 위해 React에서는 Virtual DOM이 있다. 

Virtual DOM은 이전의 DOM와 현재의 DOM을 비교하여 다른 부분만을 다시 그려준다. 그러므로 자바스크립트에 비해서 repainting이 덜하기 때문에 메모리를 아낄 수 있어서 훨씬 빠르게 클라이언트에게 페이지를 띄워줄 수 있다. 개이득!

React vs Ajax

React.js의 Virtual DOM 기능을 살펴보았는데, 그럼 이 부분과 Ajax(Asynchronous javascript xml)의 다른 점은 무엇이냐?

React.js는 Ajax처럼 단순히 요청을 보내는 게 아니라, DOM을 어떻게 최적화시키고 작동시키게 만들지 결정하는, 일종의 client library이다. React.js와 내부적으로 비슷한 라인으로는 Regular.js나 Vue.js도 있지만, 현재로서 점유율이 가장 높은 건 React.js이다.

 

 

4) Components and Props(="properties")

React.js에서 Component를 정의하는 방법은 두 가지가 있다.

  1. Function components
  2. Class components

1. Function

자바스크립트의 함수로 component를 만드는 게 가장 쉽고 간단한 방법이다.

2. Class

ES6에서 새로 추가된 class 개념을 사용하는 방법이다.

 

▪ Rendering a Component

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

const element = <Welcome name="Sara" />;
ReactDOM.render(element, document.getElementById('root'));
  1. ReactDOM.render()에서 '<Welcome name="Sara" />'로 지정된 element를 부른다.
  2. React는 props로 {name: 'Sara'}를 보내면서 'Welcome' component를 부른다.
  3. 'Welcome' component<h1>Hello, Sara</h1> element를 반환한다.
  4. React DOM은 <h1>hello, Sara</h1>로 DOM을 매칭하여 효율적으로 업데이트한다.

 

 ❗ component 명은 항상 대문자로 시작해야 한다.

➡ <div /> 는 HTML div 태그를 나타낸다. 하지만 <Welcome />은 component를 나타내므로, 코드 범위 내에 'Welcome'이 있어야 한다.

 

▪ 예제 살펴보기: Props 이해하기

props가 어떤 형태로 되어있는지 확인하기 위해서 JSON.stingify(props)를 작성하였다. JSON.stringify 메서드를 통해서 object 타입인 props를 문자열로 확인할 수 있다.

확인 결과, props는 {"name":"Sara"}이다. 그래서 앞의 예제에서는 {props.name}을 작성하여 'Sara' 문자열을 가져왔다.

props인 name은 <Welcome />을 작성할 때 선언한다.

이를 확인하기 위해 <Welcome />을 작성할 때 선언하는 props 값을 추가해보았다. 그 결과 추가한 props 값이 함께 출력된다. props는 초기에 'Welcome' component가 생성될 때 받아오는 값이다.

받아온 props의 값만 출력한 모습이다.

'Welcome' component를 생성할 때, 다른 props 값을 준 element를 ReactDOM에서 렌더링한 모습이다.

즉, props는 component가 생성될 때 고정된 자체 값이 아니라, 전달받는 값이다.

 

  component & props & element 이해하기 

 

▪ Extracting Components

다음 예제를 통해 component의 장점을 이해하자.

인스타의 댓글이나 블로그 댓글을 등록한다고 생각해보자. 만약 component & props가 없었더라면 일일이 댓글의 구성요소를 작성해야 할 것이다. 하지만 component를 함수로 정의하여 다음과 같이 사용하게 되면 이 문제점을 해결할 수 있다. 어느 한 값이 변경하고 싶을 때, component값을 한 번만 변경하면 이후로 모든 댓글인 elements를 바꿀 수 있기 때문이다. 따라서 component는 유지보수 점에서 아주 훌륭하다.

 component를 어떻게 나누냐가 중요한 요소이므로, 앞으로 현역에서도 component를 어떻게 나누어야 재활용하기에 좋고 생산성이 좋을지 계속 고민하게 될 것이다.

 

▪ Props are Read-Only

함수 혹은 class로서 정의를 마친 component는 이후로 절대 이의 props 값을 변경할 수 없다.  말그대로 "Props are Read-Only"인 셈이다. 다음 sum 함수 예제를 살펴보자.

이러한 함수들을 "pure"하다고 한다. "pure"한 함수는 다음 특성을 가진다.

  • input값은 변경되지 않는다.
  • 같은 input값을 넣으면 항상 같은 output값이 나온다.

반대로, 다음과 같은 함수는 "impure"하다고 한다.

  • input값이 변한다.
  • 같은 input값을 넣었을 때 항상 같은 ouput값이 나오지 않는다.

React.js는 다음과 같은 엄격한 규칙을 가지고 있다.

All React components must act like pure functions with respect to their props.

모든 React의 components는 props와 관련하여 "pure"한 함수로 작동해야만 한다.

물론, 애플리케이션의 UI들은 역동적이고 시간에 따라 변화한다. 이와 관련하여 다음 섹션에서 'state'라는 새로운 개념에 대해 배우게 된다. state를 사용하면, React의 components가 위의 엄격한 규칙을 어기지 않으면서도 시간이 지남에 따라 output값을 변경할 수 있게 된다.

 

 

5) State and Lifecycle

🍪 State

상태. 이전에 살펴본 props는 데이터를 받아오는 값이며, 수정이 불가능한 Read-Only 데이터이므로 '상태'라고 보기엔 어렵다.

state에는 props와 달리 시간이 지남에따라 변경될 수 있는 component와 관련된 데이터가 담긴다. state는 사용자가 정의하며, 일반 자바스크립트 객체의 형태여야만 한다. 또한 setState()를 호출하면 만들었던 mutation을 변경할 수 있으므로 this.state를 직접 변형해선 안된다. this.state를 변경 불가능한 것처럼 다뤄야 한다.

만약 타이머 ID와 같이 렌더링 혹은 데이터 흐름에 사용되지 않는 값일 경우에는 상태에 넣을 필요가 없다. 그런 값들은 component 인스턴스의 필드로 정의할 수 있다. 

▪ state와 props의 차이점

props와 state는 둘다 일반 자바스크립트 객체이다. 두 객체 모두 렌더링 결과물에 영향을 주는 정보를 가지고 있는데, 한 가지 중요한 방식에서 차이가 있다. props는 함수의 매개변수처럼 component에 전달되는 반면에, state는 함수 내에 선언된 변수처럼 component 안에서 관리된다. => stat는 외부에서 접근이 안되는 자기 자신의 상태를 나타내는 값이다.

(+) 더 알아보기: state

 

컴포넌트 State – React

A JavaScript library for building user interfaces

ko.reactjs.org

(+) 더 알아보기: state vs props

 

Lucy Bain

Blog posts about programming, mostly JS and frontend, but a few other topics as well.

lucybain.com

 

🍪 LifeCycle

생애 주기. 렌더링 과정 중에서 ...

 

▪ 예제를 통해 살펴보기

아래 예제는 이전에 살펴본 ticking clock 코드(A)이다. ( 3) Rendering Elements ) 

(A)

ReactDOM.render() 를 호출하여 이미 React의 DOM에 렌더링된 output인 element 값을 변경한다.

이제 clock component를 재사용할 수 있고 캡슐화하는 방법을 알아보자. 한 번의 코드 작성으로 Clock이 스스로 업데이트하도록 말이다. 아래 코드(B)를 살펴보자.

(B)

코드(A)와 코드(B)의 결과값은 같다. 하지만 코드(B)는 1초마다 props값을 넘겨받는데, Clock()이 타이머를 설정하고 매초마다 UI를 업데이트하는 기능이 Clock의 구현 세부 사항에 속해야만 한다.

Clock component에 state를 추가하기 위한 사전 준비

이를 수행하기 위해서 Clock component에 "state"를 추가해야 한다. state는 props와 비슷하지만, props에 비해 state는 private하며 오로지 component 내에서만 제어할 수 있으므로 외부에서 접근이 어렵다.

 

▪ Converting a Function to a Class

State와 LifeCycle을 사용하려면 무조건 componentclass로 만들어야만 한다. 그게 function으로 만드는 것보다 훨씬 더 메모리 용량을 적게 차지한다고 한다. 우선 위의 코드(A) 예제를 Class로 바꾸어보자.

  1. extends React.Component를 붙이고 이전과 같은 이름으로 Class를 생성한다.
  2. render()를 호출한다.
  3. render() 메서드 안으로 함수의 body 내용을 옮긴다.
  4. render() 메서드 안에 있는 props를 this.props로 변경한다. (props ➡ this.props)
  5. 선언했던 빈 함수를 지운다.

예제 코드(A)를 component를 Class로 나타낸 코드.

이제 Clock을 class로 만드는 것을 완료하였다. 

render() 메서드는 업데이트가 발생할 때마다 호출되지만, <Clock />가 동일한 DOM에서 렌더링된다면 Clock class 하나의 인스턴스만 사용하는 셈이 된다. 따라서 로컬의 state와 lifecycle 메서드와 같은 추가 기능을 이용하면 된다.

 

▪ Adding Local State to a Class

component를 class로 생성하였으니, 이제 date인 props를 state로 변경해보자. 총 세 단계를 거친다.

1. render() 메서드 내에 있는 this.props.datethis.state.date로 변경한다.

2. 초기에 this.state를 지정하기 위해 class constructor를 추가한다.

constructor에 props를 전달하기 위해선 다음과 같이 작성해야만 한다.

Class components는 항상 propsconstructor를 호출해야만 한다.

(+) 더 알아보기: React.js super(props)를 사용하는 이유"this"를 사용하기 위해!

 

[React] super(props) 를 써야하는 이유

이 글은 Dan Abramov의 Why Do We Write super(props)? 글을 충분한 의역으로 번역한 것입니다. 번역이 일부 자연스럽지 않은 부분이 있을 수도 있습니다. 정확한 내용은 원문을 참고하기 바랍니다 최근 Hooks

min9nim.github.io

3. <Clock />의 element에서 date prop를 삭제한다.

그리고 나중에 component에 타이머 코드를 추가할 것이다.

- 결과

결과 코드

 

▪ Adding Lifecycle Methods to a Class

이제 Clock이 스스로 타이머를 설정하고 매초마다 스스로 업데이트되도록 만들어보자.

여러 components가 있는 애플리케이션에서, components가 사라질 때마다 해당 component가 사용하고 있던 resources를 확보하는 것이 엄청 중요하다. 이를 위해서 component가 처음 실행될 때에만 실행되는 함수와, 만들어진 DOM이 삭제될 때마다 실행되는 함수가 있다.

우선 mount와 render 개념부터 체크하고 넘어가자.

 ❗ mount: component가 생성되고 DOM에 주입되는 것을 의미하며, 처음에 단 한 번만 실행된다.

 ❗ render: DOM에 그려주는 작업으로, props나 state값이 변할 때마다 이 작업을 수행한다.

 

  • 우리는 Clock이 처음으로 DOM에 렌더링 될 때만 타이머를 설정하려고 한다. 이를 React에서 'mounting'이라고 한다.
  • 또한 Clock에 의해 만들어진 DOM이 제거될 때마다, 해당 타이머를 해제하고 싶다. 이를 React에서 'unmounting'이라고 한다.

Class component가 mount 혹은 unmount할 때 일부 코드를 실행하도록 하는 특수 메서드를 component 내에 선언할 수 있다. 바로 componentDidMount()componentWillUnmount() 이다.

이 두 메서드들을 "LifeCycle methods"라고 한다.

 

(+) 참고

컴포넌트 생성
constructor ➡ componentWillMount ➡ render ➡ componentDidMount

컴포넌트 제거
componentWillUnMount

props값 변경
componentWillReceiveProps ➡ shouldComponentUpdate ➡ componentWillUpdate ➡ render ➡ componentDidUpdate

state값 변경
shouldComponentUpdate ➡ componentWillUpdate ➡ render ➡ componentDidUpdate

 

 ❗ Component의 LifeCycle 순서 

component 인스턴스가 생성되어 DOM에 추가될 때 다음 순서대로 호출된다.

[ constructor() 최초 1번 ➡ render() ]➡ [ componentDidMount() ➡ ... ] ➡ componentWillUnmount() 

( ➕ componentDidMount()에서 props나 state값이 변하면 render()가 실행된다. 만약 componentDidMount()가 현재 살펴보고 있는 예제처럼 타이머 기능을 가지고 있다면 계속하여 componentDidMount() ➡ render() 메서드가 반복적으로 실행된다.)

 

componentDidMount() 메서드는 component의 output값이 DOM에 렌더링 된 후에 실행된다. 이는 타이머를 세팅하기에 좋은 곳이다.

여기서 타이머의 ID (=this.timerID)를 저장하는 방법을 유의하여 살펴보자.

 

이제 DOM이 제거되었을 때, componentWillUnmount() 메서드를 사용하여 LifeCycle 내에 있는 타이머를 삭제하도록 하자. 

 

그리고 마지막으로 Clock component가 매초마다 작동되는 tick() 메서드를 구현하자. 이때 Clock component내에서 선언한 state값을 변경해야 하므로 this.setState() 메서드를 사용해야 한다.

이제 <한 번의 코드 작성으로 Clock이 스스로 업데이트하기> 목표를 달성하였다! class component와 state를 사용한 코드의 시계는 매초 째깍거린다.

과정을 다시 한 번 순서대로 살펴보자.

ReactDOM.render()에서 <Clock />를 읽는다.

➡ Clock component의 constructor를 호출한다.

this.state값을 현재 시각 값으로 초기화한다. (Clock이 현재 시각을 표시해야 하기 때문)

➡ Clock component의 render() 메서드를 호출하여 화면에 표시해야 할 내용을 알게 된다.

➡ Clock의 렌더링 출력값으로 DOM을 업데이트한다.

➡ Clock 출력값이 DOM에 삽입된다.

componentDidMount() 메서드를 호출한다.

➡ Clock component가 매초마다 tick() 메서드를 호출하기 위한 타이머를 설정하도록 브라우저에 요청한다.

➡ 매초 브라우저가 tick() 메서드를 호출한다.

➡ Clock component가 setState()으로 현재 시각을 포함하는 객체를 호출한다.

➡ state가 변경되었기 때문에 화면에 표시될 내용을 알기 위해 render() 메서드를 호출한다. 이때 render() 메서드 내의 this.state.date가 달라지고, 렌더링 출력값은 업데이트된 시각이다. 이렇게 DOM을 업데이트한다.

➡ Clock component가 DOM에서 삭제되면 componentWillUnmount() 메서드를 호출하여 타이머를 멈춘다.

 

▪ Using State Correctly

1. state값을 directly로 변경해선 안된다. 무조건 setState() 메서드를 사용하여 변경해야 한다.

2. state는 비동기적으로 업데이트가 될 수도 있다. 따라서 동기적으로 업데이트 되도록 콜백함수를 사용하여 작성하자.

객체 형태로 state 변경하기

this.props와 this.state 값이 비동기적으로 업데이트될 수 있으므로, 두 값이 다른 step의 값을 가질 수도 있다. 따라서 객체형태로 작성하면 Wrong!

인자를 사용하여 state 변경하기 (화살표 함수 사용)
위 코드와 동일한 코드임

동기적으로 처리할 수 있도록 콜백함수 형태로 작성하자. 자바스크립트의 비동기 처리를 보완하여 동기 처리하도록 콜백함수를 사용한다고 앞에서 배웠었다.

3. state에 다양한 변수를 작성했을 때, 각 변수를 독립적으로 변경할 수 있다.

state에 다양한 변수를 작성할 수 있다. (posts와 comments)
별도의 setState() 메서드를 호출하여, 변수를 독립적으로 업데이트할 수 있다.

setState() 메서드는 콜백 함수가 실행된 후에 리렌더링된다. 따라서 위의 예제에서 posts를 변경하면 comments에 영향을 주지 않고 posts만 변경되고, comments를 변경하면 comments만 변경된다.

(+) setState() 비동기 참고하기

 

setState( ) 파헤치기

타이머를 만들며 알게된 setState( )

berkbach.com

 

 

4. Homework

Q1. React Tutorial: tic-tac-toe 게임 만들어오기

Q2. 왜 state를 directly로 바꾸면 안되는가? (왜 directly로 바꾸면 렌더링이 안되는가?)

       ➡ Hint: 자바스크립트의 특성 때문에

Q3. React.js의 Hooks는 왜 좋은가?

 

4.1 tic-tac-toe 게임 만들기

 

Tutorial: Intro to React – React

A JavaScript library for building user interfaces

reactjs.org

 

아래 페이지가 tic-tac-toe 게임을 이해하는데에 많은 도움이 되었다. 글이 쉽게 쓰여져서 슉슉 읽힌다.

 

React | 틱택토 게임 만들기 (1/2)

튜토리얼은 리액트 공식 문서를 참고했다.자세한 내용은 여기에서 찾을 수 있다.먼저 CRA로 간단하게 tic-tac-toe 폴더를 만들어주었다. 초기 세팅을 해두고 CSS툴은 공식 문서에서 제공하는 것을 가

velog.io

 

 

4.2 React에서 setState()를 사용하는 이유는?

class component에서만 state를 사용하고, 이 값을 변경하기 위해선 setState() 메서드를 사용해야만 한다. 하지만 왜 굳이 메서드를 사용해서만 값을 변경해야 할까?

1. 자바스크립트는 다시 렌더링이 되게 하려면 렌더링이 되도록 하는 함수나 코드를 작성해야만 한다. 반면에 React는 스스로 DOM에서 변경된 부분을 확인하고, 변경된 부분만 찾아내서 다시 렌더링(render())한다. 따라서 setState() 메서드를 사용하여 값을 변경하고 React 스스로가 자동으로 렌더링하도록 한다.

2. 

 

 

 

4.3 React에서 Hooks이란?

 

 

 

 

 

 

 


참고 자료

 

TypeScript 한글 문서

TypeScript 한글 번역 문서입니다

typescript-kr.github.io

 

baseurl과 관련된 모호한 것들 정리

jekyll 블로그를 github-page를 이용하여 구성할 때 baseurl과 관련된 문제를 겪게 되어서 baseurl에 대해 깔끔하게 정리된 글을 번역해 보았습니다.

kairos03.github.io

 

[React] 컴포넌트 생명주기

이번 시간에는 컴포넌트의 생명주기(lifecycle)에 대해서 알아보겠습니다. 현재 리액트 최신버전은 v16.8입니다. 여기에서 확인할 수 있습니다. v17 부터는 componentWillMount(), componentWillUpdate(), compo..

kosaf04pyh.tistory.com

 

컴포넌트 State – React

A JavaScript library for building user interfaces

ko.reactjs.org

 

javascript_react에서 setstate를 사용하는 이유

리액트를 공부하면서 class component에서 state를 사용하고 이 값을 변경하기 위해서 setState함수를 사용해야만 한다는 것을 배웠다. 하지만 왜 굳이 함수를 사용해서만 값을 변경해야하는지 생각해

velog.io

 

 

 

 

 

반응형