리액트를 다루는 기술
모아나
Week2 Component,eventhandling

📝 면접질문

props와 state의 차이에 대해 설명해주세요.

props와 state 모두 컴포넌트에서 사용하거나 렌더링할 데이터를 담고 있으므로 비슷해보일 수 있으나 다릅니다. props는 부모 컴포넌트에서 설정해주는 컴포넌트의 속성값으로 함수형 컴포넌트의 경우 인자값으로 전달됩니다. 컴포넌트 자신은 읽기만 가능하여 직접 데이터 변경이 불가하며, 이를 변경하기 위해서는 최상위 부모 컴포넌트에서 변경하거나 추가로 state를 만들어주어야 합니다.

state는 컴포넌트 자체적으로 지닌 값으로 내부에서 변경가능한 데이터입니다. 함수형 컴포넌트에서 useState를 사용하여 렌더링 사이에 데이터를 유지하면서, 업데이트가 이뤄질때 리렌더링을 합니다. state는 불변성을 유지해줘야 하여 클래스형 컴포넌트에서는 setState로, 함수형 컴포넌트에서는 useState로 변경해줄 수 있습니다.

state가 비동기적으로 동작하는 이유에 대해 설명하세요.

이는 리렌더링과 관련있습니다. State 값이 변경되면 리액트가 이를 감지하고 VDOM과 비교하여 변경사항을 반영해줍니다. 만약 state값이 변경될 때마다 리렌더링을 동기적으로 한다면 그때마다 리렌더링이 되고 이는 성능 저하로 이어집니다. 따라서 세터함수는 state를 일괄 업데이트를 해줍니다.

클로저에 대한 개념을 설명하고, 어떻게 활용할 수 있는지 설명하세요.

클로저는 함수와 그 함수가 선언된 렉시컬 환경의 조합입니다. 함수가 속한 렉시컬 환경을 기억하여, 렉시컬 스코프 밖에서 함수가 실행되더라도 그 스코프에 접근할 수 있도록 해줍니다.

이는 자바스크립트에 없는 '캡슐화'라는 개념을 구현할 수 있도록 해줍니다. 또한 데이터베이스 인스턴스 생성 및 상태관리에 정보은닉의 이점을 이용할 수 있습니다.

3장 컴포넌트

1. 클래스형 컴포넌트

  • 함수 컴포넌트와의 차이

    • state기능 및 라이프사이클 기능 사용 가능
    • 임의 메서드를 정의할 수 있다.
    • 클래스형 컴포넌트 작성 시, 반드시 render함수 사용& 그 안에 보여줄 JSX를 반환
  • ES6의 화살표 함수

    • function() : 일반 함수에서 this는 자신이 종속된 객체를 가르킨다. //동적 바인딩
    • arrow function: 화살표 함수에서 this는 자신이 종속된 인스턴스를 가르킨다. //정적 바인딩
    function BlackDog(){
      this.name="흰둥이";
      return{
        name:' 검둥이'
        bark: function() {
          console.log(this.name +':멍멍');
        
        }
      }
    }
    const blackDog= new BlackDog();
    blackDog.bark() ; // 검둥이: 멍멍!
    function WhiteDog() {
      tihs.name='흰둥이'
      return{
        name: '검둥이'
        bark: ()=>{console.log(this.name +':멍멍!')}
      }
    }
    const whiteDog= new WhiteDog();
    whiteDog.bark(); //흰둥이: 멍멍! 

2. props

  • 프로퍼티의 줄임말로 컴포넌트의 속성을 설정

  • 프로퍼티는 해당 컴포넌트를 불러와 사용하는 부모 컴포넌트에서 설정 가능

  • ** 컴포넌트가 사용되는 과정에서 부모 컴포넌트에서 설정하는 값, 컴포넌트 자신은 읽기 전용 **

  • 프로퍼티 기본값: defaultProps를 사용해서 props를 지정하지 않을 때 보여줄 기본값 설정.

    import React from 'react';
     
    const Practice = props => {
        return (
            <div>
                {props.data} 
            </div>
        );
    };
     
    Practice.defaultProps = {
        data: "기본으로 설정된 값입니다."
    };
     
    export default PropsPractice;
  • destructuring Assignment: 비구조화 할당- 객체에서 값을 추출하는 문법.

  • propTpes를 통한 props 검증

    • propTypes를 이용해 타입을 지정해준다.
    • isRequired를 통해 필수 입력으로 설정 가능
    SthComponent.propTypes={
      name: PropTypes.string,
      number: PropTypes.number.isRequired
    }
  • 클래스형 컴포넌트에서 props

  • render 함수 내에서 this.props를 조회

  • propTypes, defaultTypes는 함수형 컴포넌트와 동일한 방식

