본문 바로가기
부트캠프

멋쟁이사자처럼 프론트엔드 부트캠프 14기 - Day 49 (유용한 배열 메서드, 배열 리듀싱, 객체 속성 순환, 암묵적 객체 반환, 명령형 vs. 선언적 코드)

by 나른한_꼬리_ 2025. 7. 7.
반응형

멋쟁이사자처럼 프론트엔드 부트캠프 14기 - Day 49 (유용한 배열 메서드, 배열 리듀싱, 객체 속성 순환, 암묵적 객체 반환, 명령형 vs. 선언적 코드)

 

목차

 

유용한 배열 메서드

JavaScript의 유용한 기능 중 하나로 배열을 조작하는 데 도움이 되는 메서드들이 있다.

  1. .findIndex(): 배열 객체에서 참(truthy)으로 평가되는 첫 번째 항목(item)의 인덱스(index)를 반환한다. 참으로 평가되는 항목이 없으면 -1을 반환한다.
  2. .find(): 배열 객체에서 참으로 평가되는 첫 번째 항목(item)을 반환하고, 없으면 undefined를 반환한다.
  3. .filter(): 배열 객체의 항목 중 참으로 평가되는 모든 항목을 걸러내어(filtering, 필터링) 새로운 배열을 반환한다. 없으면 빈 배열([])을 반환한다.
  4. .map(): 배열의 각 항목을 순환해 새로운 배열을 반환한다. 특정 항목만 있는 배열을 생성하거나 각 항목에 무언가 추가한 배열을 생성할 수도 있다.
const people = [
  { id: 1, name: '지영' }, // index: 0
  { id: 2, name: '아름' }, // index: 1
  { id: 3, name: '한영' }, // index: 2
]

// .findIndex() 메서드
const personIndex = people.findIndex((person) => {
  // 항목(item) 비교 후, 참으로 평가되는 인덱스(index) 반환
  return person.name === '한영'
})
console.log(personIndex) // 2

// .find() 메서드
const person = people.find((person) => {
  return person.id === 2
})
console.log(person) // { id: 2, name: '아름' }

// .filter() 메서드
const youngPeople = people.filter((person) => person.name.endsWith('영'))
console.log(youngPeople) // [{id: 1, name: '지영'}, {id: 3, name: '한영'}]

// .map() 메서드
const korean = people.map((person) => {
  // 각 항목(item)에 무언가를 수행하는 표현식 작성
  return { ...person, nationality: '대한민국' }
})

console.log(korean) // nationality: '대한민국' 추가된 새 배열 객체 생성됨
console.log(people) // 매핑에 사용된 배열은 변경 없음

 

.map() 메서드와 forEach() 메서드가 유사해 보이지만 .map() 메서드새 배열을 반환하고, forEach() 메서드반환 값이 없다. 새로운 배열을 반환해야 할 때 .map() 메서드를 사용하고, 새로운 배열 반환 없이 각 항목을 순환해 무언가 해야 할 때는 forEach() 메서드를 사용하면 된다.

 

배열 리듀싱

배열 객체의 .reduce() 메서드를 사용하면 배열을 하나의 값으로 변환하는 데 도움을 준다.

// accumulator: 이전 반복에서 반환된 값
// currentValue: 현재 반복 중인 배열의 항목
const callback = (accumulator, currentValue, index) => {
  // 어떤 값 반환
}
// initialValue: 시작할 값
const result = array.reduce(callback, initialValue)

 

배열을 숫자로 리듀싱. 배열의 각 숫자를 더해서 하나의 숫자 값으로 변환하는 코드를 작성한 예시다.

const numbers = [1, 2, 3, 4, 5]

// for 문 사용
let totalFor = 0

for (let i = 0, currentNumber; currentNumber = numbers[i]; i++) {
  totalFor += currentNumber
}

console.log(totalFor) // 15

// .reduce() 메서드 사용
const total = numbers.reduce((total, number) => total + number, 0)
console.log(total) // 15

 

배열을 객체로 리듀싱. 과일 개수를 세서 객체로 변환한다.

