Mastering JavaScript Set Object for Unique Data Management

자바스크립트 Set 객체를 마스터하여 중복 없는 데이터 관리를 효율적으로 해보세요.

자바스크립트 개발에서 데이터를 다룰 때 중복 값을 제거하고 고유한 값들의 집합을 관리해야 할 때가 많습니다. Set 객체는 이러한 요구사항을 간결하고 효율적으로 해결해주는 강력한 내장 객체입니다. 이 가이드에서는 Set 객체의 기본 사용법부터 고급 활용 사례까지 자세히 다루어, 여러분이 실무에서 Set을 능숙하게 사용할 수 있도록 돕습니다.

자바스크립트 Set 객체란?

자바스크립트의 Set 객체고유한 값들의 컬렉션을 저장하는 자료구조입니다. 여기서 '고유하다'는 것은 Set 내부에 같은 값을 두 번 이상 저장할 수 없다는 의미입니다. 배열과 유사하게 여러 값을 담을 수 있지만, Set은 중복을 허용하지 않는다는 결정적인 차이가 있습니다.

Set은 ES6(ECMAScript 2015)에서 도입되었으며, 주로 배열에서 중복을 제거하거나, 값의 존재 여부를 빠르게 확인해야 할 때 유용하게 사용됩니다. Set은 값의 순서가 중요하지 않으며, 삽입된 순서대로 요소를 반복할 수 있는 이터러블(Iterable) 객체입니다.

Set의 핵심은 모든 요소가 유일하다는 점입니다. 이를 통해 데이터의 무결성을 쉽게 유지할 수 있습니다.

Set은 원시 값(숫자, 문자열, 불리언, null, undefined, Symbol)뿐만 아니라 객체 참조도 저장할 수 있습니다. 객체의 경우, 참조가 동일해야 같은 값으로 간주됩니다. 즉, 내용이 같더라도 다른 메모리 주소를 가진 두 개의 객체는 Set에서 서로 다른 요소로 처리됩니다.


Set vs. 배열 (Array)

Set과 배열은 모두 값들의 컬렉션을 저장하지만, 몇 가지 중요한 차이점이 있습니다.

  • 중복 허용 여부: 배열은 중복 값을 허용하지만, Set은 허용하지 않습니다.
  • 순서: 배열은 요소의 순서가 보장되며 인덱스를 통해 접근하지만, Set은 순서가 중요하지 않으며 인덱스를 통한 직접 접근은 불가능합니다. (삽입 순서는 유지됩니다.)
  • 성능: Set은 값의 존재 여부를 확인하는 has() 메서드의 성능이 일반적으로 배열의 includes() 메서드보다 빠릅니다. 이는 Set이 내부적으로 해시 테이블과 유사한 구조를 사용하기 때문입니다.

JavaScript Set vs Array comparison table

Set 객체 생성 및 초기화

Set 객체를 생성하는 방법은 매우 간단합니다. new Set() 생성자를 사용하면 됩니다.

빈 Set 생성

가장 기본적인 방법으로, 아무런 요소도 없는 빈 Set을 생성합니다.

코드 설명: 빈 Set 생성

const mySet = new Set();
console.log(mySet); // Set(0) {}

이터러블(Iterable) 객체로 초기화

Set 생성자는 배열과 같은 이터러블 객체를 인수로 받아 Set을 초기화할 수 있습니다. 이때 이터러블 객체 내의 중복 값은 자동으로 제거됩니다.

코드 설명: 배열로 Set 초기화

const initialArray = [1, 2, 3, 2, 1];
const mySetWithArray = new Set(initialArray);
console.log(mySetWithArray); // Set(3) {1, 2, 3}

const initialString = "hello";
const mySetWithString = new Set(initialString);
console.log(mySetWithString); // Set(4) {'h', 'e', 'l', 'o'}

Set 생성자에 이터러블 객체를 전달하면 중복 값이 자동으로 제거되어 초기화됩니다.

Data flow from duplicate list to unique Set

Set 객체의 주요 메서드

Set 객체는 요소를 추가, 삭제, 확인하고 크기를 얻는 등 다양한 작업을 수행할 수 있는 유용한 메서드들을 제공합니다.

add(value)

Set에 새로운 값을 추가합니다. 만약 동일한 값이 이미 Set에 존재한다면, 아무런 변경 없이 Set이 반환됩니다. 체이닝(chaining)이 가능합니다.

코드 설명: add() 메서드

const fruits = new Set();
fruits.add('apple');
fruits.add('banana');
fruits.add('apple'); // 중복 값은 추가되지 않음

