Data Type – JavaScript, Python

“여러 가지 데이터 타입을 가지고 있어요”

자바스크립트에서 데이터 타입에 대한 설명은 이렇게 짧게 마무리되는 경우가 종종 있다. 물론 간단하게 이해하고 있어도 사용하는데 큰 불편은 없지만 데이터 타입을 이해하는 것은 언어를 이해하는 좋은 관점이라고 생각해서 정리했다. 프로그래밍 언어의 주요한 데이터 타입은 숫자와 문자열이다. 그 외에 언어 자체에서 제공하는 타입들이 여럿 있는데 이들은 언어의 성격을 나타낸다고 생각한다. 그래서 두 언어의 데이터 타입을 비교하는 방법을 사용하여 언어를 배우고 있다. Python 데이터 타입과 JavaScript 데이터 타입을 차례로 정리했다.

Python Data Type

자바스크립트에서 typeof이라는 연산자를 사용하여 타입을 구분할 수 있는 것과 비슷하게 파이썬은 type이라는 내장(Built-in) 함수를 사용하여 값의 종류를 알아낸다. 자바스크립트보다 파이썬의 타입 종류가 더 많고 복잡하다. 모든 파이썬 데이터는 객체이며 type과 값을 가지고 있다. 자바스크립트에서 대부분이 ‘object’ 타입인 것과 비슷하게 파이썬에서 모든 것이 객체다. 파이썬에는 클래스 또한 객체다. 두 언어 모두 객체를 데이터 모델의 중심으로 삼고 있다. 파이썬의 모든 타입을 나열하기 전에 객체의 타입을 알려주는 type()이라는 함수는 어떤 타입인지 알아보자

>>> type(type)
<class 'type'>

type은 함수가 아니다. ‘type’이라는 이름을 가지는 클래스다. 타입을 물어보았는데 왜 class 일까? 다른 값을 테스트 하자 이번엔 숫자 0의 타입을 알아보자.

>>> type(0)
<class 'int'>

‘int’라는 이름을 가지는 클래스라고 한다. 여기서 type은 클래스이며 type()은 파이썬 함수다. 클래스 이름 뒤에 괄호를 붙이면 클래스 인스턴스를 만드는 작업을 수행한다. type()이 함수를 호출하는 모양을 하고 있지만 클래스에게 인스턴스를 만들도록 명령을 내리는 것이다. 자바스크립트와 비교하자면 new 연산자를 앞에 두어야 하지만 파이썬에선 필요 없다. 비교를 위해서 파이썬의 함수 선언을 보자

>>> def foo():
...     pass
...
>>> type(foo)
<class 'function'>

def로 정의한 함수는 ‘function’ 이름을 가지는 클래스다. type()은 클래스 호출이지만 내장 클래스 임으로 내장 함수라고 이야기한다. type이 ‘function’ 타입은 아니어도 함수처럼 사용됨으로 type() 내장 함수라고 한다. 자바스크립트에서는 괄호가 사용되면 함수 호출이지만 파이썬에서는 함수 호출일 수도 있고 클래스에게 객체를 만들도록 요청하는 것일 수도 있다. 아래 코드에서 Foo() 호출의 결과를 보자

>>> class Foo():
...     pass
...
>>> a = Foo()
>>> b = Foo()
>>> type(a)
<class '__main__.Foo'>
>>> type(b)
<class '__main__.Foo'>
>>> print(id(a))
139892992548760
>>> print(id(b))
139892999647696

Foo()가 수행될 때마다 새로운 객체가 생성된다. 함수 호출과는 다르다. 처음 이야기로 다시 돌아가서 타입은 어디에 있는가? 클래스와 타입, 이 두 가지 용어는 Python 언어가 버전업하면서 의미가 조금씩 변했다고 한다. 내장된 클래스를 type이라고 하고 사용자가 class 키워드를 사용하여 생성한 것은 class라고 한다. 파이썬 버전 3.6.5를 예로 든다면 모두 68개의 내장(Built-in) 함수를 가지고 있다.

