자바의 변수와 데이터 타입 (Java Variables & Data type)

🗓 ⏱ 소요시간 8 분

이번 포스트에서는,

  • 변수란 무엇인가
  • 변수를 왜 사용해야 하는가
  • 자바(Java)에서 변수를 어떻게 사용하는가
  • 데이터 타입이란 무엇인가

를 알아보겠습니다.

자바 프로그래밍 Java Programming

우리는 컴퓨터의 프로그램을 왜 쓸까요? 컴퓨터에게 무언가 작업을 시키기 위함입니다. 컴퓨터에게 시킬 작업의 목록을 프로그램이라고 합니다. 컴퓨터에게 내리는 지시사항을 모아놓은 것이죠. 즉, 우리는 컴퓨터의 프로그램을 통해 컴퓨터에게 일을 시키게 됩니다.

컴퓨터에게 1 + 3 + 5 의 계산을 시킨다고 해보죠. 그러면 컴퓨터는 우선 1과 3를 기억해야 할 것이고, 그 둘을 어떻게 할 것인지 + 라는 명령어를 알아야 합니다. 그리고 1과 3을 더한 4라는 값을 기억 또는 저장해야 합니다. 그 4에 5를 더해서 9라는 최종 결과값을 가져다줍니다. 즉, 1 + 3 + 5 라는 계산을 하기 위해서는 데이터를 저장하고 저장된 데이터를 가져다가 연산을 수행해야 합니다.

즉, 프로그램을 만들기 위해서는 데이터를 저장하고 연산하는 컴퓨터에게 방법을 알려줘야 합니다. 컴퓨터는 0과 1로 이루어진 기계어를 쓰는데 기계어는 사람이 쓰기에는 너무 어렵기 때문에 자바(Java)와 같은 고급언어를 사용해 프로그램을 작성하고, 컴파일러가 해당 언어를 기계어로 번역을 합니다. 자바 언어를 번역하는 컴파일러를 자바 컴파일러(javac.exe)라고 합니다.

물론, 자바의 경우, 컴파일러가 기계어로 바로 번역하진 않습니다. 운영체제나 하드웨어 마다 사용하는 기계어가 다르기 때문에 자바는 어느 운영체제나 하드웨어에서도 동일하게 동작하도록 자바 가상 머신(Java Virtual Machine; JVM) 상에서 동작을 합니다. 자바 컴파일러는 우리가 작성한 자바 소스 (.java) 를 클래스 파일 (.class)로 변환하고, JVM 이 클래스 파일을 해당 운영체제의 기계어로 변환을 해서 프로그램을 실행합니다.

변수 Variable

변수와 메모리

앞에서 본 것처럼, 무언가를 연산하기 위해서는 연산하려는 값을 어딘가에 저장하고 사용해야 합니다. 즉, 프로그램은 컴퓨터의 메모리 공간을 사용하게 되고, 프로그램을 작성하는 프로그래머는 사용하려는 값을 메모리 공간에 저장한다고 컴퓨터에게 알려야 합니다.

여기서 데이터의 저장과 참조를 위해 할당된 메모리 공간 을 변수라고 합니다. 또한 이런 변수는 변수명 이라는 이름으로 분류하며, 이런 변수를 컴파일러에게 알려주는 것을 선언 (Declaration) 이라고 합니다.

UseVariable.java
1
2
3
4
5
6
7
8
9
10
11
public class UseVariable {
public static void main(String[] args) {

int num1;
num1 = 10;

int num2 = 20;
int num3 = num1 + num2;
System.out.println(num1 + "+" + num2 + "=" + num3);
}
}

변수를 설명하기 앞서, 중간에 public static void main(String[] args) 라는 문장이 보이시나요? 해당 문장은 프로그램의 시작점을 말하는 메인 메소드입니다. 메소드는 중괄호 ({})로 묶여있고, 우리가 메인 메소드 안에 작성하는 것들이 프로그램을 실행시켰을 때 컴퓨터가 수행하는 내용인 겁니다. 그 외에 다른 키워드들에 대해서는 앞으로 차츰 설명하도록 하겠습니다.

다시 변수로 돌아와, 우리가 변수를 선언하면, 해당 데이터를 저장하기 위한 메모리 상에 공간이 할당됩니다. int num1 이라는 부분을 봅시다. int 저장할 데이터가 10진수 정수의 데이터라는 것을 뜻합니다. num1 은 변수를 구분하기 위한 변수의 이름(변수명)입니다. 즉, int num1 num1 이라는 이름으로 10진수 정수를 저장하는 메모리 공간을 할당한다 는 뜻입니다.

num1 = 10 은 num1 이라는 공간에 10 이라는 값을 저장(대입) 하겠다는 의미입니다. 다음 줄을 보면 int num2 = 20 처럼 선언과 동시에 값을 대입할 수 있는데, 이런 것을 초기화 (Initialize)라고 합니다.

