React에서의 배열 처리



1. 배열 처리 메서드란?

React에서는 배열 데이터를 렌더링하거나 필터링하는 작업이 자주 필요합니다. 배열의 각 요소를 순회하며 특정 작업을 수행하거나, 조건에 따라 배열을 필터링하거나, 배열을 결합하는 등의 작업을 할 수 있습니다.


2. map()

1) map() 이란?

  • map() 메서드는 배열의 각 요소를 변형하여 새로운 배열을 생성하는 데 사용됩니다. 이 메서드는 원본 배열을 수정하지 않으며, 변형된 요소들로 구성된 새로운 배열을 반환합니다.
  • map() 메서드는 배열의 각 요소를 순회하며, 주어진 함수(콜백 함수)를 호출하여 그 반환 값을 새로운 배열의 요소로 사용합니다.


2) map() 의 구조

arr.map(callbackFunction, [thisArg])
  • callbackFunction: 배열의 각 요소를 순회하며 실행할 함수입니다. 이 함수는 세 가지 인수를 가질 수 있습니다.
    • currentValue: 배열의 현재 요소.
    • index: 현재 요소의 인덱스(위치). (선택 사항)
    • array: map()이 호출된 원본 배열. (선택 사항)

[thisArg]: callbackFunction 내부에서 this로 사용할 값을 지정할 수 있습니다. 이 인수를 넣지 않으면 undefined가 기본값으로 설정됩니다.


3) map() 사용 예시

import React from 'react'

export const Base = () => {
  const numbers = [10, 20, 30, 40];

  // map() 함수 사용
  const Items = numbers.map((currentValue, index, array) => {
    console.log(`현재 값: ${currentValue}`);
    console.log(`인덱스: ${index}`);
    console.log(`원본 배열: ${array}`);
    console.log(`-----------------------`);

    return(
     <li key={index}>
         : {currentValue}, 인덱스: {index}, 원본 배열: {array.join(', ')}
     </li>   
    )
  });

  return (
    <div>
        <h1>Map 예시</h1>
        <ul>{Items}</ul>
    </div>
  );
}
  • numbers.map()numbers 배열의 각 요소를 순회하면서, 현재 요소(currentValue), 요소의 인덱스(index), 그리고 원본 배열(array)을 콘솔에 출력합니다.
  • 이 반환 값을 기반으로 새로운 <li> 요소를 생성하고, 이를 배열로 반환합니다. 결과적으로 Items<li> 요소로 구성된 배열이 됩니다.


4) map() 활용

import React, { useState } from 'react'

export default function Alphabet() {
    const [alphabet, setAlphabet] = useState(['b', 'a', 'n', 'a']);

    return (
        <div>
            <h1>Map을 사용한 알파벳 출력</h1>
            <ol>
                {alphabet.map((value, idx) => {
                    return <li key={idx}>{value}</li>
                })}
            </ol>
        </div>
    );
}


5) key 속성에 idx를 사용하는 이유

  • key 속성의 역할: React에서 key 속성은 리스트 항목을 고유하게 식별하기 위해 사용됩니다. key는 리스트 항목이 추가되거나 제거될 때 React가 어떤 항목이 변경되었는지 효율적으로 알아낼 수 있게 도와줍니다.

  • key가 없거나 중복되면, React는 어떤 항목이 변경되었는지 알기 어렵기 때문에 성능이 저하될 수 있으며, 렌더링 이슈가 발생할 수 있습니다.

  • idx를 사용하는 이유: 리스트 항목이 고유한 식별자를 가지고 있지 않은 경우, 배열의 인덱스(idx)를 key로 사용하는 것이 일반적입니다. 인덱스는 배열에서 각 요소의 위치를 나타내므로, 반복문 내에서 각 요소를 고유하게 식별하는 데 유용합니다.

    • 하지만, 인덱스를 key로 사용하는 것은 모든 상황에서 이상적인 것은 아닙니다. 예를 들어, 배열의 요소가 추가되거나 삭제될 때, 인덱스 기반의 key는 재정렬될 수 있습니다. 이런 경우 React가 효율적으로 렌더링을 처리하지 못할 수 있습니다. 따라서 가능한 경우 고유한 식별자(ID 등)를 key로 사용하는 것이 좋습니다.


3. filter()

