Scala

Scala의 Symbol(심볼)

partner_jun 2017. 5. 15. 22:37

스칼라에는 심볼 혹은 심볼 리터럴이라고 불리는 특이한 객체가 있다. 심볼은 String과 다르게 단 하나의 객체만을 가진다는 특징이 있다.



JVM에서 String은 값은 같지만 '다른' 객체가 생길 수 있다. 옛날 코드, 특히 URL을 인코딩하는 예제에 많이 보이는 이상한 경우다.

val str1 = new String("String")
val str2 = new String("String")

println(str1 eq str2) // false

// 스칼라에서 eq는 자바의 ==와 같다.
// 반대로, 스칼라에서 ==는 자바의 .equals() 메소드와 같다.


new String()을 이용하지 않고 "..." 구문으로 문자열을 만들거나 intern() 메소드를 이용하면 다른 결과가 나타난다. 두 가지 방법은 JVM의 String Pool에 문자열이 존재하면 새로 만든 문자열을 버리고 이미 존재하는 문자열을 사용하기 때문이다.

val str1 = new String("String").intern() // val str1 = "String"과 같다.
val str2 = new String("String").intern() // val str2 = "String"과 같다.

println(str1 eq str2) // true


Symbol은 String과 다르게 무조건 단 하나의 객체만이 만들어진다.

val symbol1 = 'String
val symbol2 = 'String

println(symbol1 eq symbol2) // true


하지만 Symbol은 String처럼 다양한 메소드가 구현되어 있지 않다. 쓸법한 것은 심볼의 문자열을 반환하는 .name() 메소드와 ' 기호를 포함한 심볼 전체를 반환하는 .toString() 메소드 둘 뿐이다.


Symbol의 문자열을 반환하는 .name() 메소드 외에는 

AnyRef나 AnyVal같은 상위 클래스나 하위 클래스에서 구현된 메소드들 뿐이다.



직접 확인해 보지는 못했지만 Symbol간의 비교는 String간의 비교(.equals(...) 메소드를 통한)보다 더 짧은 시간이 소요된다고 한다. 당연할 것이다. 시스템적으로 단 하나만 존재하는 객체와 '같을 수도 있는' 객체의 비교이기 때문이다. String이 동적으로 생성되거나 비교가 많은 프로그램이라면 성능에 영향을 미칠 수 있을 것이다.


아무튼, 이런 특징들 때문에 무엇인가를 '표기하는' 용도로 사용할 문자열이라면 String 대신 Symbol을 사용하는 것이 더 나을 수 있다. 마치 무엇인가를 '표기하는' 객체는 enum을 사용하는 것이 더 나은 것처럼.