자료형 Data Type

저장하는 데이터에 따라서 표현하는 방법을 달리하기 위해서, 그리고 저장공간을 효율적으로 사용하기 위해서 데이터 타입 (Data Type) 이라는 것이 존재합니다. 앞에서 봤던 int 도 그 중 하나죠. 자바에서 기본적으로 제공하는 자료형은 8가지로 기본 자료형 (Primitive data type) 이라고 합니다. 하나의 데이터를 표현하는데 자료형의 종류가 여러 개인 것은 데이터의 표현 범위가 다르기 때문입니다. 즉, 해당 자료형이 사용하는 메모리 공간이 다르다는 것을 말합니다.

데이터 자료형
정수 byte, short, int, long
실수 float, double
문자 char
참과 거짓 boolean

변수명 작명 규칙

  1. 대소문자를 구분한다.
  2. 변수의 이름은 숫자로 시작할 수 없다.
  3. $ 과 _ 이외의 특수문자는 사용할 수 없다.
  4. 키워드 (지정된 예약어)는 변수의 이름으로 사용할 수 없다.

여기서 키워드는 컴파일러가 해석할 때 이미 지정된 뜻이 있어서 변수명으로는 사용할 수 없는 경우입니다. 예를 들면, 앞에서 봤던 int 같은 경우죠. 이러한 키워드는 앞으로 배워가면서 사용하는 키워드들이 모두 해당합니다.

숫자 표현 방식

정수 표현방식

우리가 10진수를 사용하듯이, 컴퓨터는 2진수를 사용합니다. 10 진수에서 각 자리수가 10배 씩 증가하는 것처럼, 2진수는 각 자리마다 2배 씩 증가하는 것을 볼 수 있습니다. 즉, 값이 2배 커질수록 자리수가 하나씩 증가합니다.

10진수 2진수
1 1
2 10
3 11
4 100
8 1000
10 1010
11 1011
12 1100

1, 10, 11 이런 값들이 메모리에 저장될 때, 각 숫자는 1 bit 라는 메모리 공간을 사용합니다. 10 처럼 두 자리수면 2 bit 를 사용할 겁니다. 8자리는 1 Byte (8bit = 1Byte) 를 사용합니다. 즉, 값이 커질수록 더 많은 메모리 공간을 사용한다는 뜻이고, 정수를 저장할 때 몇 바이트를 사용하느냐에 따라 저장할 수 있는 값의 범위가 정해지게 됩니다.

자바에서 정수를 표현하는 방법에는 4가지가 있습니다.

자료형 메모리크기 표현 가능 범위
byte 1 Byte -128 ~ 127
short 2 Byte -32768 ~ 32767
int 4 Byte -2147483648 ~ 2147483647 (약 21억)
long 8 Byte -922337036854775808 ~ 9223372036854775807

각 바이트는 표현할 수 있는 자리수를 뜻하는데 맨 처음 자리수는 부호를 결정하는 MSB (Most Sigificant Bit)기 때문에 1 Byte 의 경우 2의 8승이 아닌 -128 ~ 127까지 표현이 가능합니다(2의 7승 = 128). MSB 는 양수를 0, 음수를 1로 표현합니다.

byte 의 경우를 예로 들어볼까요. byte 타입은 1 Byte 를 가지고 있고, 표현할 수 있는 자리수는 부호를 제외하면 7자리입니다. 따라서 1은 00000001 로 저장(표현)됩니다. 같은 방식으로 2는 00000010, 3은 00000011 가 됩니다.

그렇다면 음수는 어떨까요? 음수는 MSB 가 1 이라고 했으니, -2 는 10000010 일까요? 아닙니다. 왜냐하면 2와 -2를 더하면 0이 되어야 하는데 00000010 + 10000010 = 10000100 으로 0이 아니기 때문이죠. 컴퓨터는 음수를 2의 보수라는 방식을 이용해 표현합니다. 같은 양수와 더했을 때 0이 되도록 숫자를 변환하는 것입니다. 각 자리의 0과 1을 변환한 후, 1을 더한 값을 2의 보수(Two’s complement)라고 합니다. -2를 예로 들면, 0과 1의 자리를 바꿔서 11111101 이 되고 (이 때의 값을 1의 보수(One’s complement)라고 합니다), 여기에 1을 더하면 11111110 이 됩니다. 이 값을 2와 더해보면 올림수가 버려지고 딱 0이 되어서 -2가 맞다는 것을 증명할 수 있습니다.

실수 표현방식

자바를 설명하는데 왜 이런 내용까지 공부해야 할까요? 컴퓨터가, 그리고 자바가 기본적으로 데이터를 저장하는 방법을 알아야 자료형을 이해할 수 있기 때문입니다. 또한 그냥 사용법을 익히는 것보다 ‘왜 이렇지? 왜 이렇게 되지?’ 라는 의문을 가지고 원리를 이해해야 자바를 더 잘 다룰 수 있기 때문입니다.

