리액트 생명주기

 

리액트 컴포넌트는 생성(Mount), 갱신(Update), 제거(Unmount) 주기를 가지게됩니다.

해당 주기에서 사용되는 메소드에 대해 알아보겠습니다.

 

 

생성(Mount)

constructor(props)

메소드를 바인딩 하거나 state를 초기화하는 작업이 없을 경우 사용합니다.

만약, 해당 작업이 없다면 사용하지 않아도됩니다.

 

getDerivedStateFromProps(nextProps, prevState)

props로 받아 온 값을 state로 넣어주고 싶을때 사용합니다.

state를 변경할 때는 setState가 아닌 반환 값으로 변경해야하며 반환 값이 null일 경우에는 아무일도 발생되지 않습니다.

 

render()

반드시 구현되어야하는 유일한 메소드입니다.

이 메소드가 호출되면 this.props와 this.state의 값을 활용하여 값을 반환합니다.

render는 컴포넌트의 state를 변경하지 않고 호출될 때마다 동일한 결과를 반환합니다.

해당 메소드는 브라우저와 직접적으로 상호작용하지 않습니다.

 

componentDidMount(prevProps, prevState)

컴포넌트가 생성된 직후에 호출됩니다. (즉, render 후에 호출)

setState를 통해 작업하면 render가 두번 호출되므로 DOM 노드가 있어야하는 초기 작업에 사용하는 경우를 제외하고는 setState를 사용하지 않습니다. (= state의 초기화는 constructor에서 작업합니다.)

데이터 구독을 설정하기 좋은 위치이며 componentWillUnmount()에서 구독 해제 작업을 반드시 수행해야합니다. (timer, fetch, axios 등)

 

 

갱신(Update)

getDerivedStateFromProps(nextProps, prevState)

생성과 동일

 

shouldComponentUpdate(nextProps, nextState)

컴포넌트 업데이트 직전에 호출되는 메소드입니다.

props  state가 변경 되었을 때 리렌더링 여부를 반환 값으로 정합니다. 

*사용을 잘 안하는 이유

리액트 컴포넌트의 기본 동작은 매 state의 변화마다 다시 렌더링을 수행하는 것이기 때문에 잘 사용되지 않습니다.

해당 메소드는 성능 최적화를 목적으로 두고 있기 때문에 렌더링을 방지하는 목적으로 사용할 경우 버그로 이어질 수 있다. shouldComponentUpdate가 false를 반환하면 리렌더링이 일어나지 않으므로 그 다음 순서의 메소드들은 호출되지 않습니다.

 

render():

생성과 동일

 

getSnapshotBeforeUpdate(prevProps, prevState)

렌더링 결과가 실제 돔에 반영되기 직전에 호출됩니다.

메서드의 이름에서처럼 업데이트 되기 직전에 snapshot(props & states)을 확보하는게 목적입니다.

반환 값이 componentDidUpdate의 세번째 인자로 전달됩니다.

 

componentDidUpdate(prevProps, prevState, snapShot)

최초 렌더링에서는 호출되지 않으며 돔 요소가 업데이트 된 이후 호출되는 메소드입니다. 

getSnapshotBeforeUpdate를 구현했고 리턴 값이 존재한다면 세번째 인자로 넘겨받으며 반환값이 없다면 해당 인자는 undefined입니다.

setState를 사용할 수 있지만 조건문으로 감싸지 않는 경우 무한루프가 되는 경우가 발생할 수 있으므로 주의해야합니다. 이전과 현재의 props를 비교하여 네트워크 요청을 보내야할 경우 이 메서드를 사용합니다.

 

 

제거(UnMount)

componentWillUnmount()

컴포넌트가 DOM에서 삭제된 후 실행되는 메소드로 소멸단계에서 호출되는 유일한 메소드입니다.

componentDidMout에서 생성된 작업등을 정리할 때 사용합니다. (timer, fetch, axios 등)

실행 직후에는 이제 컴포넌트가 리렌더링 되지 않으므로 setState를 사용하면 안됩니다.

 

 

오류처리 (공식문서)

제어 흐름 조작하는데 사용하면 안되며 해당 메소드들은 자기 자신(컴포넌트)에 대한 오류를 감지할 수 없고 하위에 존재하는 컴포넌트에 대한 오류만을 감지할 수 있습니다.

 

getDerivedStateFromError(error)

에러가 발생한 뒤 UI 렌더링을 제어하기 위해 사용한다.

 

