1.6 리액트에서 자주 사용되는 JS 문법

gonn-i·2025년 3월 11일
post-thumbnail

본게시글은 모던 리액트 deep dive를 읽고 정리한 글입니다.

자바스크립트 문법을 작성할때에, 자바스크립트 표준인 ECMAScript 버전을 고려해야 한다.

  • 왜냐하면 모든 브라우저와 자바스크립트 런타임이 항상 새로운 자바스크립트 문법을 지원하는 것은 아니기 때문이다.
  • 익스플로러 11은 ES5까지만을 지원하기 때문에 최신 js 문법을 사용할 수 없다.
  • 그래서 웹페이지에 접근하는 사용자의 브라우저와 버전은 개발자와 달리, 항상 최신 버전이 아닐 수 있기에 다양한 브라우저의 문법 지원을 염두에 두어야 한다.

그래서 우리에게 필요한 바벨

바벨은 자바스크립트의 최신 문법을 다양한 브라우저에서도 일괄적으로 지원할 수 있도록 코드를 트랜스파일한다.

  • 바벨 트랜스파일 코드는, 익스플로러를 지원하는 ES5를 기준으로 작성됐다

1.6.1 구조 분해 할당

구조분해할당은 배열 또는 객체의 값을, 말 그대로 분해해서 개별 변수에 즉시 할당하는 것을 의미한다. 주로 객체나 배열에서 각각의 선언문 없이, 즉시 분해해서 변수 선언과 할당을 같이할 수 있다는 장점이있다.

  • 배열 구조분해 할당 -> ES6(ECMA2015)
  • 객체 구조분해 할당 -> ECMA2018

배열 구조 분해 할당

const array = [1, 2, 3, 4, 5];
const [first, second, third, ...arrayRest] = array;

// first 1
// second 2
// third 3
// arrayRest [4, 5]

// -----

const [value, setValue] = useState();

대표적인 예시가 바로 useState이다.

  • useState가 객체가 아닌 배열을 반환하는 이유는 -> 배열 구조 분해 할당은 자유롭게 이름을 선언할 수 있기 때문으로 추측할 수 있다.
// 배열 구조 분해 할당은  , 위치에 따라 값이 결정된다,
const array = [1, 2, 3, 4, 5]
const [first, , , , fifth] = array // 2, 3, 4는 아무런 표현식이 없으므로 변수 할당 생략
// first  1
// fifth  5

// 기본값을 선언할 수도 있는데, 만약 사용하고자 하는 배열 길이가 짧을 경우 기본값을 사용할 수 있다. 

const array = [1, 2]
const [a = 10, b = 10, c = 10] = array

// a 1
// b 2
// c 10 (원래 undefined인데 10이 기본값으로 할당됨) 

기본값 할당시 주의할 점은, 오직 undefined 일때만 기본값이 적용된다는 점이다.

  • null / 0 / '' 일때는 기본값이 적용되지 않는다.
// spread 연산자를 사용하여, 특정값 이후의 값을 다시금 배열로 선언 가능
const array = [1, 2, 3, 4, 5]
const [first, ...rest] = array

// first 1
// rest [2, 3, 4, 5]

배열 구조 분해 할당 코드가 바벨에서 어떻게 트랜스파일될까!

// 트랜스파일하기 전
const array = [1, 2, 3, 4, 5]
const [first, second, third, ...arrayRest] = array

// 트랜스파일된 결과
var array = [1, 2, 3, 4, 5]
var first = array[0],
second = array[l],
third = array[2],
arrayRest = array.slice(3)

객체 구조 분해 할당

배열 구조 분해 할당과 마찬가지로, 구조를 분해해서 꺼내온다는 의미는 같다.
다만, 객체에서 값을 꺼내온 뒤 할당하는데, 이때 객체는 객체 내부 이름으로 꺼내온다는 차이가 있다. (배열은 순서 기준으로 값을 꺼내온다)

// 전개 연산자도 사용 가능하며, 이름을 다시 할당할 수도 있다.
// 배열과 마찬가지로, 기본값을 설정하는 것도 가능하다. 
const object = {
a: undefined,
b: 2,
c: 3,
d: 4,
e: 5,
}

const { a:first = 10, b:second, c:third, ...objectRest } = object
// first 10
// second 2
// third 3
// objectRest = {d: 4, e: 5}

객체 구조 분해할당의 경우, props 에서 값을 바로 꺼내올때 자주 사용되는 방식이기에 중요하다.

또한 단순히 값을 꺼내오는 것뿐만 아니라, 속성 이름 방식으로도 사용 가능하다
(변수 값으로 값 꺼내오기)

const key = 'a'
const object = {
a: 1,
b: 1,
}

// 이때, [key]의 네이밍을 적용해주지 않으면 오류가 발생한다.
// 왜냐? -> [key]로 값만 꺼냈지, 변수에 할당해주지 않았기 때문
const { [key]: a } = object
// a = 1

객체 구조 분해 할당 코드가 바벨에서 어떻게 트랜스파일될까!

배열 구조 분해 할당과는 달리, 트랜스파일 코드가 좀더 복잡하다.
트랜스파일 과정에서는 두가지 함수를 사용하는데 내용을 아래와 같다.

_objectWithoutPropertiesLoose

  • 객체와 해당 객체에서 제외할 키가 포함된 배열 두가지를 인수로 받음
  • 이 두가지 값을 활용해서, 특정 키를 제외

objectWithoutProperties

  • Object.getOwnPropertySymbols가 존재하는 환경인 경우를 대비

