본문 바로가기

Computer Science/Data Structure

프로그래밍에서 자료형(Data type)이 필요한 이유(in Java)

자료형(Data type)은 데이터를 분류하는 방법이다. 자료형을 통해 해당 자료의 처리되는 데이터 종류, 메모리 할당 과정, 연산 수행 방법을 인지할 수 있다.

 

예를 들어, Primitive type(기본형)인 int(정수) 타입은 언뜻 보면 불필요해 보인다. double(실수) 타입이 int 타입보다 더 넓은 범위의 값을 담을 수 있기 때문이다. 하지만 동일한 수치를 가지는 데이터도 자료형마다 컴퓨터의 이해, 처리하는 방식이 다르기 때문에 서로 다른 자료형으로 구분되어야 한다.

 

Python과 JavaScript의 경우 동적 타입 언어(Java는 정적 타입 언어)로서, 코드 실행 시 Interpreter 또는 Compiler가 타입 추론(Type Inference)을 통해 타입을 자동으로 추론하고 결정한다. 변수에 값 대입 시 타입을 구분할 필요가 없기 때문에 개발자 입장에서는 편리하지만, 그것이 반드시 장점이 된다고만 볼 수는 없다. 동적 타입 언어가 변수를 활용함에 있어 편리함과 유연성을 제공하는 것과는 별개로, 각기 다른 처리 방식의 데이터를 같은 변수에 두서없이 담으면 부적합한 연산으로 인해 예기치 못한 타입 오류를 발생시킬 위험성을 내포하고 있다. 따라서 동적 타입 언어에서도 개별 타입에 유의해서 변수를 사용하는 편이 바람직하다.

 

Java 역시 최신 버전에서 타입 추론 기능이 추가되었다.

 

 

자료형의 종류

 

 

자료형은 크게 Primitive type(기본형)과 Object type(객체형)으로 분류된다.

 

  • Primitive type : Java에서 기본적으로 제공되는 타입으로, 직접 값을 저장한다. Primitive type은 변경이 불가능하지만 Stack에 직접 값을 저장하므로, Heap에서 객체를 참조하는 Object type에 비해 메모리 효율과 성능 면에서 우위에 있다. 특히 초 단위의 실행 속도 제한이 있는 코딩 테스트에서는 통과 여부를 가를 수 있을 정도로 유의미한 퍼포먼스의 차이를 보인다.
  • Object type : Primitive type에 비해 복잡한 자료구조를 가진 데이터 타입으로 하나의 Object는 동시에 여러 종류의 데이터 값을 가질 수 있으며, 데이터를 변경할 수 있는 메소드 또한 제공할 수 있다. Primitive type에 비해 메모리 효율과 성능이 떨어지지만, 다양한 기능을 제공하기 때문에 복잡한 요구 사항을 구현하는 데 있어 우위를 보인다. 예를 들어 Object type만 담을 수 있는 List는 Primitive type을 담은 Array에 비해 실행 속도가 느리지만, 데이터의 삽입과 삭제가 자유롭기 때문에 생성 후 크기의 변경이 불가능한 Array의 치명적인 단점을 보완할 수 있다. 따라서 컴퓨터의 저장 용량이 비대해지고, 성능이 많이 향상되어 실행 속도의 의미가 줄어든 현재는 Array에 비해 자주 쓰이는 편이다.

특히 Linked List는 자료의 삽입과 삭제에 필요한 연산 횟수가 항상 1이고, List뿐만 아니라 Deque의 구현 클래스이기 때문에 Deque와 Deque의 부모 인터페이스인 Queue도 모두 구현한다. 따라서 다양한 메소드를 통해 매우 다재다능한 기능을 제공하는 자료구조이다.

 

 

Primitive type의 분류

 

 

Java에서 primitive type은 총 8가지로 분류된다.

 

  1. byte : 8비트를 사용하며, -128부터 127의 범위를 가진다.
  2. short : 16비트를 사용하며, -32768부터 32767의 범위를 가진다.
  3. int : 32비트를 사용하며, -2^31부터 (2^31)-1의 범위를 가진다.
  4. long : 64비트를 사용하며, -2^63부터 (2^63)-1의 범위를 가진다.
  5. float : 32비트를 사용하며, 약 ±1.4E-45부터 ±3.4028235E38의 범위를 가진다.
  6. double : 64비트를 사용하며, 약 ±4.9E-324부터 ±1.7976931348623157E308의 범위를 가진다.
  7. char : 16비트 유니코드 문자를 표현하며, 0부터 65535의 범위를 가진다. 문자로 표현되지만 엄연히 정수 타입이므로, 문자 간 연산을 편리하게 할 수 있는 이점이 있다.
  8. boolean : 참과 거짓을 표현하는 논리 타입으로, 'true'와 'false' 두 개의 값만을 가진다. 값이 범위가 2밖에 되지 않아 별로 쓸모가 없을 것 같지만, 실제 프로그래밍을 하다 보면 해당 조건이 맞는지 틀린지의 여부를 고려해야 하는 상황이 빈번하게 발생한다.