const fruits = [
  '바나나', '애플', '오렌지', '애플', '바나나', '워터 멜론', '오렌지','워터 멜론', '바나나', '참외',
]

const fruitsCount = fruits.reduce((o, fruit) => {
  if (o[fruit]) {
    o[fruit] += 1
  } else {
    o[fruit] = 1
  }
  return o
}, {})

// 삼항 연산자 사용하여 간결하게 작성(가독성 떨어짐)
// const fruitsCount = fruits.reduce((o, fruit) => {
//   o[fruit] ? (o[fruit] += 1) : (o[fruit] = 1)
//   return o
// }, {})

배열을 배열로 리듀싱. 여러 배열을 포함하는 배열이 있을 때 포함한 각 배열의 모든 값을 하나의 배열에 포함되도록 변환하는 것을 배열 평탄화(Flattening)라고 부른다.

const nestedArray = [
  [1, 2, 3, 4, 5],
  [6, 7, 8, 9, 10],
]

const flattenedArray = nestedArray.reduce((result, itemArray) => {
  result.push(...itemArray)
  return result
}, [])

// 평탄화 결과
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

// 전개 구문 사용하여 코드를 더 간결하게 작성할 수 있지만, 가독성 떨어짐
// const flattenedArray = nestedArray.reduce(
//   (result, itemArray) => [...result, ...itemArray], 
//   [],
// )

 

배열 평탄화는 .flat() 메서드를 사용하면 간단하다.

const flattenedArray = nestedArray.flat()

 

배열을 문자열로 리듀싱. 배열을 템플릿 스트링으로 변환한다.

const list = [
  { content: '하나' },
  { content: '둘' },
  { content: '셋' },
  { content: '넷' },
  { content: '다섯' },
]

const templateString = list.reduce((template, { content }) => 
  `${template}<li>${content}</li>`, 
  ''
)
console.log(templateString) // <li>하나</li><li>둘</li><li>셋</li><li>넷</li><li>다섯</li>

 

객체 속성 순환

JavaScript에서 객체를 반복해야 하는 경우가 종종 있다. 객체를 반복하는 가장 좋은 방법은 객체를 배열로 변경하는 것이다. 객체를 배열로 변경하기 위해서는 다음과 같은 객체의 메서드를 사용한다.

  • Object.keys(): 전달된 객체의 키 집합을 배열로 생성
  • Object.values(): 전달된 객체의 값 집합을 배열로 생성
  • Object.entries(): 전달된 객체의 [키, 값] 쌍을 배열로 생성(중첩된 배열 생성)
const 과일 = {
  사과: 26,
  바나나: 34,
  배: 17, 
}

const keys = Object.keys(과일)
console.log(keys) // ['사과', '바나나', '배']

const values = Object.values(과일)
console.log(values) // [26, 34, 17]

const entries = Object.entries(과일)
console.log(entries)
// [
//   ['사과', 26],
//   ['바나나', 34],
//   ['배', 17],
// ]

Object 메서드 중 하나를 사용해 객체를 배열로 변경한 후, 변경된 배열을 반복 처리할 수 있다.

const keys = Object.keys(과일)
for (const key of keys) console.log(key)

const values = Object.values(과일)
for (const value of values) console.log(value)

const entries = Object.entries(과일)
// for (const entry of entries) console.log(entry)
for (const [key, value] of entries) console.log(key, value)

// for ... of 문 대신 forEach() 메서드를 사용하면 다음과 같다.
Object.entries(과일).forEach(([이름, 갯수]) => {
  console.log(`과일 바구니에 "${이름}"가 ${갯수}개 있습니다.`)
})
// 과일 바구니에 "사과"가 26개 있습니다.
// 과일 바구니에 "바나나"가 34개 있습니다.
// 과일 바구니에 "배"가 17개 있습니다.

 

 

암묵적 객체 반환

다음 두가지 규칙을 따르면 화살표 함수가 암묵적 반환을 수행한다

  1. 함수에 한 줄 코드만 작성
  2. 해당 코드 줄은 중괄호로 묶이지 않음

