티스토리 뷰

반응형

Author: 니용

 

앞의 글에서 Hooks의 용어가 있다는 정도만 말씀드렸었고,

이번 글에서 그 Hooks가 대체 뭐길래 이렇게 강조를 하는 것인지 설명드리려고 합니다.

 

Hooks는 React 문법 중 하나입니다. 저는 문법이라는 것을 처음 알았을 때가 중학교 영어 수업시간이었습니다. 

문법이 무엇인지 모르고 영어 문제를 그저 단어 하나하나로 해석으로 푸는 것은 정말 어려웠습니다. 영어를 손절하려고 하였을 때 선생님이 처음 알려준 것은 단어가 아닌 형식이었고, 이것이 나중에는 문법이라는 것을 뒤늦게 깨달아 문법 공부를 시작하게 되었습니다. 

 

프로그래밍 언어도 영어와 마찬가지로 문법이 있습니다. 문법을 알고 React 코딩을 진행하는 것과 그러지 아니한 것은 큰 차이가 있습니다. 최초에 React가 나왔을 때에는 이 문법이 지원이 되지않아서 많은 개발자분들이 상당히 어려움을 겪었다고 합니다. (근데 저는 왜 지금도 어려울까요? ㅠㅠ)

 

이 문법이 나오고 난 이래로 디자인 패턴이라는 신기법이 나오기 시작하였고, 가장 React를 혁신적으로 사용할 수 있는 2013년에 React를 만들어낸 Facebook이 대히트를 치게 됩니다. 

 

Hook은 원래 낚시바늘을 의미합니다. 왜 이름을 이렇게 짓게 되었을까요? 

React는 컴포넌트 단위로 구성이 되어 있고, 각 컴포넌트 당 하나의 state를 가진다고 말씀드렸습니다.

이 state는 Threadready(준비), run(실행), wait(대기), pause(일시중지), end(종료)와 같이 각각의 상태를 나타내며, 

 

React Component도 이와 마찬가지로 특정 상태값을 가지고 있어 자신이 언제 호출이 되어야 하는지, 또 언제 상태를 변경해야 하는지 지정해주는 것입니다. 이러한 상태를 생명 주기(Life Cycle)이라고 합니다.

낚시바늘에 물고기를 낚듯이 상태가 변경되기 때문에 Hook이라는 이름이 붙었다고 합니다. (거참 억지스럽...)

 

Component를 한 번 아래에 소스화 해보려고 합니다. 

import React from "react";
class AbboList extends React.Component {
    constructor(props) {
       super(props);
       this.state = { abbos: [] }
    }


    render() {
        return (
            <ul>
                {this.state.abbos.map(({body, name}) =>
                    <li>{name} has {body}</li>
                )}
            </ul>
         );
    }
}

위와 같이 AbboList가 호출될 때 생성자(constructor)를 구현하였습니다. 

abbos라는 Arrays를 하나 호출하여 state 값에 넣는 것이죠.

여기서 state는 각 컴포넌트 하나 당 고유하므로 선언을 하지 않아도 선택자 this를 통하여 선택할 수 있는 변수입니다.

 

stateJSON Object이므로 어떠한 값을 가져도 좋습니다.

 

constructorc에서 주의해야 할 점은 아래와 같습니다.

 

1. 사용 목적이 없으면 작성하지 않는다.

2. 사용한다면, 반드시 super(props)를 호출하여 this.props를 정의해 주어야 버그가 나지 않는다.

3. 생성자 내에서 setState는 사용하지 않는다.

 

 

render는 기존에 사용했다시피 화면에 띄운 작업 결과물입니다.

하나의 Component는 반드시 가지고 있어야 하는 메서드이며, 없으면 에러가 납니다.

여기서 JSX 문법이 사용되게 되는데 JSX 문법은 다음 글에서 설명드리려고 합니다.

 

import React from "react";
class AbboList extends React.Component {
    constructor() {
       super();
       this.state = { abbos: [] }
    }