console.log(fruits); // Set(2) {'apple', 'banana'}
console.log(fruits.size); // 2

delete(value)

Set에서 특정 값을 제거합니다. 값이 성공적으로 제거되면 true를 반환하고, 값이 Set에 없으면 false를 반환합니다.

코드 설명: delete() 메서드

const numbers = new Set([1, 2, 3, 4]);
console.log(numbers.delete(3)); // true (3이 제거됨)
console.log(numbers); // Set(3) {1, 2, 4}
console.log(numbers.delete(5)); // false (5는 Set에 없음)

has(value)

Set에 특정 값이 존재하는지 확인합니다. 존재하면 true를, 없으면 false를 반환합니다. 이 메서드는 Set의 주요 강점 중 하나로, 매우 빠른 검색 성능을 제공합니다.

코드 설명: has() 메서드

const fruits = new Set(['apple', 'banana', 'orange']);
console.log(fruits.has('apple')); // true
console.log(fruits.has('grape')); // false

값의 존재 여부 확인에는 항상 has() 메서드를 사용하는 것이 효율적입니다.

clear()

Set의 모든 요소를 제거하여 Set을 비웁니다. 반환 값은 undefined입니다.

코드 설명: clear() 메서드

const colors = new Set(['red', 'green', 'blue']);
console.log(colors.size); // 3
colors.clear();
console.log(colors); // Set(0) {}
console.log(colors.size); // 0

size 프로퍼티

Set에 포함된 요소의 개수를 반환합니다. 메서드가 아닌 프로퍼티이므로 괄호 없이 사용합니다.

코드 설명: size 프로퍼티

const letters = new Set(['a', 'b', 'c']);
console.log(letters.size); // 3

letters.add('d');
console.log(letters.size); // 4

letters.delete('a');
console.log(letters.size); // 3

Set의 반복 (Iteration)

Set은 이터러블 객체이므로 for...of 루프나 forEach() 메서드를 사용하여 요소를 반복할 수 있습니다.

코드 설명: Set 반복

const cities = new Set(['Seoul', 'Busan', 'Jeju']);

console.log("--- using for...of ---");
for (const city of cities) {
    console.log(city);
}
// Output:
// Seoul
// Busan
// Jeju

console.log("--- using forEach ---");
cities.forEach((city, cityAgain, set) => {
    // forEach의 콜백 함수는 (value, key, set) 형태인데,
    // Set에서는 value와 key가 동일합니다.
    console.log(`${city} (key: ${cityAgain})`);
});
// Output:
// Seoul (key: Seoul)
// Busan (key: Busan)
// Jeju (key: Jeju)

JavaScript Set iteration flowchart

Set과 배열, 객체 간의 변환

Set은 다른 자료구조와 상호 변환될 수 있습니다. 특히 배열과의 변환은 중복 제거와 같은 작업에서 매우 유용하게 사용됩니다.

Set을 배열로 변환

Set은 이터러블 객체이므로, 스프레드 문법(...)이나 Array.from() 메서드를 사용하여 배열로 쉽게 변환할 수 있습니다.

코드 설명: Set을 배열로 변환

const uniqueNumbers = new Set([10, 20, 30, 20, 10]);

// 1. 스프레드 문법 사용
const numbersArray1 = [...uniqueNumbers];
console.log(numbersArray1); // [10, 20, 30]

// 2. Array.from() 사용
const numbersArray2 = Array.from(uniqueNumbers);
console.log(numbersArray2); // [10, 20, 30]

배열을 Set으로 변환 (중복 제거)

배열의 중복을 제거하는 가장 흔하고 효과적인 방법은 배열을 Set으로 변환한 다음, 다시 Set을 배열로 변환하는 것입니다.

코드 설명: 배열 중복 제거

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

const uniqueNumbersArray = [...new Set(numbersWithDuplicates)];
console.log(uniqueNumbersArray); // [1, 5, 2, 3, 4]

배열의 중복 제거는 Set을 활용하는 가장 대표적인 시나리오 중 하나입니다.

실제 활용 사례: 중복 제거 및 집합 연산

Set은 단순히 중복을 제거하는 것을 넘어, 수학적 집합 연산을 구현하는 데에도 매우 효과적입니다. 합집합, 교집합, 차집합 등을 Set을 이용해 구현할 수 있습니다.

합집합 (Union)

두 Set의 모든 고유한 요소를 포함하는 새로운 Set을 만듭니다. 스프레드 문법을 사용하여 두 Set을 합쳐 새로운 Set을 생성하면 됩니다.