3. state

  • props와 달리 **컴포넌트 내부에서 바뀔 수 있는 값 **
  • 두 가지 state : 클래스형 컴포넌트에서 state, 함수형 컴포넌트에서 useState
  • ** 클래스형 컴포넌트에서 state **
    import {Component} from 'react';
     
    class Counter extends Component{
      constructor(props){
        super(props);
        //state의 초깃값 설정하기
        this.state={
          number:0
        };
      }
      render(){
        const {number} = this.state;
        return (
          <div>
            <h1> {number} </h1>
            <button onClick={()=>{this.setState({number:number+1})}}/>
          </div>
        )
      }
    }
    • constructor작성시 반드시 super(props) 호출해줘야 함.
    • state는 객체 형식
    • render 함수에서 state 조회시 this.state로 조회.
    • state 값을 업데이트 할 때는 상태가 비동기적으로 업데이트 됨. => setState로 state 바로 업데이트 반영 ㄴㄴ
    • 바로 업데이트 하고 싶다면 setState 사용시 객체 대신 함수를 인자로 넣어라
        <button onClick{()=> this.setState(prevState=>{ number: prevState.number+1}, 
        ()=>{console.log('값 업데이트  특정 작업 수행, 두번째 파라미터에 콜백함수등록')}
        )}>
  • ** 함수형 컴포넌트에서 state **
    • useState Hooks를 사용한다.
    • useState 호출시 배열 반환 -> 배열 비구조화 할당 -> [ 현재 상태, 세터함수 ]
    • 반드시 state값 변경시 세터함수를 통해!!!
    • 객체 사본을 만들 때는 spread 연산자 활용. 배열은 내장함수 활용

렉시컬스코프와 클로저

Javascript 클로저 개념

: 자바스크립트의 클로저는 함수와 함수가 선언된 렉시컬 환경과의 조합이다. 클로저는 함수가 생성될 때 그 범위에서 사용할 수 있는 모든 변수에 접근할 수 있게 해준다.

1. 렉시컬 스코핑 (스코프: 변수나 함수가 유효할 수 있는 범위)

  • 렉시컬은 "코드를 작성하는 시점" 과 관련이 있다. JS는 렉시컬 스코핑을 사용하는 언어다. 즉, 함수의 실행 컨텍스트가 아니라, 함수가 실제로 작성된 위치에 따라 변수의 범위가 결정된다.

    function outerFunction() {
      var outerVar = 'I am outside!';
     
      function innerFunction() {
          console.log(outerVar); // 'I am outside!' outerFunction 범위에 정의되어 outerVar에 접근 가능하다.
      }
     
      return innerFunction
      }

2. 동적 스코핑

  • 렉시컬 스코프(정적스코프)와 다르게 함수를 어디서 호출했는지에 따라 상위 스코프가 결정됨.

3. 클로저

  • 함수와 그 함수가 선언된 렉시컬 환경의 조합. 함수 생성될 때, 그 함수는 주변 상태를 '기억'함. 다른 말로, 함수가 속한 렉시컬 스코프를 기억하여, 함수가 렉시컬 스코프 밖에서 실행되어도 이 스코프에 접근 가능할 수 있게 하는 기능.
 
  function outerFunction(){
  const outerVar= "I'm outside!"
    
  function innerFunction(){
    console.log(outerVar);
    }
    return innerFunction;
  }
    var myFunction = outerFunction();
    myFunction(); // 'I am outside!'
  • myFunction은 outerFunction을 호출함으로써 반환된 innerFunction 이다.
  • outerFunction이 실행을 마치고 반환된 후에도 innerFunction은 outerFunction의 변수 outerVar에 접근이 가능하다.

4. 클로저의 활용

  • 데이터 캡슐화, 상태 보존, 프라이빗 변수와 같은 패턴 구현에 유용
          function createCounter() {
      let count = 0;
      return {
          increase: function() {
              count++;
          },
          getCount: function() {
              return count;
            }
        };
    }
    console.log(count) //불가
    var counter = createCounter();
    counter.increase();
    counter.increase();
    console.log(counter.getCount());
    • createCounter 함수는 객체를 반환하고, 이 객체는 increase와 getCount 두 개의 메서드를 가지고 있다. count변수는 createCouter의 렉시컬 환경에 속하여 외부에서 직접 접근이 불가하다. 그러나 increasegetCount 함수는 클로저를 통해 count변수에 접근이 가능하다.

    • 예) 데이터베이스 인스턴스 생성 및 상태 관리

    • 주의 : 실수로 클로저로 생성된 함수는 꼭 nullify 필수 ! 그렇지 않으면 Memory Leak 이 발생