화살표 함수는 암묵적으로 값을 반환할 때 중괄호({})를 생략한다. 객체도 중괄호를 표기하기 때문에 화살표 함수를 암묵적으로 사용할 땐 객체 값을 괄호(())로 묶어야 한다.

const createUser = ({ name, age } = {}) => ({ name, age })

 

명령형 vs. 선언적 코드

코드 작성 방법은 명령형과 선언적 방법으로 두 가지다. React는 선언적 코드 작성 방법을 사용한다.

 

 

명령형 코드(Imperative Code)

명령형 코드는 프로그램에 무엇을 해야 하는지 알려준다. 예를 들어, 1 + 1 코드를 작성하면 프로그램에 11을 더해 2를 출력하도록 지시하는 것이다. 이 코드 라인은 프로그램에 무엇을 해야 할지 알려주기 때문에 필수적이다.

 

for ... of 문명령형 코드다. 아래는 과일 이름을 포함하는 과일바구니 배열에서 배의 개수를 구하는 코드다.

const 과일바구니 = ['사과', '배', '망고', '포도', '배']

let 배_개수 = 0

for (let 과일 of 과일바구니) {
  if (과일 === '배') {
    배_개수 += 1
  }
}

console.log(배_개수) // 2

 

선언적 코드(Declarative Code)

선언적 코드를 사용하면 프로그램이 구현할 세부 사항에 신경쓰지 않고 작업을 수행할 수 있다. 세부 사항은 종종 함수에 의해 처리된다. 위 코드를 선언적 코드로 다시 작성하면 다음과 같다.

const 과일바구니 = ['사과', '배', '망고', '포도', '배']

const 배_개수 = getPearCount(과일바구니)
console.log(배_개수) // 2

 

위 코드에서 getPearCount 함수를 명령형 코드 방식과 선언적 코드 방식으로 작성할 수 있다.

// 명령형 코드 방식으로 배의 개수 구하기
function getPearCount(fruitBasket) {
  let pearCount = 0
	
  for (let fruit of fruitBasket) {
    if (fruit === '배') {
      pearCount = pearCount + 1
    }
  }
	
  return pearCount
}

// 선언적 코드 방식으로 포도 개수 구하기
const getGrapeCount = (fruitBasket) =>
  fruitBasket.filter(fruit => fruit === '포도').length

 

오늘 하루를 돌아보며

오늘도 역시 진도를 엄청 빠르게 나갔다. 그래도 다행히 못 따라갈 것 같을 때쯤에 강사님의 폭주를 막는 '잠시만요, 천천히 해주세요'라는 메시지들이 올라왔다. 부랴부랴 강의 노트를 적다 보면 강사님께 천천히 해달라고 타이핑을 칠 여유조차 없을 때가 많은데 속도를 조절해 주는 동기들이 있어서 감사하다.

 

마지막 주제로 선언적 코드에 대한 내용 중에 마음에 위로가 되는 말이 있어서 아래 남긴다.

선언적 코드가 명령형 코드보다 낫지만, 처음엔 작성이 쉽지 않습니다.
그러니 처음부터 선언적 코드 작성을 해야 한다는 강박관념에 사로잡히지 마세요.
중요한 것은 코드 방식이 아니라, 프로그램이 작동되도록 하는 것입니다.
프로그램이 작동되면 추후에 리팩토링하여 명령형 코드를 선언적 코드로 변경할 수 있습니다.
시간이 지나면 선언적 코드 작성에 익숙해질 것이니 너무 조급해하지 않길 바랍니다.

 

나에게 정말 필요한 말이었다. 처음부터 잘하려는 생각에 조급해지면서 코드를 어디서부터 작성하기 시작해야 할 지조차 감을 못 잡을 때가 있다. 처음부터 완벽하려고 해서 그런 것 같다. 하지만 "중요한 것은 코드 방식이 아니라, 프로그램이 작동되도록 하는 것"이다. 우선, 프로그램이 작동되도록 코드를 작성한 후에 하나씩 변경하면 되는 것이다! 부담 갖지 말고, 조급해하지 말고, 강박관념에 사로잡히지 말고, 일단 할 수 있는 것부터 해보자!!!

 

반응형