이번시간에는 타입 시스템, 강/약타입 ,정적/동적 타입 검사에 대해 알아보려 한다
Type은 굉장히 많이 접하고 자주 사용하는 (거의 항상 사용하는) 개념이다
하지만 이 Type이 의미하는 것이 무엇인지 어떤 이유로 사용하는지는 생각해본적이 많이 없었다
Type은 '올바른 동작' 을 하기 위해 정의하고 사용한다
만약 Type이 없는 코드를 생각해보자 매우 당황스러울 것이다
예시
어떤 동작과 목적을 가지고 변수를 만들고 함수를 사용하는지에 대한 기초적인 것은 Type 정의부터 시작한다고 생각된다
위에서는 타입이 무엇인지에 대해 간략하게 알아보았다
그렇다면 타입 시스템은 무엇일까 ?
쉽게 말하면 타입 검사자 이며 코드의 타입을 검사하는 일종의 시스템이다
타입시스템의 목표는 개발자가 작성한 코드들의 타입을 의도에 맞게 명확하게 체크하는 것이다
여기서 타입 검사를 언제로 하느냐에 따라 동적 혹은 정적 타입 검사 인지 구분이 가능하다
그리고 아주 꼼꼼하고, 세심하게 체크하는 것이 훌륭하고 정답인 타입 시스템은 아니다
여기서도 트레이드 오프
(개인적으로 좋아하는 단어이다) 가 발생하기 때문이다
예를 들어 컴파일러가 타입에 대해 꼼꼼하고, 세심하게 체크할 수록 언어를 작성하는 개발자 입장에서는 제약이 많이 생길 수 밖에 없을 것이다
먼저 약타입, 강타입에는 어떤 언어가 있을까 ?
약타입
강타입
이 둘을 나누는 중요한 기준은 타입 에러를 항상 검출할 수 있냐
, 타입 변환이 가능한가
이다
약 타입의 C언어 같은 경우에는 타입을 바꿀 수 있다 아래에서는 a와 b는 서로 자료형이 다른 상황에서 + 연산을 하려고 한다 자료형이 다름에도 불구하고 컴파일 혹은 실행시점에 암시적으로 형 변환을 해준다 이를 Implicit Type conversion이라고도 한다
int a = 1;
float b = 1.3f;
float c = a + b; // int 형인 a가 float 형으로 변환됩니다.
약타입, 강타입을 공부하기 전 나는 항상 타입을 명시해줘야 하므로 C언어가 강타입 언어인 줄 알았다 하지만 타입을 명시해주는 기준이 아닌 타입이 변환이 가능한지 아닌지, 타입 에러를 검출할 수 있는지가 중요했다
타입을 바꾼다는 것을 형 변환(Type conversion)이라고 한다
다만, 암시적 형 변환이 될때는 아래 그림처럼 표현 범위가 좁은 데이터 타입에서 넓은 데이터 타입으로만 변환될 수 있다
즉, float은 double 로 바뀔 수 있지만 double은 float으로 바뀔 수 없다
다만 약타입 언어에서는 명시적으로 변환이 가능하다
암시적 형 변환이 되는 경우는 몇가지가 있다
다른 자료형 값으로 변수가 할당되는 경우
float a;
a = 3;
함수 매개 변수에 다른 자료형의 값을 전달하는 경우
void do(long l)
{ }
do(3); // 다른 타입의 파라미터
함수에서 다른 자료형의 값을 반환하는 경우
float do()
{
return 3;
}
강 타입의 go 언어의 경우 아래와 같이 코드를 작성하면 컴파일 에러가 발생한다
강 타입 언어에서는 데이터 타입이 강제로 지정되어있고, 변수를 선언할 때 명시적으로 해당 타입을 지정해야 한다 그러므로 서로 다른 데이터 타입 간에는 자동으로 형 변환이 일어나지 않는다
var a int = 1
var b float32 = 1.3
var c float32 = a + b // int 형인 a가 float32 형으로 변환되지 않고 컴파일 에러 발생
그렇다면 왜 이렇게 약타입과 강타입으로 언어를 나눌까 ?
그냥 편하게 타입변환이 알아서 되게 하면 안될까 ?
특징에서도 볼 수 있다 시피 약타입 언어는 유연성과 편의성을 제공하지만 타입오류의 위험을 그만큼 감수해야 합니다 반면에 강터입 언어는 타입 안정성과 가독성을 높여주지만 코드가 비교적 복잡하고 개발시간이 증가할 수 있습니다.
위의 타입시스템에서도 간략하게 설명하였지만 정적/동적 타입은 언제 타입을 검사하는지 즉, 타입의 결정시점을 기준으로 구분이 됩니다
정적 타입 검사는 런타임 이전에 컴파일 시 검사를 실시합니다
따라서 프로그램을 따로 실행하지 않고도 타입에 대한 오류를 예방할 수 있습니다
동적 타입 검사는 런타임에 검사를 실시합니다
프로그램을 실행하기 전에는 타입 오류에 대해서 알 수 없으므로 타입에 대한 리스크를 그만큼 감당해야 합니다
참고