프론트엔드 개발을 하다 보면 중복된 데이터를 처리하거나 키-값 쌍으로 데이터를 관리해야 하는 경우가 많이 있습니다. 특히 React로 개발할 때 상태 관리나 캐싱을 구현할 때 이러한 상황을 자주 마주치게 됩니다. 이번에는 제가 실제 프로젝트에서 Set과 Map을 활용한 경험을 바탕으로 이 두 자료구조의 특징과 활용법을 공유하려고 합니다.
Set: 중복 없는 유니크한 값들의 집합
기본 사용법
Set은 중복을 허용하지 않는 값들의 집합입니다. 배열과 비슷하지만, 같은 값을 여러 번 포함할 수 없다는 특징이 있습니다.
// Set 생성
const uniqueNumbers = new Set();
// 값 추가
uniqueNumbers.add(1);
uniqueNumbers.add(2);
uniqueNumbers.add(1); // 중복된 값은 무시됨
console.log(uniqueNumbers); // Set(2) {1, 2}
✨ 실제 활용 예시: React에서 중복 제거하기
최근 프로젝트에서 API로 받아온 데이터에서 중복된 태그들을 제거해야 하는 상황이 있었습니다:
const PostTags = ({ tags }) => {
// 중복된 태그 제거 및 정렬
const uniqueTags = Array.from(new Set(tags)).sort();
return (
<div className="tags-container">
{uniqueTags.map(tag => (
<span key={tag} className="tag">
{tag}
</span>
))}
</div>
);
};
Map: 키-값 쌍으로 데이터 관리하기
기본 사용법
Map은 Object와 비슷하지만, 키로 모든 타입의 값을 사용할 수 있다는 장점이 있습니다.
// Map 생성
const userRoles = new Map();
// 값 설정
userRoles.set('user123', 'admin');
userRoles.set('user456', 'editor');
// 값 가져오기
console.log(userRoles.get('user123')); // 'admin'
‼️ Object vs Map: 언제 무엇을 써야 할까?
Map을 써야 하는 경우:
- 키가 문자열/심볼이 아닌 다른 타입일 때
- 데이터를 자주 추가/삭제해야 할 때
- 순회가 빈번할 때
Object를 써야 하는 경우:
- JSON으로 직렬화해야 할 때
- 간단한 키-값 저장소가 필요할 때
실제 활용 예시: 캐싱 구현하기
const memoizedCalculator = () => {
const cache = new Map();
return (n) => {
if (cache.has(n)) {
console.log('캐시된 결과 사용');
return cache.get(n);
}
const result = /* 복잡한 계산 */;
cache.set(n, result);
return result;
};
};
🔍 Set의 주요 메소드들
Set 객체는 데이터를 다루기 위한 다양한 메소드를 제공합니다. 이러한 메소드들을 잘 활용하면 데이터를 더욱 효율적으로 관리할 수 있습니다.
데이터 추가/삭제 메소드
const mySet = new Set();
// add(): 값 추가
mySet.add('apple'); // Set(1) {'apple'}
mySet.add('banana'); // Set(2) {'apple', 'banana'}
// delete(): 값 삭제 - 성공하면 true, 실패하면 false 반환
console.log(mySet.delete('apple')); // true
console.log(mySet.delete('orange')); // false
// clear(): 모든 값 삭제
mySet.clear(); // Set(0) {}
데이터 확인 메소드
const mySet = new Set(['a', 'b', 'c']);
// has(): 값 존재 여부 확인
console.log(mySet.has('a')); // true
console.log(mySet.has('d')); // false
// size: 저장된 값의 개수 (프로퍼티)
console.log(mySet.size); // 3
‼️ Pro Tip: Set의 has() 메소드는 배열의 includes()보다 성능이 좋습니다. 중복 체크가 빈번한 경우 Set을 고려해보세요!
🔍 Map의 주요 메소드들
Map은 키-값 쌍을 다루는데 특화된 메소드들을 제공합니다. Object와 비슷하지만 더 다양한 기능을 제공합니다.
데이터 추가/수정/삭제 메소드
const userMap = new Map();
// set(): 키-값 쌍 추가 또는 수정
userMap.set('user1', { name: 'John', role: 'admin' });
userMap.set('user2', { name: 'Jane', role: 'editor' });
// delete(): 키-값 쌍 삭제
console.log(userMap.delete('user1')); // true
// clear(): 모든 키-값 쌍 삭제
userMap.clear();
데이터 접근/확인 메소드
const userMap = new Map([
['user1', { name: 'John' }],
['user2', { name: 'Jane' }]
]);
// get(): 키로 값 가져오기
console.log(userMap.get('user1')); // { name: 'John' }
// has(): 키 존재 여부 확인
console.log(userMap.has('user1')); // true
// size: 저장된 키-값 쌍의 개수 (프로퍼티)
console.log(userMap.size); // 2
순회 메소드
const fruitPrices = new Map([
['apple', 1000],
['banana', 1500],
['orange', 2000]
]);
// keys(): 키들의 이터레이터 반환
for (const fruit of fruitPrices.keys()) {
console.log(fruit); // apple, banana, orange
}
// values(): 값들의 이터레이터 반환
for (const price of fruitPrices.values()) {
console.log(price); // 1000, 1500, 2000
}
// entries(): [키, 값] 쌍의 이터레이터 반환
for (const [fruit, price] of fruitPrices.entries()) {
console.log(`${fruit}: ${price}원`);
}
✨ 실용적인 활용 예시: API 응답 캐싱
const apiCache = new Map();
async function fetchUserData(userId) {
// 캐시 확인
if (apiCache.has(userId)) {
console.log('캐시된 데이터 사용');
return apiCache.get(userId);
}
// API 호출
const response = await fetch(`/api/users/${userId}`);
const userData = await response.json();
// 캐시 저장 (5분 후 자동 삭제)
apiCache.set(userId, userData);
setTimeout(() => {
apiCache.delete(userId);
}, 5 * 60 * 1000);
return userData;
}
성능 고려사항
- Set: O(1) 시간 복잡도로 값 존재 여부 확인 가능
- Map: O(1) 시간 복잡도로 키를 통한 값 접근 가능
- 둘 다 메모리 사용량은 저장된 항목 수에 비례
마치며
Set과 Map은 각각의 용도에 맞게 잘 활용하면 코드의 가독성과 성능을 모두 개선할 수 있는 강력한 도구입니다. 특히 React와 같은 프론트엔드 개발에서 상태 관리나 데이터 처리에 매우 유용하게 사용됩니다. 앞으로 프로젝트를 진행하시면서 이 자료구조들을 적절히 활용해보시기 바랍니다.
'개발일지' 카테고리의 다른 글
Java Stream API 마스터하기: 함수형 프로그래밍의 강력함 🌊 (0) | 2024.12.10 |
---|---|
Java String Pool의 내부 동작 원리: 메모리 최적화와 문자열 관리 심층 분석 📘 (0) | 2024.12.10 |
자바스크립트 함수 완벽 가이드: 함수 표현식부터 모던 자바스크립트까지 (0) | 2024.11.30 |
자바스크립트 화살표 함수 vs 일반 함수: 당신이 알아야 할 모든 것 (0) | 2024.11.30 |
[TIL] 자바스크립트 옵셔널 체이닝 연산자(?.) 완벽 가이드 (0) | 2024.11.28 |