1) filter() 란?

  • filter() 메서드는 배열의 각 요소를 순회하며, 주어진 조건에 맞는 요소들로 구성된 새로운 배열을 생성하는 데 사용됩니다. 이 메서드 역시 원본 배열을 수정하지 않습니다.
  • 조건에 맞는 요소만을 반환하기 때문에, 배열에서 특정 요소를 제거하거나, 특정 조건에 맞는 요소만을 추출하는 데 유용합니다.


2) filter() 의 구조

arr.filter(callbackFunction, [thisArg])
  • callbackFunction: 배열의 각 요소를 순회하며 실행할 함수입니다. 이 함수는 세 가지 인수를 가질 수 있습니다.
    • currentValue: 배열의 현재 요소.
    • index: 현재 요소의 인덱스(위치). (선택 사항)
    • array: filter()가 호출된 원본 배열. (선택 사항)

[thisArg]: callbackFunction 내부에서 this로 사용할 값을 지정할 수 있습니다. 이 인수를 넣지 않으면 undefined가 기본값으로 설정됩니다.


3) filter() 사용 예시

다음은 filter() 메서드를 사용하여 특정 조건에 맞는 배열 요소만을 추출하는 예시입니다.

import React from 'react'

export const Base = () => {
  let animals = ['dog', 'cat', 'rabbit'];

  let newAnimals = animals.filter((animal) => {
    return animal.length > 3;  // 문자열 길이가 3 초과인 요소만 필터링
  })

  return (
    <div>
        <h1>Filter 예시</h1>
        <ul>{newAnimals.join(', ')}</ul>
    </div>
  );
}
  • animals.filter()animals 배열의 각 요소를 순회하면서, 문자열의 길이가 3 초과인 요소만을 필터링하여 새로운 배열 newAnimals를 만듭니다.
  • 결과적으로 newAnimals 배열에는 길이가 3을 초과하는 rabbit만 포함됩니다.


4) filter() 활용

filter() 메서드는 특정 조건에 맞지 않는 요소를 배열에서 제거하거나, 원하는 조건에 맞는 요소만을 추출하는 데 매우 유용합니다.

import React, { useState } from 'react'

export default function Alphabet() {
    const [alpha, setAlpha] = useState([
        { id: 1, al: `a` },
        { id: 2, al: `p` },
        { id: 3, al: `p` },
        { id: 4, al: `l` },
        { id: 5, al: `e` },
    ]);

    // 글자 삭제
    const deleteAlpha = (targetId) => {
        console.log(targetId);  // 삭제할 요소의 id 출력
        const new

        Alpha = alpha.filter((al) => al.id !== targetId);  // 해당 id를 제외한 새로운 배열 생성 = 삭제한 것과 같은 결과

        setAlpha(newAlpha);  // 새로운 배열로 상태 업데이트
    
    }

    return (
        <div>
            <h1>Filter를 사용한 알파벳 삭제</h1>
            <ol>
                {alpha.map((value) => (
                    <li key={value.id} onDoubleClick={() => deleteAlpha(value.id)}>{value.al}</li>
                ))}
            </ol>
        </div>
    );
}
  • deleteAlpha 함수는 alpha 배열에서 특정 id를 가진 요소를 제거합니다. 이때 filter() 메서드를 사용해 조건에 맞는 요소만을 포함하는 새로운 배열을 생성합니다.
  • 사용자는 리스트 항목을 더블 클릭하여 해당 요소를 삭제할 수 있으며, 삭제된 후 새로운 배열이 상태로 설정됩니다.


4. concat()

1) concat() 란?

  • concat() 메서드는 배열을 결합하거나 새로운 요소를 추가하는 데 사용됩니다. 이 메서드는 기존 배열을 변경하지 않고, 주어진 배열이나 값들을 새로운 배열로 결합하여 반환합니다.
  • 즉, 원본 배열은 그대로 유지되며, 결합된 새로운 배열이 생성됩니다.


2) concat() 사용 예시

import React, { useState } from 'react'

