김은정
Study

정리하기 파일

1.1 자바스크립트의 동등 비교

  • props의 동등 비교에 따른 결과로, 리액트 컴포넌트의 렌더링을 발생한다.
  • 리액트의 동등 비교를 기반으로 하는 것 : 리액트의 가상 DOM과 실제 DOM의 비교, 리액트 컴포넌트가 렌더링할지를 판단하는 방법, 변수나 함수의 메모제이션 등

1.1.1 자바스크립트의 데이터 타입

  • 원시 타입
    • 객체가 아닌 다른 모든 타입
    • undefined, null, boolean, Number, String, Symbol
  • 객체 타입(참조 타입)
    • 자바스크립트를 이루고 있는 대부분의 타입
    • 배열, 함수, 정규식, 클래스 등

1.1.2 값을 저장하는 방식의 차이

원시 타입과 객체 타입의 가장 큰 차이점은 바로 값을 저장하는 방식의 차이

이 값을 저장하는 방식의 차이가 동등 비교를 할 때 차이를 만드는 원인

  • 원시 : 불변 형태의 값으로 저장, 변수 할당 시점에 메모리 영역을 차지하고 저장, 값을 비교
  • 객체 : 변경 가능한 형태로 저장, 값 복사 시 값이 아닌 참조를 전달

1.1.3 Object.is

  • 두 개의 인수가 동일한지 확인하고 반환하는 메서드
  • 동등비교 ===가 가지는 한계를 극복하기 위해 만들어졌으나, 객체 간 비교에 있어서는 동일하게 동작
  • == vs Object.is :
    • == : 같음을 비교하기 전에 양쪽이 같은 타입이 아니라면 비교할 수 있도록 강제로 형변환
    • Object.is : 타입이 다르면 그냥 false
  • === vs Object.is : ===가 만족하지 못하는 특이한 케이스 비교 (양의 0, 음의0 비교 가능. NaN 비교 가능)

1.1.4 리액트에서의 동등 비교

  • Object.is를 구현한 폴리필(Polyfill)을 함께 사용
    • 폴리필(Polyfill) : 변경된 표준을 준수할 수 있게 기존 함수의 동작 방식을 수정하거나, 새롭게 구현한 함수의 스크립트
  • objectIS 함수 : 리액트에서 값을 비교하는 함수
  • shallowEqual 함수 : objectIS를 기반으로 동등 비교를 하는 함수. 의존성 비교 등에서 사용

⇒ Object.is로 비교 수행 → Object.is에서 수행하지 못하는 비교(객체 간 얕은 비교) 수행

❓리액트에서의 동등 비교시, 객체의 얕은 비교까지만 수행하는 이유

리액트에서 사용하는 JSX props는 객체이고, 리액트는 props에서 꺼내온 값을 기준으로 렌더링하기 때문에 얕은 비교로 충분하다.

1.2 함수

  • 함수 표현식과 선언식의 차이 : 호이스팅
  • 함수의 호이스팅 : 함수에 대한 선언을 실행 전에 미리 메모리에 등록하는 작업
    • 함수 선언문 : 미리 메모리에 등록되고, 코드의 순서에 상관없이 정상적으로 함수를 호출할 수 있게 됨

    • 함수 표현식 : 함수를 변수에 할당

      ⇒ 호이스팅되는 시점에 var의 경우에는 undefined로 초기화

      ← 런타임 이전에 undefined로 초기화되고, 런타임 시점에 함수가 할당되어 작동하기 때문

  • 화살표 함수와 일반 함수의 차이, this 바인딩
    • this : 자신이 속한 객체나 자신이 생성할 인스턴스를 가리키는 값
    • 일반 함수의 this : 함수가 어떻게 호출되느냐에 따라 동적으로 결정됨
    • 화살표 함수의 this : 상위 스코프의 this를 그대로 따름(함수 자체의 바인딩을 갖지 않음)

⇒ 화살표 함수는 별도의 작업을 추가로 하지 않고 this를 접근할 수 있음