abs(), all(), any(), ascii(), bin(), bool(), bytearray(), bytes(), callable(), chr(), classmethod(), compile(), complex(), delattr(), dict(), dir(), divmod(), enumerate(), eval(), exec(), filter(), float(), format(), frozenset(), getattr(), globals(), hasattr(), hash(), help(), hex(), id(), input(), int(), isinstance(), issubclass(), iter(), len(), list(), locals(), map(), max(), memoryview(), min(), next(), object(), oct(), open(), ord(), pow(), print(), property(), range(), repr(), reversed(), round(), set(), setattr(), slice(), sorted(), staticmethod(), str(), sum(), super(), tuple(), type(), vars(), zip(), __import__()

이것은 68개의 내장 클래스가 있다는 말과 같은 말이다. 위의 모든 내장 함수는 아래 세 가지 클래스에 포함된다.

  • ‘_sitebuiltins._Helper’
  • ‘builtin_function_or_method’
  • ‘type’

주목하는 것은 ‘type’ 클래스인데 이 중 다른 언어에서 자주 보던 이름이 몇 가지 보인다.

  • int
  • str
  • bool

리터럴 코드를 사용하여 테스트 하면

>>> type(0)
<class 'int'>
>>> type("apple")
<class 'str'>
>>> type(True)
<class 'bool'>

0, “apple”, True 같은 리터럴 코드가 돌려준 타입의 이름이 ‘int’, ‘str’, ‘bool’ 임을 알 수 있는데 이들이 바로 내장 함수의 이름이다.’ 내가 알고 싶었던 파이썬의 데이터 타입이다.

>>> type(int)
<class 'type'>
>>> type(str)
<class 'type'>
>>> type(bool)
<class 'type'>

이런 이름으로 불리는 파이썬의 전체 데이터 타입을 알고 싶었다. 결론부터 말하면 자바스크립트에서 확인할 수 있었던 7개와 같은 타입 리스트는 찾을 수는 없었다. 다만 범위를 좁힐 수 있었는데 우선 ‘type’으로부터 만들어진 26개의 내장 타입을 고르면 아래와 같다.

bool, bytearray, bytes, classmethod, complex, dict, enumerate, filter, float, frozenset, int, list, map, memoryview, object, property, range, reversed, set, slice, staticmethod, str, super, tuple, type, zip

이들은 타입의 종류면서 해당 타입을 만드는 클래스이고 괄호를 붙이면 내장 함수다. 자바스크립트보다 타입 종류가 많다. 위의 리스트에는 None 객체의 타입인 NoneType은 빠져있다. 26개의 내장 타입 중에서 인자 없이 내장 함수를 수행하고 그 결과의 타입이 자신과 같은 타입을 나타내는 것을 정리했다.

bool() is False
bytes() is b''
complex() == 0j
dict() == {}
float() == 0.0
int() is 0
list() == []
str() is ""
tuple() is ()
bytearray()
frozenset()
object()
range(100)
set([100]) == {100}

is 연산자는 동일한 객체인지 구분하는 연산자이고 == 은 값이 같은지 확인하는 연사자이다. 다른 객체라도 같은 값을 가지고 있을 수 있기 때문이다. is로 표현 못하는 경우 == 를 사용했다. 위의 리스트를 기반으로 파이썬은 자바스크립트 대비 14개의 데이터 타입을 가지고 있다고 생각하기로 했다.

bool, bytes, complex, dict, float, int, list, str, tuple, bytearray, frozenset, object, range, set

대부분 디폴트 값을 가지고 있으며 일부는 리터럴 표현이 가능하다. 자바스크립트에서도 집합과 같은 객체를 찾을 수 있지만 타입의 종류가 아니고 내장 객체다. 리터럴로 표현 가능한 것만 모으면 더욱 더 일반적인 데이터 타입과 비슷해 보인다.

bool, bytes, complex, dict, float, int, list, str, tuple, set

파이썬에서 객체의 타입을 확인하는 또 다른 방법이 있다. 비교를 위해 비슷한 방법을 사용하는 자바스크립트의 예를 먼저 들겠다. 객체를 생성시킨 객체를 확인하는 instanceof라는 연산자를 제공한다.

> 0 instanceof Object
false
> Number instanceof Object
true
> ({}) instanceof Object
true

0은 ‘number’ 타입임으로 내장 객체인 Object으로부터 생성되지 않았으며 Number는 내장 객체임으로 모든 객체의 생성자인 Object로부터 생성되었다. 객체 생성의 리터럴 표현인 {}도 역시 내장 객체 Object로부터 생성되었다. 이와 비슷하게 파이썬도 객체를 생성한 클래스를 알려주는 isinstance() 내장 함수를 제공한다. type() 내장 함수와 다른 점은 부모 클래스를 찾아서 거슬러 올라가는 점이다.

