김영한의 자바 입문 강의 내용을 정리한 글이다.
1. 변수가 필요한 이유
코드를 먼저 보자.
숫자 10을 세 곳에 직접 적었다. 출력값을 20으로 바꾸려면 세 줄을 모두 고쳐야 한다. 100줄이라면 100곳이다. 사용자가 입력한 값을 출력해야 하는 상황이라면 아예 해결이 불가능하다.
모든 프로그래밍 언어가 이 문제를 해결하기 위해 제공하는 것이 변수(variable)다. 값을 한 곳에 저장해 두고, 필요한 곳에서 이름으로 꺼내 쓰는 방식이다.
이제 a = 20; 한 줄만 바꾸면 세 출력 모두 20이 된다.
2. 패키지
예제 코드 첫 줄에 package variable;이 등장한다. 패키지는 자바 파일을 구분하는 폴더다. variable이라는 패키지에 속하는 자바 파일은 첫 줄에 반드시 package variable;을 선언해야 한다. 파일이 위치하는 패키지와 선언이 일치하지 않으면 컴파일 오류가 발생한다.
3. 변수 선언과 초기화
변수 선언
int a;는 "정수를 저장할 수 있는, 이름이 a인 공간을 메모리에 만들어라"는 뜻이다. 컴퓨터는 메모리의 어느 주소에 4바이트 공간을 확보하고, 그 위치에 a라는 이름을 붙인다.
변수를 여러 개 선언하는 방법은 두 가지다.
변수 초기화
변수를 선언한 뒤 처음으로 값을 저장하는 것을 초기화라 한다.
자바에서 =는 수학의 등호가 아니다. 오른쪽 값을 왼쪽에 저장한다는 대입 연산자다.
초기화하지 않으면 컴파일 오류
지금 배우는 변수는 지역 변수(Local Variable)다. 메서드 블록 안에서 선언된 변수가 지역 변수이며, 개발자가 직접 초기화해야 한다. 초기화 없이 사용하면 컴파일러가 오류를 낸다.
이유는 메모리 구조에 있다. 메모리는 여러 프로세스가 함께 사용하는 공간이라 어떤 값들이 계속 쌓인다. 변수를 선언하면 메모리의 특정 주소를 확보하지만, 그 공간에 이미 어떤 값이 남아 있을지 알 수 없다. 초기화 없이 읽으면 의미 없는 쓰레기 값이 출력될 수 있다. 자바는 이를 허용하지 않는다.
지역 변수만 개발자가 직접 초기화해야 한다. 클래스 변수와 인스턴스 변수는 자바가 자동으로 초기화해 준다.
JVM 스택 프레임과 지역 변수
메서드가 호출될 때마다 JVM은 스택(Stack)에 스택 프레임(Stack Frame)을 하나 생성한다. 프레임 안에는 지역 변수들이 배열 슬롯 형태로 저장된다. int, float 같은 4바이트 타입은 슬롯 1개를, long, double 같은 8바이트 타입은 슬롯 2개를 차지한다.
메서드 실행이 끝나면 해당 프레임이 스택에서 즉시 제거된다. 지역 변수도 함께 사라진다. 힙(Heap)에 별도로 남지 않는다는 점이 중요하다.
변수 값 변경
새 값을 대입하면 기존 값은 삭제된다. 변수는 하나의 값만 저장한다. 실행 순서를 따라가면 아래와 같다.
4. 변수 타입
변수는 담을 수 있는 데이터 종류가 정해져 있다. 이것을 타입(type) 또는 형이라 한다.
기본 타입 전체
| 분류 | 타입 | 크기 | 표현 범위 |
|---|---|---|---|
| 정수 | byte | 1byte (2⁸) | -128 ~ 127 |
| 정수 | short | 2byte (2¹⁶) | -32,768 ~ 32,767 |
| 정수 | int | 4byte (2³²) | 약 -21억 ~ 21억 |
| 정수 | long | 8byte (2⁶⁴) | 약 -920경 ~ 920경 |
| 실수 | float | 4byte | 약 ±3.4E38, 7자리 정밀도 |
| 실수 | double | 8byte | 약 ±1.7E308, 15자리 정밀도 |
| 문자 | char | 2byte | 유니코드 문자 하나 (UTF-16) |
| 논리 | boolean | 1byte | true, false |
String은 이 목록에 없다. 기본 타입이 아니라 클래스이며, 뒤에서 별도로 다룬다.
리터럴
코드에 개발자가 직접 적은 고정된 값을 리터럴(literal)이라 한다. "literal"의 어원은 "문자 또는 글자"다. 변수의 값은 바뀔 수 있지만 리터럴 자체는 변하지 않는다.
타입에 맞는 값만 저장 가능
리터럴 타입 지정 — L과 f
정수 리터럴의 기본 타입은 int다. int 범위(약 21억)를 넘는 값을 사용하려면 L을 붙여 long으로 지정해야 한다.
실수 리터럴의 기본 타입은 double이다. float을 쓰려면 f를 붙여야 한다.
정수 오버플로우
int의 최댓값을 넘으면 어떻게 될까? 예외가 발생하지 않고, 조용히 반대쪽 끝으로 돌아간다(wrap-around).
오버플로우는 디버깅하기 어려운 버그의 원인이 된다. 값이 20억을 넘을 가능성이 있으면 처음부터 long을 사용한다.
float vs double — 왜 정밀도가 다른가
float과 double 모두 IEEE 754 부동소수점 표준을 따르지만 비트 수가 다르다. float은 32비트(가수부 23비트)로 유효 자릿수 약 7자리를, double은 64비트(가수부 52비트)로 약 15자리를 보장한다.
둘 다 정확하지 않지만 double이 더 정밀하다. 현대 CPU는 64비트 연산에 최적화되어 있어 float과 double의 성능 차이가 거의 없다. 실무에서는 double만 사용한다고 생각하면 된다. 금액 계산처럼 오차가 치명적인 경우에는 BigDecimal을 사용한다.
char와 유니코드
char는 문자 하나를 저장하며, 작은따옴표로 감싼다. 크기가 2바이트인 이유는 유니코드(Unicode) 때문이다. 자바가 설계된 1990년대 초, 유니코드는 2바이트(65,536개)로 세계 모든 문자를 표현할 수 있다고 가정했다. 자바는 이 설계를 따라 char를 2바이트 UTF-16 코드 유닛 하나로 정의했다.
이후 유니코드가 확장되어 이모지 같은 문자는 char 하나로 표현할 수 없게 됐다. 실무에서는 문자 하나도 String으로 처리하는 편이 안전하다.
String의 특수성
String은 기본 타입이 아니라 클래스(참조 타입)다. 문자열은 길이가 가변적이어서 고정 크기인 기본 타입으로 표현할 수 없기 때문이다. 객체이므로 메모리의 힙(Heap)에 저장된다.
자바는 메모리 효율을 위해 String Pool(문자열 상수 풀)을 관리한다. 리터럴로 문자열을 생성하면 JVM이 풀을 먼저 확인하고, 동일한 내용이 있으면 새 객체를 만들지 않고 기존 참조를 재사용한다.
지금은 "문자열을 다루는 특별한 타입"으로만 이해해도 충분하다.
String에 대한 자세한 내용은 별도로 다룬다.
5. 실무에서 자주 쓰는 타입
| 분류 | 권장 타입 | 이유 |
|---|---|---|
| 정수 | int |
JVM이 4바이트 연산에 최적화되어 있다. byte, short를 써도 내부적으로 int로 승격되어 처리된다 |
| 정수 (큰 값) | long |
20억이 넘을 가능성이 있으면 처음부터 long을 사용한다 |
| 실수 | double |
float보다 정밀도가 2배 높고, 성능 차이가 거의 없다 |
| 논리 | boolean |
조건문에서 필수 |
| 문자/문자열 | String |
문자 하나도 String으로 처리하는 것이 안전하고 편리하다 |
byte, short, float, char는 실무에서 거의 사용하지 않는다. 메모리를 조금 아끼는 것보다 코드의 가독성과 안정성이 더 중요하다. 파일 전송이나 바이너리 처리에서는 byte를 사용한다.
메모리 용량은 매우 저렴하다. 메모리 절약보다 개발 속도와 코드 품질에 초점을 맞추는 것이 효과적이다.
6. 변수 명명 규칙
변수 이름을 짓는 방식은 규칙과 관례로 나뉜다.
규칙 — 위반하면 컴파일 오류
- 숫자로 시작할 수 없다. (
1num불가,num1가능) - 공백을 포함할 수 없다.
- 자바 예약어를 변수 이름으로 사용할 수 없다. (
int,class,public등) - 사용 가능한 문자: 영문자(
a-z,A-Z), 숫자(0-9),$,_
관례 — 전 세계 자바 개발자가 따르는 표준
| 대상 | 표기법 | 예시 |
|---|---|---|
| 변수, 메서드 | camelCase (소문자 시작) | firstName, userAccount |
| 클래스 | PascalCase (대문자 시작) | Person, OrderDetail |
| 상수 | UPPER_SNAKE_CASE | USER_LIMIT, MAX_SIZE |
| 패키지 | 모두 소문자 | org.spring.boot |
camelCase(낙타 표기법)는 여러 단어를 이어 쓸 때 첫 단어는 소문자, 이후 각 단어의 첫 글자는 대문자로 표기한다. 이름에 공백을 넣을 수 없는 프로그래밍 언어의 제약을 우회하면서도 단어를 구분하는 효과적인 방식이다.
변수 이름은 용도를 명확하게 설명해야 한다.
a,b같은 이름은 간단한 예제에서만 허용한다. 실무에서는studentCount,maxScore,userAccount처럼 읽는 사람이 의미를 바로 파악할 수 있는 이름을 사용한다.
'Study > Java' 카테고리의 다른 글
| [Java] 스코프, 형변환 (0) | 2026.04.04 |
|---|---|
| [Java] 반복문 (0) | 2026.04.04 |
| [Java] 조건문 (0) | 2026.04.04 |
| [Java] 연산자 (0) | 2026.04.04 |
| [Java] Java란? (0) | 2026.04.03 |