componentDidCatch(error, errorInfo)

에러 정보를 기록하려고 사용합니다.

*공식사이트에서 설명하길, 해당 메소드에서 setState를 통해 UI를 렌더링 할 수 있으나 추후 릴리즈에서 사용할 수 없게할 것이라고 적혀있습니다.

 

 


 

참고

자바스크립트는 단일 스레드입니다.

단일 스레드라는 것은 하나의 스택이라는 뜻으로 동시에 하나의 일만 가능하다는 것을 의미합니다.

 

하지만,

자바스크립트가 사용되는 환경을 보면 비동기 작업을 통해 여러개를 동시에 처리하고 있는것 같습니다. 

멀티 스레드라고 착각할 수도 있을 것 같은데,

어떻게? 이렇게 동작할 수 있는지를 알아보도록 하겠습니다.

 

 

자바스크립트 엔진

메모리 힙(Memory Heap)과 콜 스택(Call Stack)으로 이루어져 있습니다.

  • 메모리 힙
    • 구조화되지 않은 넓은 메모리 영역을 말한다.
    • 객체들이 할당된다
      • 프로그램에 선언한 변수, 함수 등
  • 콜 스택
    • 함수 호출은 프레임들의 스택을 형성
    • 먼저 들어온 것이 나중에 나가는 선입 후출

 

자바스크립트 엔진에는 설명하려는 이벤트 루프가 등장하지 않는데, 이유는 간단합니다.

비동기 작업에서 필요한 중요한 요소인 이벤트루프, 콜백 큐등은 자바스크립트를 구동시키는 환경(=브라우저, 노드)이 담당하고 있기 때문입니다.

 

 

브라우저 환경

출처: https://medium.com/front-end-weekly/javascript-event-loop-explained-4cd26af121d4

 

  • Web APIs
    • 브라우저에서 제공하는 API들, 웹 브라우저에 내장되어 있다
      • DOM, Ajax, Timeout 등..
      • 브라우저 및 주변 컴퓨터 환경의 데이터를 노출하고 이를 사용하여 유용한 복잡한 작업을 수행 할 수 있다
  • Callback Queue
    • 처리할 메시지 목록인 메시지 대기열
    • 먼저 들어온 것이 먼저 나가는 선입선출
      • Task Queue
        • ex: setTimeout
      • Micro Task Queue (= Job Queue) 
        • ex: Promise의 .then()
      • Animation Frames
        • ex: requestAnimationFrame API
  • Event Loop
    • 콜 스택과 콜백 큐를 감시한다
    • 콜 스택이 비어있으면 콜백 큐에서 태스크를 가지고 와서 콜 스택에 추가하는 행동을 한다

+ Event Table: 특정 이벤트가 발생했을때 어떤 콜백함수가 호출되어야하는지 알고 있는 자료구조

 

 

크롬 기준

Micro Task Queue > Animation Frames > Task Queue 순으로 실행됩니다.

그 외에 Queue들도 설명하는 블로그 글도 있기는 하나 정확한 정보는 못 찾았다고 합니다.

도움이 되는 글이라 생각하니 방문해서 읽어보세요~

velog.io/@thms200/Event-Loop-%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EB%A3%A8%ED%94%84#animation-frames

 

Event Loop (이벤트 루프)

이번 글은 Event Loop (이벤트 루프) 에 대해 정리해보려고 한다. Event Loop? Event Loop 출처 How JavaScript works: an overview of the engine, the runtime, and the call stack Event Loop는 MDN 문서로 검색하면 "큐의 다음 메시

velog.io

 

여튼 동작을 예로 들면.. 

ES6의 Promise의 then이 Micro Task Queue로 들어가며 setTimeout 함수는 Task Queue로 들어간다.

이때 Task Queue 대기열에 Task가 있어도 Micro Task Queue가 먼저 이벤트 루프에 의해 콜 스택으로 이동된다.

 

 

Micro Task Queue와 Job Queue는 같은 것 일까?

공부하던 중에 논란이 있음을 인지했고 찾아본 두 블로그 글을 가져와봅니다.

정확한 설명은 링크를 통해 들어가서 확인해보세요^^

 

ECMA에선 PromiseJobs라는 내부 큐(internal queue)를 명시합니다.

V8 엔진에선 이를 '마이크로태스크 큐(microtask queue)'라고 부르기 때문에 이 용어가 좀 더 선호되고 있습니다.

