[SeSACx코딩온] map & filter
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. map
과 filter
를 동시에 사용하는 경우
map
과 filter
를 함께 사용하는 경우도 자주 있습니다. 특정 조건에 맞는 요소만 변형하여 새로운 배열을 생성할 때 유용합니다.
1) map
과 filter
를 함께 사용하는 예시
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>
요소로 렌더링합니다.