export default function Alphabet() {
    const [alpha, setAlpha] = useState([
        { id: 1, al: `a` },
        { id: 2, al: `p` },
        { id: 3, al: `p` },
        { id: 4, al: `l` },
        { id: 5, al: `e` },
    ]);

    const [inputAlpha, setInputAlpha] = useState('');

    // 글자 추가
    const addAlpha = () => {
        // 입력된 값이 빈 문자열이면 아무 작업도 하지 않음
        if(inputAlpha.trim().length === 0) {
            return;
        }

        // 새로운 알파벳을 기존 배열에 추가하기 위해 concat 사용
        const newAlpha = alpha.concat({
            id: alpha.length + 1,
            al: inputAlpha,
        });

        setAlpha(newAlpha);  // 상태를 업데이트하여 화면에 새 요소가 반영되도록 함
        setInputAlpha('');  // 입력 필드를 초기화
    }

    return (
        <div>
            <h1>Concat을 사용한 알파벳 추가</h1>
            <input 
                type="text" 
                placeholder="알파벳 입력" 
                value={inputAlpha} 
                onChange={(e) => setInputAlpha(e.target.value)}
            />
            <button onClick={addAlpha}>추가</button>
            <ol>
                {alpha.map((value) => (
                    <li key={value.id}>{value.al}</li>
                ))}
            </ol>
        </div>
    );
}
  • concat() 메서드는 alpha 배열에 새로운 요소를 추가하여 새로운 배열을 생성합니다. 원본 배열 alpha는 그대로 유지되며, 새로 추가된 요소가 포함된 새로운 배열 newAlpha가 반환됩니다.
  • 이렇게 생성된 새로운 배열로 상태를 업데이트함으로써, React는 UI를 재렌더링하여 새 요소가 화면에 반영되도록 합니다.


5. forEach, map, concat의 차이점

forEach, map, concat은 배열을 처리할 때 자주 사용되는 메서드이지만, 그 목적과 결과는 다릅니다.

1) forEach

  • 배열의 각 요소에 대해 주어진 함수를 실행하는 것이 목적입니다. 반환값이 없는 함수입니다.
  • forEach()는 단순히 배열을 순회하며 각 요소에 대해 어떤 작업을 수행하는 데 사용됩니다.
  • 새로운 배열을 반환하지 않으며, 원본 배열 자체도 변경하지 않습니다.

2) map

  • 배열의 각 요소를 변형하여 새로운 배열을 생성하는 것이 목적입니다.
  • map()은 변형된 요소들로 구성된 새로운 배열을 반환하며, 원본 배열은 변경되지 않습니다.

3) concat

  • 배열을 결합하거나 새로운 요소를 추가하는 것이 목적입니다.
  • concat()은 기존 배열을 변경하지 않고, 주어진 배열이나 값들을 결합하여 새로운 배열을 생성합니다.

4) 비교 예시

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

// forEach 사용 예시
numbers.forEach(number => {
    console.log(number);
});

// map 사용 예시
const double = numbers.map((number) => number * 2);
console.log(double);  // [2, 4, 6, 8, 10]

// concat 사용 예시
const extendedNumbers = numbers.concat([6, 7]);
console.log(extendedNumbers);  // [1, 2, 3, 4, 5, 6, 7]
  • forEach: forEach는 배열의 각 요소를 순회하면서 주어진 함수를 실행합니다. 하지만 새로운 배열을 반환하지 않습니다.

  • map: 배열의 각 요소를 변형한 결과를 새로운 배열로 반환합니다. 원본 배열은 그대로 유지됩니다.

  • concat: 배열을 결합하여 새로운 배열을 반환합니다. 원본 배열은 변경되지 않으며, 결합된 요소들로 구성된 새로운 배열이 생성됩니다.


6. mapfilter를 동시에 사용하는 경우

mapfilter를 함께 사용하는 경우도 자주 있습니다. 특정 조건에 맞는 요소만 변형하여 새로운 배열을 생성할 때 유용합니다.

1) mapfilter를 함께 사용하는 예시

import React from 'react'

export const MapFilterExample = () => {
  const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

  const evenDoubled = numbers
    .filter((number) => number % 2 === 0)  // 짝수만 필터링
    .map((number) => number * 2);  // 짝수의 값을 2배로 변형

  return (
    <div>
        <h1>Map과 Filter를 함께 사용한 예시</h1>
        <ul>
            {evenDoubled.map((value, idx) => (
                <li key={idx}>{value}</li>
            ))}
        </ul>
    </div>
  );
}
  • 먼저, numbers 배열에서 짝수만 필터링합니다. filter() 메서드를 사용하여 짝수(number % 2 === 0)만을 포함하는 새로운 배열을 생성합니다.
  • 그 후, map() 메서드를 사용하여 필터링된 짝수의 값을 2배로 변형합니다. 이 변형된 값을 가진 새로운 배열 evenDoubled가 생성됩니다.
  • 결과: 결과적으로 [4, 8, 12, 16, 20]이라는 배열이 생성되며, 이를 <li> 요소로 렌더링합니다.