- ko.javascript.info/microtask-queue

 

브라우저마다 프라미스의 호출 순서가 다른 문제를 지적했다.

프라미스가 ECMAScript에 정의되어 있는 반면에 마이크로 태스크는 HTML 스펙이 정의되어 있는데,

둘의 연관관계가 명확하지 않기 때문이다.

ES6부터 프라미스를 위해 잡 큐(Job Queue)라는 항목이 추가되었지만, HTML 스펙의 마이크로 태크스와는 별도의 개념이다.

프라미스A+ 스펙문서의 Note를 보면 구현 시에 일반(macro) 태스크나 마이크로 태스크 둘 다 사용할 수 있다고 적혀 있다.

실제로 프라미스가 처음 자바스크립트에 도입되는 시점에는 프라미스를 어떤 순서로 실행할 것인가에 대한 논의가 꽤 있었던 것으로 보인다.

하지만 앞서 언급한 것처럼 현재는 프라미스를 마이크로 태스크라고 정의해도 무리가 없을 것 같다.

- meetup.toast.com/posts/89

 

 


참고

ko.javascript.info/microtask-queue

meetup.toast.com/posts/89

 

프로그래밍의 관점을 갖게하고 결정하는 역할인 프로그램의 패러다임에 대해 알아보겠습니다.

발전하게 된 순서는 '절차적 -> 객체지향 -> 함수형'으로 단점들을 극복을 위해 나왔다고 합니다.

 

 

프로그래밍 패러다임

명령형 프로그래밍(How): 알고리즘을 명시하고 목표는 명시하지 않는다

  • 프로그램의 상태와 상태 변경을 시키는 '구문'의 관점에서 연산을 설명하는 방식
    • 절차적 프로그래밍: 수행되어야 할 연속적인 계산 과정을 포함하는 방식
    • 객체지향 프로그래밍: 객체들의 집합으로 프로그램의 상호작용을 표현
  • 선언형 프로그래밍(What): 알고리즘을 명시 하지않고 목표만 명시한다
    • 어떤 방식(How)가 아닌 무엇(What)과 같은지를 설명하는 방식
      • 함수형 프로그래밍: 순수함수를 보조함수와 조합하는 방식

 

 

명령형 프로그래밍

절차적 프로그래밍 (위키백과)

실행 절차에 중점을 둔 프로그래밍 방식으로 순차적인 처리방식으로 프로그램 전체가 유기적인 연결이 있다. 

순차적인 처리방식은 컴퓨터의 동작 방식과 같아서 처리 시간이 빠르다고 한다.

 

특징

  1. 하나의 큰 기능을 처리하기 위해 작은 단위의 기능들로 나누어 처리하는 Top-Down 방식
  2. 비교적 작은 규모의 작업을 수행하는 함수 생성
  3. 인수, 반환 값으로 명령을 전달하고 수행
  4. 데이터와 함수를 별개 취급
  5. 특정 기능을 수행하려면 해당 메소드를 직접 호출

 

장단점

장점

  • 개인 프로젝트에 적합
  • 객체 지향에 비해 빠르다

단점

  • 대형 프로젝트에 부적합
  • 유지보수가 어렵다
  • 코드 순서가 중욯서 순서 변경 시 다른 결과 초래 가능
  • 분석과 디버깅이 어렵다

 

 

객체지향 프로그래밍 (위키백과, 관련포스팅)

기능별로 모듈화하여 하드웨어가 같은 기능을 중복하지 않게하고 모듈을 재활용하여 하드웨어의 처리량을 줄인다.

'객체'라는 기본 단위로 나누고 이들의 상호작용으로 서술하는 방식

클래스를 이용해 연관있는 처리부분과(함수) 데이터부분(변수)을 하나의 객체(인스턴스)로 묶어 생성, 사용, 작은 문제를 해결하는 객체를 생성해 큰문제를 해결하는 Bottom-Up 방식.

네가지 특징(추상화, 캡슐화, 다형성, 상속)을 지키며 코딩해야하며 이 조건을 지키지 않고 클래스 단위로 프로그래밍하는 것은 객체지향이 아닌, 클래스기반(캡슐화)을 사용하는 것이다.  

 

특징

1. 추상화

현실세계 대상을 관찰하여 핵심적인 특징(속성과 행위)을 뽑아내는 과정이다.

