본문 바로가기
Javascript 데이터 구조 & 알고리즘 공부

Set 자료형에 중복되는 원소가 나타날 수 있을까?

by cuziam 2023. 7. 3.

원칙적으로 말하면 불가능하다. 이는 누구나 아는 사실이다. Set은 집합을 나타내기 위한 자료형이기 때문에, 중복값이 나타나면 안된다. 하지만 중복되는 원소가 나타나는 현상을 발견했기 때문에 이 글을 찾아왔을 것 같다.

 

Set에 중복이 나타나는 상황은 언제일까?

이런 현상은 배열이나 객체와 같은 참조타입 데이터의 값을 Set에 넣을 때 발생한다. 이렇게만 말하면 잘 감이 안 잡히기 때문에 바로 예시를 들어보자.

const set = new Set();

const obj1 = { key: 'value' };
const obj2 = { key: 'value' };

set.add(obj1);
set.add(obj2); // obj1과 obj2는 값은 동일하지만 다른 객체 참조

console.log(set); // Set { { key: 'value' }, { key: 'value' } }
console.log(set.size); // 2

obj1과 obj2는 동일한 내용의 프로퍼티를 가지고 있다. 이 때 obj1과 obj2를 set에 추가하면 set에 동일한 원소가 나타난다.

const array1 = [1, 2, 3];
const array2 = [1, 2, 3];
const array3 = array1;

const set = new Set();

set.add(array1);
set.add(array2);
set.add(array3);

console.log(set); // Set { [ 1, 2, 3 ], [ 1, 2, 3 ] }
console.log(set.size); // 2

배열의 경우에도 동일한 상황이 발생한다. array1과 array2가 다른 배열이기 때문에 set에 넣을 수 있다. 한편 array3은 array1과 동일한 배열을 참조하기 때문에 array3의 값은 set에 넣어지지 않는다.

 

왜 이런 현상이 발생할까?

참조 타입과 값 타입에 대한 이해가 있다면 빠르게 이해할 수 있다. 우리가 데이터들은 참조타입과 값 타입 둘 중 하나의 형태로 정해진다.

 

참조 타입: 어떤 데이터의 주소를 저장. ex)객체, 배열

값 타입: 어떤 데이터의 값을 직접적으로 저장. ex) 원시 타입 자료형(숫자, 문자열, 불리언, null, undefined, Symbol)

 

위의 예시에서 obj1과 obj2, 그리고 array1과 array2는 참조타입이며 각 변수는 고유한 주소를 저장한다. Set은 이 주소들을 해쉬테이블을 이용하여 저장한다. 그래서 Set내부에 '동일한 것들이 저장되어 있는 것처럼' 보이는 것이다.

 

예를 들어 obj1이 1234, obj 2341 이라는 주소를 가지고 있다고 하면 Set 내부적으로는 {1234,2341}을 저장한 셈이다. 하지만 주소 1234, 2341이 가리키는 값들은 동일한 내용이기 때문에 { { key: 'value' }, { key: 'value' } }와 같이 저장되는 것이다.

 

 

최종 결론: Set에 동일한 내용을 가진 객체나 원소를 넣으면, 중복 원소라도 넣을 수 있다. 하지만 내부적으로 살펴보면 서로 다른 주소를 넣는 것이기 때문에 실제로 중복되는 것을 넣는 것은 아니다.