안녕하세요 ~ 오늘은 자바스크립트에서 배열처럼 사용하는 set에 대하여 알아보려고 합니다. 간략하게 set은 무엇이고 배열과의 차이점은 무엇인지 알아볼께요!


# set은 무엇인가?
그럼 가장 먼저 set은 무엇일까요? 자바스크립트에서 set은 ES 6에서 처음 소개되었으며 새로운 형태의 데이터 타입으로 사용되는 객체입니다.

@ 배열처럼 사용하는 set
자바스크립트에서 set을 사용하다 보면 배열과 비교되고는 합니다. 왜 그럴까요? 실제로 사용해보면 배열과 크게 다르지 않기 때문입니다. 문법의 차이점과 동일한 값을 가지지 않는다는 점만 제외한다면 사실 set이 반드시 필요한지 의문을 가질 수 있습니다.

이런 이유로 set을 사용하지 않더라도 크게 불편하거나 차이를 찾기 어렵습니다. 하지만 set만의 장점도 반드시 존재합니다. 바로 유니크(unique)한 값만을 가진다는 set의 특징입니다. set은 배열처럼 사용하지만 set에 사용되는 모든 값은 고유의 값만 허용됩니다. 이 점은 배열과 set의 가장 큰 차이점이니다. 그래서 set을 사용할 경우 특히 고유한 데이터 값을 가져야 하는 경우에 사용하는 것에 큰 이점이 있습니다.

그럼 실제로 set을 어떻게 사용하는지 알아봅니다.


! set을 사용하는 방법
다음으로 자바스크립트에서 set을 사용하는 문법을 알아봅니다. set을 사용하려면 먼저 new 키워드와 함께 생성자 Set을 사용하며 이 경우 set 객체를 반환합니다.

const mySet = new Set()


위에서 mySet은 몇 가지 프로퍼티와 메소드를 사용할 수 있습니다. 대표적으로 사용되는 몇 가지를 알아보죠. 먼저 프로퍼티 정보입니다.

* Set Properties
size // Set이 가진 데이터의 크기를 반환. 배열의 length와 같음

다음으로 메소드 정보입니다.

* Set Methods
add // 새로운 값을 추가함. 배열의 push() 역할
has // 특정 값을 가졌는지 여부를 반환함. 배열의 includes() 역할
delete // 특정의 값을 제거. 배열의 pop()과 비슷. Boolean 반환
clear // set 내부를 비움. 모든 값 제거
values // set의 iterator인 순환객체를 반환함
entries // 모든 값을 순환함
forEach // 모든 값을 순환하며 함수를 실행함
keys // values의 별칭(alias)으로 사용


! set을 사용한 다양한 예제
먼저 길이를 얻을 수 있는 프로퍼티 size의 예제입니다.
mySet = new Set([1, 2, 3])
mySet.size

// Result
3

이제 add()를 사용하여 새로운 값을 추가할 수 있습니다.
mySet = new Set()
mySet.add(1)
mySet.add(2)

// Result
{ 1, 2 }

참고로 아래와 같이 체이닝(Chaining) 방식으로 add()가 가능합니다.
mySet = new Set()
mySet.add(1).add(2).add(3)

// Result
{ 1, 2, 3 }

값이 존재하는지 알아보기 위해서 has()를 사용합니다. 배열의 includes()와 동일합니다. 실제로 1이 있으므로 true를 반환하겠죠
mySet.has(1)

// Result
true

이번에는 mySet의 값을 제거하려고 합니다. 삭제를 위해서 delete()를 사용하겠습니다.
mySet.delete(1)
// true { 2, 3 }

mySet.delete(4)
// false { 2, 3 }

삭제되면서 동시에 true를 반환합니다. 위에서 4의 값은 없으므로 삭제되지 않으며 이 경우 false를 반환하게됩니다. 다음으로 모든 값을 비우기 위해서 clear()를 사용할 수 있습니다.
mySet.clear()
// undefined {}

삭제와 동시에 undefined를 반환하게 됩니다. 다음으로 forEach()입니다. 만약 1부터 10까지의 set값을 만들고 이를 순환하며 함수를 실행할 때 아래와 같이 코드를 작성할 수 있습니다.
mySet = new Set([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
myArray = []
mySet.forEach((i) => { if (i % 2 === 0) { myArray.push(i) } })

// Result myArray
[2, 4, 6, 8, 10]

여기까지 자주 사용되는 메소드를 알아봤습니다. 아래부터는 이 외에 set을 사용하는데 알아두면 좋은 내용 몇 가지 입니다.


@ set 문자열(String)에 적용하기
set은 배열이 아닌 유사 배열값(문자열 또는 노드)에 사용하기도 합니다. 만약 특정 문자열에 set을 적용하면 어떻게 되는지 확인해보겠습니다.
mySet = new Set('abcde')

// Result
Set {'a', 'b', 'c', 'd', 'e'}

문자열 abcde가 각각 나뉘어 값을 가지게 됩니다.

참고로 배열도 비슷하게 만들 수는 있습니다. 다만 함수 split()을 사용해야 합니다.
mySet = 'abcde'.split('')

// Result
['a', 'b', 'c', 'd', 'e']


@ set 객체의 타입 확인해보기
set으로 반환된 인스턴스의 타입을 확인해보겠습니다. 객체로 나오게 되겠죠. 실제로 해봐도 object를 반환합니다.
typeof mySet

// Result
'object'

set 역시 객체임을 확인할 수 있습니다. 배열 역시 타입은 object를 반환하므로 이 부분은 동일하네요. 정확한 타입을 비교할 경우 instanceOf를 사용할 수 있겠습니다.
mySet instanceof Object
// true

mySet instanceof Array
// false

mySet instanceof Set
// true

Object와 Set 객체를 상속 받았다는 것을 알 수 있습니다. Array를 제외하고는 true를 반환하죠.


! 배열을 set으로 변환하는 방법
set은 고유한 값만을 가지기 때문에 배열을 set으로 변환할 경우 set의 값들은 고유한 값들만 남게 됩니다. 이런 이유로 배열을 set으로 변환하여 사용 후 다시 배열로 변환하기도 합니다. 이 경우 고유한 값만 가질 수 있겠죠!

예를들어 만약 배열 myArray를 mySet으로 변경할 경우 아래와 같습니다.
myArray = [0, 0, 1, 1, 2, 2]
mySet = new Set(myArray)

// Result
{ 0, 1, 2 }

// mySet.size
3


[기타] set이 만들어진 이유는 무엇일까?
배열(Array)과 딱히 차이점을 모를 수 있는 set이 꼭 필요할까에 대하여 궁금할 수 있습니다. 이 둘의 성능을 비교했을 때 set이 값을 제거하는 경우를 제외하고는 대부분 배열의 성능이 삭제하거나 추가하는 등의 작업에서 더 우수하다고 합니다.

그럼에도 set은 필요할 수 있다!
하지만 set의 가장 큰 특징인 오직 하나의 값만을 가지는 경우는 얘기가 많이 달라집니다. 그 이유는 고유한 값을 가지도록 하는 과정에서 불필요한 많은 시간이 소모될 수 있기 때문입니다. 즉 고유의 값을 가져야하는 경우라면 set을 사용하는 것이 결과적으로 훨씬 나은 선택일 수 있다는 점입니다.


여기까지 자바스크립트의 set 타입에 대하여 알아보았습니다.