🔐 자바스크립트에서 유사배열과 배열의 차이는 무엇일까요? 유사배열의 각 요소를 수정하고 싶다면 어떤 과정을 거쳐야할까요?
유사배열과 배열의 차이를 비교하기 전에 각 용어의 개념을 정리하자.
배열(Array)
관련 있는 데이터를 하나의 변수에 할당해 관리하기 위해 사용하는 데이터 타입이다.
자바스크립트는 명시적 타입이 없기때문에, 하나의 배열은 여러 자료형을 가질 수 있는 특징이 있다.
배열을 사용하면 여러 데이터를 관련성 있게 관리할 수 있기 때문에 생산성 및 코드 가독성이 높아지고 이는 유지보수 비용의 감소로 이어진다.
유사배열(Array-Like Object)
이름 그대로 배열과 유사한 객체를 말한다.그렇기 때문에 유사배열은 배열의 forEach, map, filter, reduce 같은 메서드를 사용할 수 없다.
유사배열은 함수에서 처리 결과로 배열을 반환하고 싶을때 또는, Array에서 기본으로 내포되어있는 기능을 제공하고 싶지 않거나 Array에 내포되어있지 않은 기능을 제공하고싶을때 사용한다.
- 유사 객체 배열은 배열처럼 보이지만 사실 key가 숫자이고 length 값을 가지고 있는 객체이고 배열은 데이터 타입이는 점이 다르다.
유사배열의 각 요소를 수정하고 싶다면
- Array.from( )메서드를 사용하면 된다. Array.from() 메서드는 유사 배열 객체(array-like object)나 반복 가능한 객체(iterable object)를 얕게 복사해새로운Array 객체를 만든다. Array.from()으로 유사 배열 객체이 있는 value를 복사해 배열로 만드는 것이다. 그러면 배열 메서드를 사용할 수 있다.
또는
- 배열에 내포되어있는 기능들을 유사배열에서 사용하기 위해 call, apply, bind을 사용한다. (apply와 call은 함수를 호출하는 방법 중 하나로, 다른 객체에 내포되어있는 함수를 내것처럼 사용할 수 있게 해준다.)
부모 컴포넌트 A와 자식 컴포넌트 B가 있습니다. 컴포넌트 A는 state로 {name: "르탄이"}를 가지고 있고, 자식인 컴포넌트 B에게 name 값을 넘겨주었습니다. 컴포넌트 B는 받아온 name을 화면에 뿌려주고 있습니다. 컴포넌트 A의 state가 {name: "진도사우르스"}로 바뀌었을 때, 어떤 과정을 거쳐 바뀐 값을 화면에 보여주는 지 라이프 사이클 흐름을 그려볼까요?
컴포넌트 A에서 “르탄이”라는 state를 “진도사우르스” 변경 -> 부모 컴포넌트에서 Updating이 발생 -> shouldComponentUpdate 가 실행 -> 바뀐 props를 이용하여 부모 컴포넌트의 렌더링 -> 마찬가지로 바뀐 props를 이어받아 컴포넌트 B의 렌더링이 실행 된다.
양방향 바인딩은 무엇일까요? 양방향 바인딩을 사용하는 경우 리렌더링이 어떻게 이루어질 지 그려보세요. (부모 컴포넌트 A와 자식 컴포넌트 B가 있음을 가정하고 그려봅시다.)
양방향 바인딩의 경우, 사용자의 입력값이 곧바로 코드 상의 변수에 바인딩 될 수 있지만 단방향바인딩의 경우 적절한 Event를 통해서만 코드 상 변수에 데이터 값이 담긴다.
양방향 데이터 바인딩이란 뷰와 모델의 데이터를 동기화하는 것이다.
즉 사용자의 입력값에 따라 js의 데이터가 변경되고,
js의 데이터가 변경되면 사용자의 화면도 변경된다
event listener는 등록되면 반드시 해제되어야 합니다. 클래스형 컴포넌트에서는 컴포넌트가 화면에서 사라질 때(unmount 될 때) event listener를 해제합니다. (componentWillUnmount에서요!) 그럼 라이프사이클 메소드를 사용할 수 없는 함수형 컴포넌트에서는 event listener를 해제할 때 어떻게 해야할까요?
클래스형 컴포넌트에서 componentDidMount()의 역할을
함수형 컴포넌트에선 useEffect()훅을 사용한다.
따라서, 클래스형에서 componentWillUnmount() 단계를
useEffect()에서는 return() 단계에서 동작한다.
이 단계에서 .removeEventListener()을 사용해 이벤트를 해제해줘야 한다.
리액트에서는 DOM 요소에 접근하기 위해 주로 ref를 씁니다. domcument.getElementsByClassName 등을 쓰는 게 아니라 ref를 쓰는 이유는 무엇일까요?
ref는 reference의 준말 (참고,참조) ref는 render 메서드에서 생성된 DOM 노드나 React 엘리먼트에 접근하는 방법을 제공합니다.
-React 공식문서-
ref를 쓰는 이유는 ref는 특정 DOM 요소를 가져올 때 더 신뢰할 만하기 때문입니다. 라이프사이클에 따라 DOM 요소를 가져오지 못하는 경우가 있습니다 예측하지 못한 상황(대개는 라이프사이클의 흐름을 예측하지 못한 상황)으로 DOM 요소를 가져오지 못한다면 이는 해당 코드가 포함된 로직에 따라 큰 문제가 발생할수 있습니다
또 만약 컴포넌트가 하나가 아닌 여러 개가 생성되는 경우 이때 우리는 id나 class로 특정해서 원하는 DOM 요소를 가져오기가 힘들다 DOM 요소를 특정할 수 있도록 관심 영역을 특정 컴포넌트로 제한하는 역할도 ref가 할 수 있습니다.
SPA 방식과 MPA 방식은 무엇인가요?
SPA(Single Page Application)는 한 개 Page로 구성되어있고
MPA(Multi Page application)는 여러 개 Page로 구성되어있다
MPA는 새로운 페이지를 요청할 때마다 정적 리소스가 다운로드 되고, 그에 맞춰 전체 페이지를 다시 렌더링한다.
인터넷 주소창에 주소를 입력하거나, 링크를 클릭하는 등 사용자가 어떤 요청을 하면, 그에 맞는 html, 이미지 등의 파일들이 전부 다운로드 되고 다시 렌더링 된다.
반면 SPA는 웹 애플리케이션에 필요한 모든 정적 리소스를 최초 한번에 다운로드한다.
그 이후 새로운 페이지 요청이 있을 경우, 페이지 갱신에 필요한 데이터만 전달받아 페이지를 갱신한다.
어떤 링크를 클릭한다고 해서 그에 관련된 모든 파일을 다운받는게 아니라, 필요한 정보만 받아서 그 정보를 기준으로 업데이트 될 뿐이다.
그래서 SPA를 CSR(Client Side Rendering)방식으로, MPA를 SSR(Server Side Rendering)방식으로 렌더링한다고 말한다.
가상DOM이란?
작업을 하다가 어떠한 부분을 수정해야 할떄
document.getElementById()라는 DOM 접근 메서드를 이용할 텐데 이 방식의 아쉬운점은 메모리 누수와 속도 그리고 코드량이 있다 만일 태그를 찾는 코드를 변수에 저장하지 않고 매번 메서드를 사용한다면 매 단계마다 수많은 DOCUMENT객체들을 전부 흝으며 찾는 현상이 발생되고 이것은 곧 메모리 누수로 이어진다 그리고 수정후 변화가 일어난다면 다시 연산하고 레이아웃을 구성하고 웹페이지를 다시 그려주는 과정에서도 시간이 든다
다른하나의 객체를 찾기 위해 작성하는 코드가 복잡할수있다 ID라는 고유성을 침해하당하지 않게 태그의 네이밍을 심사숙고해야할것이고 태그를 접근하기 위해 작성해야 하는 메서드가 짧지않다(document.getElementById())
html 마크업을 시각적이 형태로 변환하는 시간(css가 적용되고 수정되어 반영되는 시간)이 드는 것은 어쩔 수 없지만, 최소한의 DOM 조작을 통해 개선하고자하여 가상돔이라는 개념을 도입되었다
가상돔이란? 실제 돔에 접근하여 조작하지 않고 이것을 추상화시킨 자바스크립트 객체를 이용해 사용한다 (무거운 실제 돔의 가벼운 사본느낌)
작은 규모의 레이아웃(리플로우)이 여러번 발생하는 것보다 큰 규모의 레이아웃이 한 번 발생하는 것은 성능상의 큰 차이를 나타낸다
- 변화가 일어났을때 변화된 버전을 가상돔으로 바꿈(데이터가 업데이트 되면 전체 UI를 가상돔에 리렌더링)
- 가상돔끼리 비교(변화 전의 가사돔과 변화된 가상돔 비교)
- 바뀐부분만 적용(바뀐부분만 실제 돔에 적용 함으로써 에이아웃 계산은 한번만 이행된다)
jsx문법의 특징
- 반드시 부모 요소 하나가 감싸는 형태여야 한다
- virtyal dom에서 컴포넌트 변화를 감지할때 효율적으로 비교할수 있도록 컴포넌트 내부는 하나의 dom트리 구조로 이루어져야 한다는 규칙이 있기 때문
- 자바스크립트 표현식
- jsx안에서도 자바스크립트 표현식을 사용할수있다 자바스크립트 표현식을 작성하려면 jsx 내부에 코드를 중괄호로 {} 감싸준다
- if문(for문) 대신 삼항 연산자(조건부 연산자) 사용
- 자바스크립트의 if문과 for 루프는 jsx에는 쓸수가 없다 그렇기 때문에 조건부에 따라 다른 렌더링 시 JSX 주변 코드에서 if문을 사용하거나, {}안에서 삼항 연산자(조건부 연산자)를 사용 한다.
- React DOM은 HTML 어트리뷰트 이름 대신 camelCase 프로퍼티 명명 규칙을 사용 한다
- JSX에서 자바스크립트 문법을 쓰려면 {}를 써야 하기 때문에, 스타일을 적용할 때에도 객체 형태로 넣어 주어야 한다. 카멜 표기법으로 작성해야 한다. (font-size => fontSize)
- JSX 내에서 주석 사용 방법
- JSX 내에서 {/…/} 와 같은 형식을 사용 한다
Class Component와 Function Component의 차이점
Class Component는 여러 단계의 상속으로 이어져있어 복잡성과 오류 가능성을 증가시킨다. 이로 인해 Function Component가 탄생하게 되었고, Class component는 라이프 사이클을 가지며 이로인해 각각 생명주기 메소드에 대해 알고 있어야 한다. 하지만 function component는 이러한 기능을 hooks을 사용하여 생명주기에 원하는 동작을 하게해 좀더 자유롭다.
styled-components의 의미와 예시
기존 돔을 만드는 방식인 css, scss 파일을 밖에 두고, 태그나 id, class이름으로 가져와 쓰지 않고, 동일한 컴포넌트에서 컴포넌트 이름을 쓰듯 스타일을 지정하는 것을 styled-components라고 부릅니다.
css 파일을 밖에 두지 않고, 컴포넌트 내부에 넣기 때문에, css가 전역으로 중첩되지 않도록 만들어주는 장점이 있습니다
이런식으로 따로 css를 따로 만들지 않고도 쉽고 직관적으로 속성을 적용시키고 수정이 가능하다.
css 중첩을 막기 위한 방법과 예시
클래스 이름으로 인해 중첩이 일어나는 경우가 흔치 않다.
이를 막기 위한 방법으로 CSS Moduel이라는 것을 사용하게 되는데
그 이유는
- 클래스 이름이 중첩되는것을 방지해준다.
- 유지보수하기 편해진다
- 사용 범위를 제한하여, 스타일링 하고싶은 컴포넌트가 다른 컴포넌트와 중복되는클래스 이름에 의하여 방해되는것을 막아준다.
아래 사진들은 css module을 사용하지 않았을때 일어나는 상황이다.
Module1.js에 module1.css를 import 했는데, Module2.js에도 스타일이 들어갔다.
이런 경우를 방지하기 위해 CSS Module을 사용한다.
CSS Module 사용해서 css를 적용하게 되면 이런 식으로 원하는 곳에만 적용하는 게 가능하게 된다.