본문 바로가기
React

[React]함수형 컴포넌트 vs 클래스형 컴포넌트 비교(1)

by codnjs779 2021. 11. 10.

 몇년 전까지만 해도 리액트에서는 Class로 컴포넌트를 생성하는 방식을 사용해왔다. 하지만 내가 리액트 공부를 시작할때는 공식문서에서도 함수형컴포넌트를 사용하는 것을 권장하고 있었기 때문에 처음 배울 때 함수형으로 배웠다. 

 

 공부를 하다보면 구글링을 통해 해결방법을 찾아야 하는일이 많은데 아무래도 함수형이 쓰이게 된지 오래되지 않아서Class형으로 작성된 레퍼런스들이 많기때문에 클래스형 코드를 보고 함수형과 어떤 부분이 차이가 있는지 알아보고자 공부했다. 

 

아래의 코드는 간단한 구구단게임 예제를 만드는 코드이다.

 


1. 클래스형 컴포넌트  

: class component 선언 + render(사용자 화면에 보이는 부분) 으로 나눠서 작성해줘야한다. 

이런 형식의 틀을 만들것! 

 <script type="text/babel">
            const e = React.createElement;
            class GuGuDan extends React.Component {
                constructor(props) {
                    super(props);
                    this.state = {
                        first: Math.ceil(Math.random() * 9),
                        second: Math.ceil(Math.random() * 9),
                        value: "",
                        result: "",
                    };
                }

 class 안쪽에 state를 생성해준다. state 내부에는 기본값으로 설정해주고 싶은 값을 넣어주면 된다. 

위 그림에 number 곱하기 number? 부분이 state안쪽에 기본값으로 설정해 준 부분이다. js math random 함수를 사용해서 1 ~9까지의 숫자가 랜덤으로 출력 될 수있게 했다.

 

 

   render() {
                    console.log("렌더링");
                    return (
                        <>
                            <div>
                                {this.state.first} 곱하기 {this.state.second}는?
                            </div>
                            <form onSubmit={this.onSubmit}>
                                <input
                                    ref={(e) => {
                                        this.onRef;
                                    }}
                                    type="number"
                                    value={this.state.value}
                                    onChange={(e) => {
                                        this.setState({ value: e.target.value });
                                    }}
                                />
                                <button>입력!</button>
                            </form>
                            <div>{this.state.result}</div>
                        </>
                    );
                }
            }
            
 		<script type="text/babel">
            ReactDOM.render(<GuGuDan />, document.querySelector("#root")); 
        </script>

render 부분은 사용자가 볼 수 있는 화면이다. state에 저장해둔 값을 가져와서 사용한다고 생각하면 된다. 이 때 꼭 this를 써줘야 정상적으로 state값을 가져다가 사용할 수 있다. state값을 수정하고 싶으면 setState()를 사용해서 수정할 수 있다.

 

onChange부분에 이벤트를 따로 메서드로 만들지 않고 그대로 써준것과 form에는 따로 메서드로 분리해준 형태 이렇게 두개를 다르게 써둔것은 둘중 한 방법이 좋지 않은 방법임을 기억하고자 함이다.

 

onChange에 적용한 이벤트 적용방식이 좋지 않은 방법인데 왜일까? 렌더링이 될 때 불필요하기 때문이다. 함수를 바깥으로 빼주게 되면 렌더링이 일어날때마다 함수가 실행되는게 아니라 필요할 때만 실행이 된다. 하지만 내부에 써주면 렌더링 될때마다 함수가 실행되기 때문에 굉장히 비효율적이다. 지금이야 단순한 함수이지만 규모가 커지고 실행시간이 긴 함수가 있기라도 한다면? 큰 문제가 될것이다. 그러니 함수를 꼭 렌더 바깥에서 선언해서 사용하자.

 

 

앞서 바깥으로 빼준 onSubmit함수가 실행됐을 때 일어나는 이벤트를 정해주는 코드이다. 

 

    onSubmit = (e) => {
                    e.preventDefault();
                    if (parseInt(this.state.value) === this.state.first * this.state.second) {
                        this.setState((prevState) => {
                            return {
                                result: `정답  ${prevState.value}`,
                                first: Math.ceil(Math.random() * 9),
                                second: Math.ceil(Math.random() * 9),
                                value: "",
                            };
                        });
                        this.input.focus;
                    } else {
                        this.setState({
                            result: `정답은 ${this.state.value}!! 땡 `,
                            value: "",
                        });
                    }
                };

                input;
             
                onRef = (e) => {
                    this.input = e;
                };

if조건문에 보면 preventState가 있다. 이것은 이전값이랑 다음 코드들이 실행되었을 때 나와야 하는 값이 혼동될 수 있으니까 setState에 return을 해주고 이전값을 인자로 주게 되면 효율적으로 구분하며 표현할 수 있기 때문에 사용하면 좋다.  이전값을 사용해서 새로운 state 값을 만들고 싶으면 리턴값을 써줘야한다. 

 

onRef는 값을 입력하고 제출 한뒤 인풋의 포커스가 없어지지 않고 유지되었으면 해서 설정해둔 것! DOM에 직접적으로 접근하고 싶을 때 유용하게 사용할 수 있다. 

 

 

 

⚡전체 코드

    <div id="root"></div>
        <script type="text/babel">
            const e = React.createElement;
            class GuGuDan extends React.Component {
                constructor(props) {
                    super(props);
                    this.state = {
                        first: Math.ceil(Math.random() * 9),
                        second: Math.ceil(Math.random() * 9),
                        value: "",
                        result: "",
                    };
                }

                onSubmit = (e) => {
                    e.preventDefault();
                    if (parseInt(this.state.value) === this.state.first * this.state.second) {
                        this.setState((prevState) => {
                            return {
                               
                                result: `정답  ${prevState.value}`,
                                first: Math.ceil(Math.random() * 9),
                                second: Math.ceil(Math.random() * 9),
                                value: "",
                            };
                        });
                        this.input.focus;
                    } else {
                        this.setState({
                            result: `정답은 ${this.state.value}!! 땡 `,
                            value: "",
                        });
                    }
                };

                input;
               
                onRef = (e) => {
                    this.input = e;
                };

                render() {
                    console.log("렌더링");
                    return (
                        <>
                            <div>
                                {this.state.first} 곱하기 {this.state.second}는?
                            </div>
                            <form onSubmit={this.onSubmit}>
                                <input
                                    ref={(e) => {
                                        this.onRef;
                                    }}
                                    type="number"
                                    value={this.state.value}
                                    onChange={(e) => {
                                        this.setState({ value: e.target.value });
                                    }}
                                />
                                <button>입력!</button>
                            </form>
                            <div>{this.state.result}</div>
                        </>
                    );
                }
            }
        </script>
        <script type="text/babel">
            ReactDOM.render(<GuGuDan />, document.querySelector("#root")); 
        </script>