1.2.3 다양한 함수 살펴보기

  • 즉시 실행 함수 : 함수를 정의하고 그 순간 즉시 실행되는 함수. 재호출 불가능

    ⇒ 독립적인 함수 스코프 운용

    ← 즉시 실행 함수 내부에 있는 값은 그 함수 내부가 아니고서는 접근 불가능하기 때문

    ⇒ 리팩터링에 도움

  • 고차 함수 : 함수를 인수로 받거나 결과로 새로운 함수를 반환하는 역할을 하는 함수

  • 고차 컴포넌트 : 함수형 컴포넌트를 인수로 받아 새로운 함수형 컴포넌트를 반환

    ⇒ 효율적인 리팩토링 가능(컴포넌트 내부에서 공통으로 관리되는 로직을 분리해 관리할 수 있음)

1.2.4 함수를 만들 때 주의해야 할 사항

  • 함수의 부수 효과를 최대한 억제하라
  • 가능한 한 함수를 작게 만들어라 (함수는 하나의 일만 하도록 → 재사용성 높임)
  • 누구나 이해할 수 있는 이름을 붙여라

1.3 클래스

  • constructor : 객체를 생성하는 데 사용하는 특수한 메서드
  • 프로퍼티 : 클래스로 인스턴스를 생성할 때 내부에 정의할 수 있는 속성값 (기본적으로 public 접근)
  • getter, setter
  • 인스턴스 메서드(프로토타입 메서드) : 클래스 내부에서 선언한 메서드
    • 프로토타입 체이닝 : 직접 객체에서 선언하지 않았음에도 프로토타입에 있는 메서드를 찾아서 실행을 도와주는 것

      ⇒ 생성한 객체에서도 직접 선언하지 않은, 클래스에 선언한 메서드를 호출할 수 있음

      ⇒ 메서드 내부에서 this 접근 가능

  • 정적 메서드 : 클래스의 인스턴스가 아닌 이름으로 호출할 수 있는 메서드
    • this 접근 불가능 (클래스 자신을 가리키기 때문)
    • 객체를 생성하지 않아도 여러 곳에서 재사용 가능 ⇒ 유틸 함수에 활용됨
  • 상속

1.4 클로저

함수형 컴포넌트의 구조와 작동 방식, 훅의 원리, 의존성 배열 등 함수형 컴포넌트의 대부분의 기술이 모두 클로저에 의존하고 있다.

1.4.1 클로저의 정의

  • 함수와 함수가 선언된 어휘적 환경
    • 선언된 어휘적 환경 : 변수가 코드 내부에서 어디서 선언됐는지
  • 코드가 작성된 순간에 정적으로 결정됨
  • 스코프 : 변수의 유효 범위, 스코프
    • 기본적으로 자바스크립트는 함수 레벨 스코프를 가짐. ({} 밖에서도 접근 가능한 것)

1.4.3 클로저의 활용

  • 전역 스코프 : 어디서든 원하는 값을 꺼내올 수 있으나, 누구나 수정할 수 있음

    ⇒ 클로저 내부에서만 접근하도록 변경한다면?

    ⇒ 전역 스코프의 사용을 막아, 개발자가 원하는 정보만 개발자가 원하는 방향을 노출시킬 수 있음

    • 직접적인 노출을 막아 사용자가 직접 수정하는 것(접근)을 제한
    • 무분별한 변경 막음
  • 리액트에서의 클로저, useState

    • useState의 호출은 컴포넌트 내부 첫 줄에서 종료되었지만, 계속해서 최신 값을 확인할 수 있음

      ← 외부 함수가 반환한 내부 함수는 외부 함수의 호출이 끝났음에도 자신이 선언된 외부 함수가 선언된 환경을 기억하기 때문

1.4.4 주의할 점

  • 클로저는 생성될 때마다 그 선언적 환경을 기억해야하므로 비용이 발생한다.

  • 클로저로 실행했을 때의 메모리 상태, 긴 배열을 어디에 사용하는지 상관없이 일단 내용을 기억해둬야 하기 때문에 메모리에 큰 배열이 올라가 있다.

    ⇒ 무분별한 클로저 사용은 메모리를 불필요하게 잡아 먹어 성능에 악영향을 미침