>>> isinstance(0, object)
True
>>> isinstance(int, object)
True
>>> isinstance({}, object)
True

자바스크립트와 다르게 파이썬에서는 숫자 0 조차도 객체다. int는 클래스임으로 역시 객체며 사전의 리터럴 표현인 {}도 클래스임으로 역시 객체다. 다음은 자바스크립트의 데이터 타입을 살펴보겠다.

JavaScript Data Type

최근 공부하고 있는 파이썬 타입과 비교하기 위하여 자바스크립트 타입을 정리했다. 설명을 위해 자바스크립트가 가지고 있는 typeof, instanceof라는 특별한 연산자를 사용하였다.

코드
typeof(0) ‘number’
typeof(‘str’) ‘string’
typeof(true) ‘boolean’
typeof(null) ‘object’
typeof(undefined) ‘undefined’
typeof(Symbol()) ‘symbol’
typeof({}) ‘object’
typeof([]) ‘object’

자바스크립트는 프리미티브 타입과 6개와 ‘object’ 타입을 가지고 있다. null 타입이 ‘object’라는 것은 알려진 오류다. Typeof 연산자의 인자를 모두 리터럴로 표시했는데 Symbol의 경우 리터럴 표기가 없어서 그대로 사용했다. 리터럴을 사용하지 않고 함수를 사용하는 방법으로 변경해도 비슷한 결과를 가진다.

코드
typeof(Number(0)) ‘number’
typeof(String(‘str’)) ‘string’
typeof(Boolean(true)) ‘boolean’
typeof(Symbol()) ‘symbol’
typeof(Object()) ‘object’
typeof(Array()) ‘object’


생성 함수가 없는 null과 undefined를 제외하면 나머지는 같다. 이 함수들은 모두 자바스크립트가 미리 준비한 내장 함수다. 함수는 괄호를 붙이면 함수 바디를 실행하는 특수한 ‘object’ 다. new 연산자를 함수 앞에 두면 객체 생성자로 동작한다. 같은 함수를 new 연산자르 사용하여 호출하자.

코드
typeof(new Number(0)) ‘object’
typeof(new String(‘str’)) ‘object’
typeof(new Boolean(true)) ‘object’
typeof(new Symbol()) TypeError
typeof(new Object()) ‘object’
typeof(new Array()) ‘object’


new 연산자와 함께 사용할 수 없는 Symbol을 제외하고 모든 함수가 ‘object’ 타입을 돌려주었다. 리터럴 표시 0과 Number(0)은 같은 값을 가지고 있지만 new Number(0)은 프리미티브 타입이 아닌 ‘object’ 타입이다.

> 0 === Number(0)
true
> Number(0) === new Number(0)
false

new 연산자를 사용하면 묵시적인 데이터 타입으로 ‘object’를 돌려준다. 물론 생성자로 사용된 함수에서 return 키워드를 사용하여 명시적으로 지정할 경우는 예외다. 여기서 우리는 값을 만드는 세 가지 방식을 구분할 수 있다.

  • 리터럴
  • 함수 호출
  • new 연산자를 사용한 함수 호출

new와 함께 호출되는 함수를 생성자 함수라고 부르기도 한다. 그렇다면 함수 자체는 어떤 타입인가?

코드
typeof(Number) ‘funtion’
typeof(String) ‘funtion’
typeof(Boolean) ‘funtion’
typeof(Symbol) ‘funtion’
typeof(Object) ‘funtion’
typeof(Array) ‘funtion’

‘object’ 타입을 예상했지만 모두 ‘function’이다. 그렇다면 누가 이 함수들을 생성했는지 알아보자 모든 객체는 자신을 생성한 함수와 연결되어서 constructor 속성을 사용하여 확인할 수 있다.

코드
Number.constructor [Function: Function]
String.constructor [Function: Function]
Boolean.constructor [Function: Function]
Symbol.constructor [Function: Function]
Object.constructor [Function: Function]
Array.constructor [Function: Function]