지금 이야기하려고 하는 실수 표현방식도 마찬가지입니다. 여기서 말하는 실수란 딱 떨어지는 값이 아닌 소수점을 가진 수를 말하는데, 이 실수는 무한하기 때문입니다. 1과 2 사이에 있는 1.1, 1.2, 1.3, … 이런 값 뿐만 아니라 1.11, 1.111, 1.1111, … 이런 식으로 무한하게 존재합니다. 그렇다면 컴퓨터는 과연 실수를 어떻게 표현할까요?

실수를 저장하려는 저장공간은 한정되어 있고, 어차피 무한한 값을 정확히 표현할 수 없으니, 최대한 근사한 값으로 표현하게 됩니다. 또한 표현 범위를 넓게 하기 위해서 지수로 표현을 합니다. 컴퓨터에서 실수를 표현하기 위한 부동 소수점 규칙은 IEEE 754 표준에 정의되어 있습니다.

부동 소수점 표현

위처럼, 실제 값을 표현하는 지수 부분과 소수점 자리수를 구분하는 지수 부분이 나뉘어져 있습니다. 오차가 존재할 수 밖에 없죠.

자료형 Data type

앞에서 컴퓨터가, 그리고 자바가 데이터를 어떻게 저장하는지 살펴봤습니다. 따라서 데이터를 저장할 때 사용하는 메모리의 크기가 달라지면 값의 표현 범위가 달라진다는 것을 알 수 있었습니다.

정수 자료형

정수는 어떤 자료형에 저장하는 것이 적합할까요?

자료형 메모리크기 표현 가능 범위
byte 1 Byte -128 ~ 127
short 2 Byte -32,768 ~ 32,767
int 4 Byte -2,147,483,648 ~ 2,147,483,647 (약 21억)
long 8 Byte -2의 63승 ~ 2의 63승 - 1 (9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807)

변수에 저장할 값에 따라서 변수의 데이터 타입을 지정해야 할 겁니다. 하지만 중요한 것은, 자바의 기본 데이터형이 int 라는 점입니다. byte 나 short 에 저장하더라도 실제 연산 시에는 int 로 변환하는 작업을 수행합니다. 또한 요즘 컴퓨텅 환경은 메모리가 넉넉하기 때문에 이 정도의 메모리 차이는 크지 않습니다. 그래서 일반적으로 정수는 int 를 사용하게 된다. 그렇다면 long 은 어떨까요? int 로 표현할 수 없는 값의 범위를 표현할 때는 데이터 손실을 방지하기 위해서 반드시 long 을 사용해야 합니다.

int 타입이 약 21억 표현할 수 있다는 점을 기억해두면 좋습니다.

실수 자료형

부동 소수점 표현

자료형 메모리 크기 bit 구성
float 4 Byte 부호(1bit) + 지수(8bit) + 가수(23bit) = 32 bit = 4 Byte
double 8 Byte 부호(1bit) + 지수(11bit) + 가수(52bit) = 64 bit = 8 Byte

실수 자료형의 표현 범위는 다음과 같습니다.

자료형 표현 범위
float 1.40239846E-45f ~ 3.40282347E+38f
double 4.94065645841246544E-324 ~ 1.79769313486231570E+308

문자 자료형

자료형 메모리 크기 표현 범위
char 2 Byte \u0000 ~ \uFFFF

char 타입은 유니코드 문자를 저장합니다. 정확히 말하면 이 코드란 것은 실제로는 숫자입니다. 컴퓨터가 표현할 수 있는 것은 0과 1, 즉 숫자죠. 특정한 숫자에 문자를 맵핑시켜서 표현한 것을 코드라고 합니다.

1
2
3
char c = 'A';
System.out.println(c); // A
System.out.println((int) c); // 65

유니코드란 전 세계의 모든 문자를 저장할 수 있도록 처리한 방식입니다. 초창기에 사용하던 7 bit 의 ASCII 코드는 로마자 위주 코드였기 때문에 다른 국가의 언어를 처리할 수 없었습니다. 그래서 2 Byte (16 bit) 공간에 문자를 할당한 것이 유니코드입니다.

이 코드를 가지고 어떻게 표현할 것인가하는 인코딩 방식에는 UTF-8이 있습니다. 2 Byte 로 사용하는 용량이 커지면서 1 Byte 만으로 표현할 수 있는 문자 입장에서는 메모리를 비효율적으로 사용하게 되었습니다. 이에 따라서 문자에 따라 메모리를 가변적으로 사용하는 가변길이 문자 인코딩(UTF-8) 이 생겨났습니다.

참 거짓 자료형

참/ 거짓 자료형은 truefalse 두가지 값을 가지고 주로 조건문에서 활용됩니다.

1
2
3
4
5
6
7
boolean isChecked = false;

if (isChecked()) {
// do something...
} else {
// ...
}