자료형의 크기는 byte < short < int < long < float < double 순이다. char의 경우 short와 서로 겹치지 않는 범위를 표현하기 때문에 직접적인 비교가 어렵다.

 

 

Primitive type의 타입 변환

 

 

범위가 넓은 자료형의 변수에 범위가 좁은 자료형의 값을 담으면 범위가 큰 자료형으로 자동 타입 변환(Promotion)이 이루어지지만, 반대는 불가능하므로 변환하려는 타입을 직접 명시해 강제 타입 변환(Casting)을 해야 한다.

 

float은 int와 long의 범위를 모두 담을 수 없고, double은 long의 범위를 모두 담을 수 없지만 실수는 정수보다 훨씬 정밀한 값을 다루므로, 기본적으로 실수형이 정수형에 비해 범위가 넓게 표현된다. 하지만 범위를 초과하는 값을 담을 수는 없어 값의 크기가 극단적으로 커지거나 작아질수록 부정확해진다. 따라서 값을 옮길 때는 온전한 값을 수용 가능한 지 항상 주의해야 한다.

 

 

자료형(Data type)이 필요한 이유

 

 

자료형의 구분으로 인해 이렇게 Python과 JavaScript에 비해 불편한 특성을 가졌음에도, 정적 타입 언어인 Java의 자료형 구분에는 여러 유의미한 이점이 있다.

 

  1. Java는 컴파일 단계에서 타입 검사를 수행하여 타입에 맞지 않는 값이 할당되거나 연산되는 것을 방지한다. 따라서 소프트웨어 실행 중 발생할 수 있는 많은 오류를 미리 잡아낼 수 있으며, 디버깅 작업에 투입되는 시간과 인력을 절약할 수 있다.
  2. Java는 컴파일 단계에서 변수의 타입을 인지할 수 있으므로, 메모리 할당과 성능 최적화에서 유리함을 보인다. 대부분의 경우 동적 타입 언어에 비해 실행 속도가 빠르고 메모리 사용이 효율적이다. 코딩 테스트에서 파이썬의 무시무시한 실행 속도는 커다란 약점으로 작용하기도 한다.
  3. 변수 선언 시 자료형을 명시하면 해당 자료의 의도를 더 명확하게 표현할 수 있으므로, 코드의 가독성과 유지보수성이 향상된다. 따라서 정적 타입 언어로 개발을 진행할 시, 타 개발자뿐만 아니라 (미래의) 나에게도 코드를 이해하고 유지보수하는 데 도움을 줄 수 있다.
  4. 정적 타입 언어의 자료형은 그 불편한 특성과는 역설적으로, 정형화된 부분이 많이 존재하는 점을 활용해 오히려 IDE(Integrated Development Environment, 통합 개발 환경)와 같은 개발 툴에서는 더 유용한 지원을 받을 수 있다. 코드 자동 완성, 리팩토링 도구, 타입 오류 감지와 같은 정형화된 format에서 보다 활용 가능성이 높은 기능들이, 예전과 달리 대부분의 개발자가 IDE를 사용하는 현재에는 역으로 정적 타입 언어를 사용한 개발 과정에서 강점으로 작용할 수 있다.

정적 타입 언어의 이러한 이점들 때문에, 현재 JavaScript에 정적 타입 검사 기능을 추가한 TypeScript가 각광받고 있다.

 

참고 자료
https://songacoding.tistory.com/88

'Computer Science > Data Structure' 카테고리의 다른 글

Heap 구조의 이해  (0) 2023.06.17
Linked List 구조의 이해  (0) 2023.06.16
Hash Map 구조의 이해  (0) 2023.06.15
배열(Array) 구조의 이해  (0) 2023.06.14
큐(Queue) 구조의 이해  (0) 2023.06.13