갑자기 등장한 Function 함수도 자바스크립트의 내장 함수다. 다만 Function 함수를 사용하여 함수를 생성하는 것은 권장하지 않는다. 사실 리터럴 문법보다 불편하다. 생성한 함수를 알아보기 위해 instanceof 연산자를 사용할 수도 있다.

코드
Number instanceof Function true
String instanceof Function true
Boolean instanceof Function true
Symbol instanceof Function true
Object instanceof Function true
Array instanceof Function true

위의 내장 함수들을 생성한 함수는 Function이다. 모든 함수는 constructor 속성과 더불어 name이라는 이름 속성을 가지고 있어서 내장 객체의 이름을 알아볼 수 있다.

코드
Number.name ‘Number’
String.name ‘String’
Boolean.name ‘Boolean’
Symbol.name ‘Symbol’
Object.name ‘Object’
Array.name ‘Array’

같은 방식으로 알아보면 Function.name은 ‘Function’이다.

> Function.name
'Function'

자신의 생성자 함수를 가리키는 함수의 prototype 속성을 따라 올라가 보자. Array 예를 들면

> Object.getPrototypeOf(Array).constructor.name
'Function'
> Object.getPrototypeOf(Object.getPrototypeOf(Array)).constructor.name
'Object'

함수의 prototype 속성은 dot notation으로 바로 읽을 수 없음으로 내장 객체 Object의 getPrototypeOf를 사용한다. 각각 ‘Function’과 ‘Object’를 나타낸다. Object가 Function 을 생성하고 Function이 Array를 생성한 것을 알 수 있다.

마무리

자바스크립트는 ‘number’, ‘string’, ‘boolean’, ‘null’, ‘undefined’, ‘symbol’ 이렇게 6개의 타입을 제외한 모든 데이터는 ‘object’ 타입을 가진다고 이해하고 있다. 추가로 ‘function’ 타입이 있는데 특이하긴 하지만 ‘object’로 이해하는 것이 편했다. 이것은 함수를 ‘object’ 처럼 다루어도 된다는 의미다. 자바스크립트의’number’는 파이썬의 int, float, complex와 비슷하다. 더 세분화 되었다. 모두 하나의 숫자를 담는 데이터 타입이다. ‘string’은 str과 ‘boolean’는 bool과 비슷하다. 두 언어의 문자열은 유니코드를 사용한다. 파이썬에는 bytes라는 데이터 타입이 있는데 바이트 단위의 조작이 가능하다. 자바스크립트의 ‘null’ 은 파이썬의 None과 비슷한 용도로 사용된다. 변수에 값을 할당했지만 의미 없는 값이라는 뜻이다. 자바스크립트의 ‘undefined’ 은 파이썬에는 없다. 자바스크립트에서는 변수를 선언만 하고 값을 할당하지 않을 경우에 초기 값으로 undefined 을 가지게 된다. 그러나 파이썬에서는 선언만으로는 변수를 만들 수 없다. 값을 만들려면 할당을 해야 한다. 자바스크립트의 ‘symbol’ 은 파이썬에서 비슷한 타입을 찾을 수 없었다. 자바스크립트에서 특수한 내장 객체인 Array는 서로 다른 데이터 타입을 순서대로 담을 수 있는 데이터 객체이다. 파이썬은 이와 비슷한 데이터 타입으로 list, dict, tuple, set를 사용한다. list는 자바스크립트의 Array 객체와 dict는 Map 객체와 set는 Set 객체와 비슷하다. tuple은 변경할 수 없는 list라고 볼 수 있는데 이름 가진 tuple은 변경할 수 없는 dict라고도 볼 수 있다. 이 tuple는 자바스크리트에서 비슷한 데이터 타입을 찾지 못했다. 데이터 타입이라는 말이 일반적이고 언어에 따라서 의미가 달라지긴 하지만 처음 접하는 언어를 배울 땐 한 번쯤 데이터 타입을 알아보는 것도 괜찮은 방법이라고 생각한다. 다르게 생각한다면 당신이 이해하는 방식을 알려주길 바란다.

답글 남기기

아래 항목을 채우거나 오른쪽 아이콘 중 하나를 클릭하여 로그 인 하세요:

WordPress.com 로고

WordPress.com의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Google photo

Google의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Twitter 사진

Twitter의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Facebook 사진

Facebook의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

%s에 연결하는 중

This site uses Akismet to reduce spam. Learn how your comment data is processed.