    componentDidMount() {
        fetch("/api/url/call")
            .then(res => res.json())
            .then(abbos => this.setState({ abbos }))
    }


    render() {
        return (
            <ul>
                {this.state.abbos.map(({body, name}) =>
                    <li>{name} has {body}</li>
                )}
            </ul>
         );
    }
}

이번에는 componentDidMount 함수를 작성하였습니다. 

이 함수는 해당 컴포넌트가 호출이 된 후 마운트(mount)가 된 후 호출되는 함수입니다.

mount는 생성자가 생성된 후 화면에 가상 DOM이 삽입되는데 실제로 DOM을 업데이트하는 과정을 의미합니다.

즉, 화면을 그리는 비동기 작업과정입니다.

 

보통 다음과 같은 경우에 주로 사용하게 됩니다.

 

1. Modal이나 Tooltip과 같이 사이즈나 위치를 확인하고 초기화를 해야 하는 경우

2. 외부의 데이터를 불러오거나 네트워크 요청을 보내는 경우

 

setState를 실행하는 경우 기존의 state 값에 네트워크("/api/url/call")를 통해 가져온 데이터를 넣어주게 됩니다. 

이 경우 화면이 2번 rendering이 진행되는데, 클라이언트는 이 경우 2번 실행되는 과정은 볼 수 없게 됩니다. 왜냐하면 이 로직은 생성자가 호출된 후 브라우저에 화면을 갱신하기 전 한 번만 실행되기 때문입니다. 

 

여기서 주의해야 할 점은, 이렇게 2번 렌더링이 진행되면 성능상으로 문제를 일으킬 수 있습니다. 

부득이하게 위의 경우에 사용이 안된다면 가급적 생성자(constructor)에서 세팅하는 것이 좋은 방법이라고 할 수 있겠습니다.

 

이외에도, shouldComponentUpdatecomponentWillUnmount 와 같은 함수도 존재합니다.

그 함수들은 아래에 정리하겠습니다.

함수 이름 호출 시점 사용시 주의사항
shouldComponentUpdate(nextProps, nextState) 현재 state, props의 변화가 있거나 새로운 값으로 갱신될 때 성능 최적화를 주 사용목적으로 사용하기 때문에 렌더링 방지 목적으로 사용하면 버그로 이어짐
componentWillUnmount 컴포넌트가 DOM 상에서 제거될 때  
componentDidUpdate(prevProps, prevState, snapshot) shouldComponentUpdate 갱신이 일어난 직후 네트워크 요청 후 props가 변하지 않았으면 보내지 않아도 됨
getDerivedStateFromProps(props, state) 최초 마운트 시, 갱신 시 모두에서 render 메서드를 호출하기 직전 1.컴포넌트 인스턴스에 접근 불가능
2.유일한 static method
getSnapshotBeforeUpdate(prevProps, prevState) 가장 마지막으로 렌더링된 결과가 DOM에 반영되었을 때 호출  
componentDidCatch(error, info) 로직 중 오류 처리(Exception 발생)시 호출 error는 발생한 오류, info는 어떤 컴포넌트가 오류를 발생시켰는지에 대한 정보

 

아래의 생명주기 함수들은 '레거시'로 분류되어 작동은 하지만 권장하지 않는 함수입니다. 참고하셔요.

함수 이름 호출 시점 사용시 주의사항
componentWillMount render 실행 전  
componentWillReceiveProps(nextProps) props 변화에 대응한 부수 효과 발생시  
componentWillUpdate(nextProps, nextState) 새로운 props 또는 state 전달시 this.setState 호출 불가
반응형

'Client' 카테고리의 다른 글

Thymeleaf Utility Objects (2)  (0) 2020.06.11
Thymeleaf Utility Objects (1)  (0) 2020.06.10
Thymeleaf 기본 문법  (0) 2020.06.09
[React.js] React를 제대로 활용하기 (3)  (0) 2020.03.22
[React.js] 간단한 시계 만들기 (2)  (0) 2020.03.22
[React.js] 간단한 시계 만들기 (1)  (0) 2020.03.18
댓글
공지사항