1.5 이벤트 루프와 비동기 통신의 이해

1.5.1 싱글 스레드 자바스크립트

  • 프로세스 : 프로그램을 구동해 프로그램의 상태가 메모리상에서 실행되는 작업 단위
  • 하나의 프로세서에서는 여러 개의 스레드를 만들 수 있고, 스레드끼리는 메모리를 공유할 수 있어 여러 가지 작업을 동시에 수행할 수 있음
  • 멀티 스레드
    • 내부적으로 처리가 복잡하다
    • 동시에 서로 같은 자원에 접근할 수 있는데, 이때 동시성 문제가 발생할 수 있음
    • 메모리 공유로 인해 동시에 같은 자원에 접근할 경우 타이밍 이슈가 발생할 수 있음
  • 싱글 스레드
    • 동시성을 고민할 필요가 없음

    • 특정 작업이 오래 걸린다면 웹페이지가 멈춘 것 같은 느낌을 줄 수 있음

      ← 하나의 작업이 끝나기 전까지는 다른 작업이 실행되지 않기 때문

1.5.2 이벤트 루프

  • 호출 스택(call stack) : 자바스크립트에서 수행해야할 코드나 함수를 순차적으로 담아두는 스택
  • 이벤트 루프 : 호출 스택이 비어 있는지 여부를 확인하는 것
  • 태스크 큐 : 실행해야 할 태스크의 집합

⇒ 이벤트 루프 :

  • 호출 스택에 실행 중인 코드가 있는지, 그리고 태스크 큐에 대기중인 함수가 있는지 반복해서 확인
  • 호출 스택이 비었다면 태스크 큐에 대기 중인 작업이 있는지 확인하고, 이 작업을 실행 가능한 가장 오래된 것부터 순차적으로 꺼내와서 실행(FIFO)
  • 비동기 함수 : 태스크 큐가 할당되는 별도의 스레드에서 수행(브라우저, Node.js)

1.5.3 태스크 큐와 마이크로 태스크 큐

  • 이벤트 루프는 하나의 마이크로 태스크 큐를 가짐
  • 마이크로 태스크 큐는 기존 태스크 큐보다 우선권을 가짐
    • 태스크 큐 : setTimeout, setInterval, setImmediate
    • 마이크로 태스크 큐 : process.nextTick, Promise 등
  • 브라우저에 렌더링하는 작업은 마이크로 태스크 큐와 태스크 큐 사이에서 일어남

1.7 선택이 아닌 필수, 타입스크립트

  • any 대신 unkown을 사용하자

  • 타입 가드를 적극 활용하자

    • instanceof : 지정한 인스턴스가 특정 클래스의 인스턴스인지 확인
    • typeof : 특정 요소에 대해 자료형을 확인
    • in : 어떤 객체에 키가 존재하는지 확인
  • 제네릭 : 함수나 클래스 내부에서 단일 타입이 아닌 다양한 타입에 대응할 수 있도록 도와주는 도구

  • 인덱스 시그니처 : 객체의 키를 정의하는 방식. [key: string]

    → 동적인 객체를 정의할 때 유용하지만, 존재하지 않는 키로 접근하면 undefined를 반환할 수 있음

    ⇒ 동적으로 선언되는 경우를 최대한 지양, 객체의 타입 좁히기

    • Record<Key, Value> 사용
    • 타입을 사용한 인덱스 시그니처
  • Object.keys로 객체의 key를 뽑아내고, 그 키로 객체에 접근할 때 에러가 발생하는 이유?

    Object.keysstring[]을 반환하는데, 이 string은 인덱스 키로 접근할 수 없기 때문

    ← 자바스크립트의 특징과, 타입스크립트의 구조적 타이핑의 특징 때문 ~> 덕 타이핑

    • 덕 타이핑 : 객체의 타입이 클래스 상속, 인터페이스의 구현 등으로 결정되는 것이 아니고 어떤 객체가 필요한 변수와 메서드만 지니고 있다면 그냥 해당 타입에 속하도록 인정해주는 것