이때 관련있는 것들을 묶게되면 캡슐화가 되고 묶은 개념은 추상화가 되고 주체는 클래스가 된다.

'객체'는 클래스로 부터 실체화 된것으로 눈에 보이며 실체한다.

'클래스'는 추상적이기에 눈에 보이지 않고 개념적으로만 존재한다.

 

2. 캡슐화

속성과 행위를 관련있는 것끼리 묶는다.

여기서 중요한 것은 접근이 필요한 부분을 제외하고 구체적인 로직은 내부로 숨긴다. (=은닉성)

구체적인 로직을 내부로 은닉하는 목적

  • 클래스 내부 구현의 '응집도'를 증가
  • 외부 다른 클래스와의 '결합도'를 감소
    • 이때 일반적인 객체지향언어는 '접근제한자'를 지원한다. (public, private, protected)

 

3. 상속

대상이 되는 클래스의 모든 특징을 물려받는 것, 이때 자식 클래스로 부터 부모 클래스가 대체되어도 의미가 성립되어야한다.

계층형 구조

  • 부모 클래스와 자식클래스는 '상속관계'
  • 관계가 아래로 내려갈수록 '구체화된다'라고 말한다. (=> 고유 특징이 증가)
  • 관계가 위로 올라올수록 '일반화된다'고 말한다. (=> 더 많은 객체에 영향을 준다)

 

장단점

장점

  • 부모 클래스로 부터 물려 받은 특징으로 인해 같은 내용을 다시 구현할 필요가 없어 '코드의 재사용성'이 향상된다.

단점

  • 재 사용성만 고려하여 상속한다면 혼란이 생긴다.
  • 상속은 '다형성'을 구현하기 위해 사용할 것을 권장한다.
    • 좋은 상속관계는 is-a 관계 (~은 ~이다) : 바나나는 과일이다 / 자동차는 바퀴가 있는 탈 것이다
    • 혼란을 줄 수 있는 상속관계는 has-a 관계 : 사람-팔 / 자동차-바퀴 / 새-날개

 

4. 다형성

하나의 속성이나 행위가 상황에 따라 다른 의미로도 해석될 수 있는 특성으로 오버로딩, 오버라이딩을 통해 다형성을 구현 할 수 있다.

  • 오버로딩
    • 매개 변수에 따라 여러 종류의 타입을 받아 같은 기능으로 하도록 하기 위한 작업
    • 자바스크립트는 자유로운 언어이므로 기본 제공하지는 않는다
    • 함수는 변수로 취급하며 모든 변수는 전역 객체로 취급하기 때문에 같은 이름이라면 하나만 취급
    • 따라서 타입체크해서 기능을 구현하도록 함수를 만들 수는 있다
  • 오버라이딩
    • 상위 클래스의 메서드를 하위 클래스에서 재 정의하는 것(상속)

 

 

절차적 프로그래밍과 객체지향 프로그래밍 차이

두 방식이 아예 반대개념이라고 할 수는 없다.

둘다 명령형 프로그램의 하위 개념이기에 공유하는 것이 많다.

그리고 절차적이지 않은 프로그램은 없기 때문이다.

다만

  • 절차적 프로그래밍
    • 프로그램의 순서와 흐름을 먼저 세우고 필요한 자료구조와 함수를 설계
    • (=데이터 중심으로 절차적 실행에 초점)
  • 객체지향 프로그래밍
    • 반대로 자료구조와 함수를 먼저 설계하고 그 후 실행순서와 흐름을 설계
    • (=객체간의 관계에 초점)

 

선언현 프로그래밍

함수형 프로그래밍 (위키백과)

순수함수를 보조함수와 조합하고 소프트웨어를 만드는 방식

로직내에 복잡성을 해결하고 변수사용을 억제하여 상태변경을 피하려는 프로그래밍 패러다임

 

특징

1. 일급객체

사용할때 다른 요소와 아무런 차별이 없는 객체 (자바스크립트 함수는 객체, 일급함수)

  1. 변수나 데이터 구조 안에 담을 수 있다
  2. 파라미터로 전달 할 수 있다
  3. 반환값(return value)로 사용할 수 있다
  4. 할당에 사용한 이름과 관계없이 고유한 구별이 가능하다
  5. 동적으로 프로퍼티 할당이 가능하다
  6. 비교연산이 가능하다

 

2. 고차함수

람다 계산법에서 만들어진 용어로 함수는 함수를 파라미터로 전달할 수 있어야하며 함수의 반환값으로 함수를 사용할 수 있습니다. (일급 객체의 부분집합)