객체 구조 분해 할당의 경우, 트랜스파일을 거치면 번들링 크기가 상대적으로 크기 때문에 개발 환경에 따라서, ES5인 경우 객체 구조 분해 할당을 자주 쓰진 않는다면 꼭 써야 하는지 검토해볼 필요가 있다.
(... rest 와 같은 함수가 필요하다면 외부 라이브러리를 사용하는것도 고려해봄직 하다! lodash.omit rambda.omit)


1.6.2 전개구문

전개 구문은 배열이나 객체, 문자열과 같이 순회할 수 있는 값에 대해 전개해서 간결하게 사용할 수 있는 구문이다.

  • 배열 전개 구문 -> ES6(ECMA2015)
  • 객체 전개 구문 -> ECMA2018

배열 전개구문

이전에는 배열 간의 합성을 위해서 push() concat() splice() 등의 메서드를 사용해야 했는데 전개구문을 이용하면 아주 간편하다.

const arr1 = ['a', 'b']
const arr2 = arr1
arr1 === arr2 // true. 내용이 아닌 참조를 복사하기 때문 

const arr1 = ['a', 'b']
const arr2 = [...arrl]
arr1 === arr2 // false. 실제로 값만 복사됐을 뿐

배열 전개 구문 트랜스파일 코드

// 트랜스파일하기 전
const arr1 = ['a', 'b']
const arr2 = [...arr1, 'c', 'd', 'e']
              
// 트랜스파일된 결과  (concat로 배열을 연결)
var arr1 = ['a', 'b']
var arr2 = [].concat(arr1, ['c', 'd', 'e'])

객체 전개구문

객체 전개 구문의 경우, 사용에 있어서 크게 다른 점은 없지만
전개 구문 이후에 값 할당이 있다면, 그 내용이 덮어씌워질 수 있다.

또한, 객체 구조 분해 할당과 마찬가지로, 트랜스파일 코드가 굉장히 길다.
단순히 값을 복사하는 배열과는 다르게, 객체의 경우 객체 속성값 및 설명자 확인, 심벌체크 등 으로 인해 코드가 커지기에, 상대적으로 번들링 크기로 인해 사용에 있어 주의가 필요하다.


1.6.3 객체 초기자

객체 초기자란, 객체 선언시 객체에 넣고자 하는 키와 값을 가지고 있는 변수가 이미 존재한다면 해당 값을 간결하게 넣어줄 수 있는 방식

const a = 1
const b = 2

const obj = {
  a,
  b,
}
// {a: 1, b: 2}

a: a 와 같은 형식으로 작성하는 대신, 변수를 넣어주면 위와 같이 축약해서 선언하는 것이 가능하다. 트랜드파일 코드 역시


1.6.4 Array 프로토타입의 메서드: map, filter, reduce, forEach

map, filter, reduce, forEach 는 ES5에서부터 사용한 문법으로, 별도의 트랜스파일이나 폴리필이 없어도 부담없이 사용할 수 있다는 특징이있다.

1️⃣ Array.prototype.map

const arr = [1, 2, 3, 4, 5]
const doubledArr = arr.map((iem) => iem * 2)
// [2, 4, 6, 8, 10]

// 리액트
const arr = [1, 2, 3, 4, 5]
const Elements = arr.map((iem) => {
return <Fragment key={item}>{item}</Fragment>
})

인수로 전달받은 배열과 똑같은 길이의 새로운 배열을 반환하는 메서드이다.
리액트에서도 특정 배열 기반, 리액트 요소를 반환하고자 할때 많이 사용된다.

2️⃣ Array.prototype.filter

const arr = [1, 2, 3, 4, 5]
const evenArr = arr.filter((item) => item % 2 === 0)
// [2, 4]

콜백함수에서 truthy 한 조건을 만족하는 경우에만, 원소를 반환하는 메소드이다. 참인 경우에만 필터링을 하기에, 기존 배열의 크기와 다른 크기를 가진 배열이 반환될 수도 있다.

3️⃣ Array.prototype.reduce

const arr = [1, 2, 3, 4, 5]
const sum = arr.reduce((result, item) => {
	return result + item
}, 0)
// 15

쉽게 말해서 누적연산을 할때, 사용되는 메소드이다.
메서드에서는 콜백 함수와 함께 초깃값을 추가로 인수를 받는데, 이 초깃값에 따라 배열이나 객체, 또는 그 외의 다른 무언가를 반환할 수 있다.

4️⃣ Array.prototype.forEach

const arr = [1, 2, 3]
	arr.forEach((item) => console.log(item))
// 1, 2, 3

콜백 함수를 받아, 배열을 순회하면서 단순히 콜백함수만을 실행하는 메서드이다.
위에서 봤던 3개의 메서드와는 다르게, 반환값이 없다는 점이 특징이다.
또한, 반복문을 돌면서 중간에 breakreturn 을 해도 배열 순회를 멈출 수 없다.


1.6.5 삼항 조건 연산자

자바스크립트에서 유일하게 3개의 피연산자를 취할 수 있는 문법이다.

조건문? 참일때 값 : 거짓일때 값 의 형식으로 나타난다.

function Component({ condition }) {
	return <>{condition ? '참, : '거짓,}</>
}

종종 삼항 연산자를 중첩해서 사용하는 경우도 흔한데, 가독성면에서 가급적 지양하는 것이 좋다고 한다.

profile
https://gonnn-i.tistory.com/

0개의 댓글