코드 설명: 합집합

const setA = new Set([1, 2, 3]);
const setB = new Set([3, 4, 5]);

const union = new Set([...setA, ...setB]);
console.log(union); // Set(5) {1, 2, 3, 4, 5}

교집합 (Intersection)

두 Set에 공통으로 존재하는 요소를 포함하는 새로운 Set을 만듭니다. 한 Set의 요소를 순회하면서 다른 Set에 해당 요소가 has() 메서드로 존재하는지 확인하여 구현할 수 있습니다.

코드 설명: 교집합

const setA = new Set([1, 2, 3, 4]);
const setB = new Set([3, 4, 5, 6]);

const intersection = new Set([...setA].filter(x => setB.has(x)));
console.log(intersection); // Set(2) {3, 4}

차집합 (Difference)

한 Set에는 존재하지만 다른 Set에는 존재하지 않는 요소를 포함하는 새로운 Set을 만듭니다. 교집합과 유사하게 filter()has()를 조합하여 구현할 수 있습니다.

코드 설명: 차집합

const setA = new Set([1, 2, 3, 4]);
const setB = new Set([3, 4, 5, 6]);

const difference = new Set([...setA].filter(x => !setB.has(x)));
console.log(difference); // Set(2) {1, 2}

Set operations Venn diagram

Set 객체 사용 시 주의사항

Set은 강력하지만, 몇 가지 주의할 점이 있습니다. 특히 객체 비교와 관련된 부분에서 예상치 못한 결과가 나올 수 있습니다.

객체 비교의 한계

Set은 원시 값에 대해서는 값으로 비교하지만, 객체에 대해서는 참조(reference)로 비교합니다. 이는 두 객체가 동일한 속성과 값을 가지고 있더라도, 서로 다른 메모리 주소를 가리키면 Set에서는 다른 객체로 간주한다는 의미입니다.

코드 설명: 객체 비교

const obj1 = { id: 1 };
const obj2 = { id: 1 };
const obj3 = obj1; // obj1과 동일한 참조

const objectSet = new Set();
objectSet.add(obj1);
objectSet.add(obj2); // obj2는 obj1과 내용이 같지만 다른 객체이므로 추가됨
objectSet.add(obj3); // obj3은 obj1과 동일한 참조이므로 추가되지 않음

console.log(objectSet); // Set(2) {{id: 1}, {id: 1}}
console.log(objectSet.size); // 2

이 점은 Set을 사용하여 객체를 저장할 때 반드시 유의해야 합니다. 만약 객체의 내용 기반으로 중복을 제거하고 싶다면, 객체를 JSON 문자열로 변환하거나 고유한 ID를 기반으로 직접 비교 로직을 구현해야 할 수 있습니다.

JavaScript Set object reference comparison

NaN의 특이점

자바스크립트에서 NaN(Not-a-Number)은 자신과 같지 않은 유일한 값입니다 (NaN === NaNfalse). 그러나 Set에서는 NaN을 고유한 값으로 취급하여 오직 하나만 저장할 수 있습니다.

코드 설명: NaN 처리

const nanSet = new Set();
nanSet.add(NaN);
nanSet.add(NaN); // 추가되지 않음

console.log(nanSet); // Set(1) {NaN}
console.log(nanSet.size); // 1

Set은 NaN고유한 값으로 처리하는 예외적인 동작을 합니다.

마무리

자바스크립트 Set 객체는 중복 없는 고유한 값들의 컬렉션을 효율적으로 관리해야 할 때 빛을 발하는 자료구조입니다. 배열의 중복 제거부터 복잡한 집합 연산까지, Set은 코드를 간결하고 성능 좋게 만드는 데 크게 기여할 수 있습니다. 2026년 현재, 모던 자바스크립트 개발에서 Set은 필수적인 도구로 자리매김했습니다.

이 가이드를 통해 Set의 기본 개념과 주요 메서드, 그리고 실용적인 활용 사례들을 충분히 익히셨기를 바랍니다. 여러분의 자바스크립트 코드에 Set을 적극적으로 활용하여 더욱 견고하고 효율적인 애플리케이션을 만들어나가시길 응원합니다.


이제 Set으로 중복 걱정 없이 코딩하세요!

Set 객체에 대한 더 궁금한 점이 있다면 언제든지 댓글로 문의해주세요. Kwonglish는 여러분의 효율적인 개발을 돕기 위해 항상 노력하겠습니다.