셋(Set)은 수학의 '집합' 개념을 프로그래밍으로 옮긴 자료구조로, 중복을 허용하지 않고 고유한 값만 저장한다는 점이 가장 큰 특징입니다. 자바스크립트는 ES6부터 내장 Set 객체를 제공하지만, 셋이 내부적으로 어떻게 동작하는지 깊이 이해하려면 직접 구현해 보는 것이 가장 좋은 학습 방법입니다.
아래는 일반 객체를 내부 저장소로 활용해 셋의 핵심 기능을 모두 담은 MySet 클래스의 전체 구현 코드입니다.
MySet 클래스 전체 구현
class MySet {
constructor() {
this.container = {};
}
display() {
console.log(this.container);
}
has(val) {
return this.container.hasOwnProperty(val);
}
add(val) {
if (!this.has(val)) {
this.container[val] = val;
return true;
}
return false;
}
delete(val) {
if (this.has(val)) {
delete this.container[val];
return true;
}
return false;
}
clear() {
this.container = {};
}
forEach(callback) {
for (let prop in this.container) {
callback(prop);
}
}
static union(s1, s2) {
if (!(s1 instanceof MySet) || !(s2 instanceof MySet)) {
console.log('주어진 객체는 MySet 타입이 아닙니다');
return null;
}
const newSet = new MySet();
s1.forEach(elem => newSet.add(elem));
s2.forEach(elem => newSet.add(elem));
return newSet;
}
static difference(s1, s2) {
if (!(s1 instanceof MySet) || !(s2 instanceof MySet)) {
console.log('주어진 객체는 MySet 타입이 아닙니다');
return null;
}
const newSet = new MySet();
s1.forEach(elem => newSet.add(elem));
s2.forEach(elem => newSet.delete(elem));
return newSet;
}
}주요 메서드 살펴보기
constructor() – 생성자
인스턴스가 생성될 때 내부 저장소 역할을 할 빈 객체 this.container를 초기화합니다. 값을 객체의 키(key)로 저장하기 때문에 같은 키는 다시 생기지 않으므로, 중복 추가가 자연스럽게 차단됩니다.
has(val) – 요소 존재 여부 확인
hasOwnProperty()를 사용해 특정 값이 셋에 들어 있는지 검사합니다. 값이 존재하면 true, 없으면 false를 반환합니다.
add(val) – 요소 추가
추가하려는 값이 아직 존재하지 않을 때만 컨테이너에 저장하고 true를 반환합니다. 이미 있는 값이라면 아무 작업 없이 false를 반환해 중복을 방지합니다.
delete(val) – 요소 삭제
값이 존재하면 해당 키를 삭제하고 true를 반환하며, 존재하지 않으면 false를 반환합니다.
clear() – 전체 비우기
내부 컨테이너를 새 빈 객체로 교체해 셋의 모든 요소를 한 번에 제거합니다.
forEach(callback) – 요소 순회
for...in 반복문으로 컨테이너의 각 키를 순회하며, 전달받은 콜백 함수에 요소를 하나씩 넘겨줍니다. 참고로 객체의 키는 문자열로 관리되므로 숫자 값도 문자열 형태의 키로 저장됩니다.
static union(s1, s2) – 합집합
두 셋에 있는 모든 요소를 합친 새로운 셋을 반환합니다. 인자로 받은 객체가 MySet 타입이 아니면 안내 메시지를 출력하고 null을 반환합니다.
static difference(s1, s2) – 차집합
s1의 모든 요소를 새 셋에 복사한 뒤, s2에도 포함된 요소를 제거하여 's1에는 있지만 s2에는 없는' 요소만 남긴 셋을 반환합니다.
사용 예제
const setA = new MySet();
setA.add(1);
setA.add(2);
setA.add(3);
const setB = new MySet();
setB.add(3);
setB.add(4);
console.log(MySet.union(setA, setB));
// { '1': 1, '2': 2, '3': 3, '4': 4 }
console.log(MySet.difference(setA, setB));
// { '1': 1, '2': 2 }주의: instanceof 연산자 우선순위
일부 예제에서 !s1 instanceof MySet처럼 작성된 코드를 볼 수 있습니다. 그러나 ! 연산자가 instanceof보다 먼저 적용되어 (!s1) instanceof MySet으로 해석되므로 의도대로 동작하지 않습니다. 반드시 아래처럼 괄호로 묶어야 합니다.
if (!(s1 instanceof MySet) || !(s2 instanceof MySet)) { ... }이처럼 MySet 클래스는 내장 Set의 핵심 동작, 즉 중복 방지, 추가·삭제·순회, 합집합·차집합 연산을 간결한 코드로 재현해 줍니다. 자료구조 학습이나 코딩 면접 준비에도 유용하게 활용할 수 있습니다.