(React의 고차컴포넌트는 컴포넌트를 이용하여 위의 조건을 만족하는 컴포넌트를 말한다)

 

3. 불변성

변하지 않는 성질을 말한다.

자바스크립트는 자유로운 언어로 데이터의 변경이 언제든 가능하나 안되는 언어들이 존재한다.

불변성을 지키기 위해서는 데이터 변경이 필요할 경우 원본을 유지한 채 복사본을 만들어 작업해야한다.

 

4. 순수함수

동일한 입력에는 항상 같은 값을 반환해야한다.

함수의 실행은 프로그램의 실행에 영향을 미치지말아야한다. (Side Effect가 없어야함)

함수 내부에서 인자값의 변경이나 프로그램의 상태를 변경하면 안된다.

 

5. 합성함수

새로운 함수를 만들거나 계산하기 위해서는 둘 이상의 함수를 조합하는 과정을 말한다.

함수형 프로그래밍은 작은 여러개의 함수들로 이루어져 있기에 이러한 함수들을 연쇄적으로 또는 병렬로 호출해서 더 큰 함수를 만드는 과정으로 전체 프로그래밍을 구축한다.

 

 

명령형 프로그래밍과 함수형 프로그래밍 비교

 

명령형 프로그래밍

함수형 프로그래밍

프로그램이란

프로그램은 명령의 수행이다

프로그램은 함수의 계산이다

중점적 시각

어떻게?

무엇?

 

 

객체지향 프로그래밍과 함수형 프로그래밍의 차이

함수형 프로그래밍과 객체지향 프로그래밍은 약간의 차이가 있다.

  • 객체지향: 관리하는 모듈함수에 의한 재사용성에 관심을 가지고 있으며 클래스(또는객체,Object)가 일급객체
    • 클래스와 객체들의 관계를 중심으로 코드 작성
    • 상태, 멤버변수, 메서드 간의 긴밀한 관계
    • 멤버변수의 상태에 따라 결과가 달라짐
  • 함수형: 순수함수와 일급객체에 관심을 가지고 있으며 함수(Function)자체가 일급객체
    • 값의 연산 및 결과 도출 중심으로 코드 작성
    • 함수 내부로 넘겨받은 인자 값을 별도로 저장하지 않으며 간결한 과정으로 처리하고 매핑하는데 주 목적입니다.

 

 

 

 

위키백과에서 먼저 정의를 살펴보았습니다.

 

 

"라이브러리는 주로 소프트웨어를 개발할 때 컴퓨터 프로그램이 사용하는 비휘발성 자원의 모임이다.

여기에는 구성 데이터, 문서, 도움말 자료, 메시지 틀, 미리 작성된 코드, 서브루틴, 클래스, 값, 자료형 사양을 포함할 수 있다."

 

"컴퓨터 프로그래밍에서, 소프트웨어 프레임워크는 복잡한 문제를 해결하거나 서술하는 데 사용되는 기본 개념 구조이다.

간단히 뼈대, 골조, 프레임워크라고도 한다."

 

글만 간단히 보아도 두 개념이 많이 다른 것을 알 수 있습니다.

라이브러리는 프레임워크에 비해 작은 개념입니다.

 

 

프론트개발을 할때 쉽게 접하는 것을 예로 들어보자면 jQuery, React 같은 것들이 라이브러리입니다.

엥? 왜 React가 라이브러리이지? 프레임워크 아니었어? 하는 사람이 있을 수도 있습니다.

과거의 저도 헷갈렸었는데, 정확히 리액트의 생태계는 프레임워크이지만 리액트만은 라이브러리라고 합니다.

 

프레임워크로 분류되기 위해서는 필수로 충족해야하는 것들이 있습니다. 

다른 많은 프레임워크들이 기본적으로 내장하고 있는 기능들말이죠.. (예를 들어 라우터 기능이라던가)

 

리액트에서 이러한 기능들을 구현하기 위해서는 여러가지 추가적인 라이브러리를 같이 사용해야합니다.

(react-router, react-redux, react-saga 등....) 

그렇기 때문에 React는 프레임워크로 분류되지 않고 라이브러리로 분류됩니다.

 

react 공식사이트 메인 캡쳐

 

 

물론 공식사이트에도 라이브러리로 소개되고 있습니다.^^

 

 

+ Recent posts