변수란 기본형 8종 리터럴 기본형 vs 참조형 상수 · var 📝 문제풀이
◀ 이전 📋 목차 CH 04 ▶
📦 CHAPTER 03 · 입문

값을 담는 상자, 변수와 자료형

프로그램은 결국 값(데이터)을 다루는 일이에요. 그 값을 어디에 담고, 어떤 종류로 나눌지를 배우는 게 이번 장입니다. 상자에 이름표를 붙이는 이야기로 천천히 풀어볼게요.

🎯 이 장을 끝내면
📦
변수란
값을 담는 "상자"에 "이름표"를 붙이기
가장 기본이 되는 개념이에요. 비유로 확실히 잡고 갈게요.

변수(variable)는 값을 담아 두는 "상자"예요. 그리고 그 상자에는 나중에 다시 꺼내 쓰기 위해 이름(이름표)을 붙여요. 예를 들어 나이를 저장하고 싶다면, age라는 이름의 상자를 하나 만들고 그 안에 20이라는 값을 넣는 거죠.

🏷️
이름 (age)
상자에 붙인 이름표
📦
상자 (int)
담을 값의 종류(크기)를 정함
🔢
값 (20)
상자에 실제로 담긴 데이터

그런데 자바는 상자를 만들 때 "이 상자에 어떤 종류의 값을 담을지"를 미리 정해야 해요. 이걸 자료형(type)이라고 해요. 정수를 담을 상자, 소수를 담을 상자, 글자를 담을 상자가 서로 다른 거죠. 이렇게 타입을 미리 정하는 언어를 정적 타입 언어라고 부르는데, 자바가 바로 그런 언어예요.

상자를 만드는 문장을 선언(declaration), 그 상자에 처음 값을 넣는 것을 초기화(initialization)라고 해요. 둘을 한 줄에 같이 쓸 수도 있어요.

int age;          // 선언: "int(정수)를 담을 age 상자를 만든다"
age = 20;         // 대입: age 상자에 20을 넣는다

int score = 100;  // 선언 + 초기화를 한 줄에 (가장 흔한 형태)
🧩 선언 · 초기화 · 대입, 뭐가 다를까? ① 선언 — 상자를 만드는 일. int age; (아직 값은 없음)
② 초기화 — 상자에 처음 값을 넣는 일. int age = 20;
③ 대입 — 상자의 값을 바꿔 넣는 일. age = 30; (기존 20이 사라지고 30) 💡 =는 "같다"가 아니라 "오른쪽 값을 왼쪽 상자에 넣어라"라는 뜻이에요. 수학의 등호와 헷갈리지 마세요.

변수는 값을 바꿔 담을 수 있어요. 상자 안의 내용물을 새 값으로 갈아 끼우는 셈이죠. 그래서 이름이 "변(變)수" — 변하는 수예요.

int age = 20;
System.out.println(age);   // 20
age = 21;                  // 상자 내용물을 21로 교체
System.out.println(age);   // 21
📝 변수 이름(식별자) 규칙 1. 시작 문자 — 반드시 문자, 또는 _ (밑줄), $ (달러)로 시작. 예: name, _temp, $id
2. 숫자로 시작 불가2age ❌ (숫자는 두 번째 글자부터는 OK: age2 ✅)
3. 예약어 불가int, class, for 처럼 자바가 이미 쓰는 단어는 이름으로 못 씀
4. 대소문자 구분ageAge다른 변수예요
5. 관례(카멜케이스) — 첫 단어는 소문자, 이후 단어의 첫 글자는 대문자. 예: userName, maxScore 규칙(1~4)은 어기면 에러가 나고, 관례(5)는 어겨도 돌아가지만 모두가 지키는 약속이라 꼭 따르는 게 좋아요.
🧭
이름은 "뜻"이 보이게. int a = 20; 보다 int age = 20;이 훨씬 좋아요. 몇 달 뒤의 나(또는 동료)가 코드를 읽을 때 이름만 보고 뜻을 알 수 있으니까요.
🔢
기본형 8종
자바가 기본으로 주는 8개의 상자
외우려 하지 말고 "왜 이렇게 나눴나"를 이해하면 자연스럽게 남아요.

자바에는 미리 준비된 기본 자료형(primitive type)이 딱 8개 있어요. 값의 성격에 따라 정수 · 실수 · 문자 · 논리 네 그룹으로 나뉘어요. 각 타입은 담을 수 있는 크기(바이트)가 정해져 있어요. 상자가 클수록 더 큰 값을 담을 수 있지만 메모리도 더 써요.

🔤
용어 — 바이트(Byte)는 컴퓨터가 데이터를 저장하는 크기(용량)의 기본 단위예요. 1바이트 = 8비트이고, 비트는 0 또는 1 하나를 담는 가장 작은 칸이에요. 그래서 "int는 4바이트"라는 말은 그 상자가 차지하는 메모리 크기가 4바이트라는 뜻이에요. 숫자가 아무리 커도 상자 크기 안에서만 담을 수 있어요.
그룹타입크기대략적 표현 범위 · 값용도
정수byte1바이트-128 ~ 127아주 작은 정수, 바이트 데이터
short2바이트약 -3.2만 ~ 3.2만작은 정수 (잘 안 씀)
int4바이트약 -21억 ~ 21억정수의 기본. 대부분 이걸 씀
long8바이트약 -922경 ~ 922경 (아주 큼)int로 부족한 큰 정수(금액·시간)
실수float4바이트소수 (정밀도 약 7자리)메모리 아낄 때의 소수
double8바이트소수 (정밀도 약 15자리)실수의 기본. 대부분 이걸 씀
문자char2바이트글자 한 개 ('가', 'A')단일 문자. 작은따옴표 ' '
논리boolean1바이트*true / false참·거짓 (조건, 스위치)
💡
기본은 딱 둘만 기억하세요. 정수는 int, 실수는 double. 특별한 이유가 없으면 이 둘을 쓰면 돼요. byte·short·float은 "이런 게 있구나" 정도면 충분해요.
🔤
용어 — 정밀도(precision)소수를 몇 자리까지 정확하게 표현할 수 있는지를 뜻해요. float는 약 7자리, double는 약 15자리라, double이 더 촘촘하고 정확해요. 돈 계산처럼 정확함이 중요할 땐 double(또는 나중에 배울 별도 타입)을 쓰는 이유예요.

그런데 큰 상자에 담을 값이라면 자바에게 그렇다고 알려줘야 해요. long에는 뒤에 L, float에는 뒤에 f를 붙여요. double은 기본이라 아무것도 안 붙여도 돼요.

long population = 8000000000L;   // 80억 → int 범위를 넘어서 L 필수
float pi = 3.14f;                // float에는 f (없으면 double로 취급돼 에러)
double rate = 3.14;              // double은 기본, 접미사 불필요

char grade = 'A';                // 문자 한 개 → 작은따옴표
boolean isPassed = true;         // 참 / 거짓
🤔 왜 L·f를 붙여야 할까? 자바는 코드에 그냥 100이라고 쓰면 그걸 int로 봐요. 그래서 80억처럼 int(약 21억)를 넘는 숫자를 쓰면 "이건 int인데 너무 크다"며 에러가 나요. 그때 L을 붙여 "이건 long이야"라고 알려주는 거예요.
마찬가지로 3.14는 자바가 double로 봐요. 그래서 float 상자에 넣으려면 f를 붙여 "이건 float이야"라고 알려줘야 해요. 즉 접미사는 "이 값의 타입을 이걸로 봐 달라"는 표시예요. 다음 절에서 리터럴의 기본 타입을 더 자세히 봅니다.
📦 번외 — boolean은 왜 크기가 애매할까?
booleantrue / false 딱 두 값만 있으니 이론적으로는 1비트면 충분해요. 그런데 컴퓨터가 데이터를 다루는 최소 단위가 보통 바이트(8비트)라, 실제로는 JVM 구현에 따라 처리돼요. 그래서 어떻게? 자바 명세는 boolean의 정확한 크기를 못 박지 않았어요. 그래서 시험에서 "boolean은 몇 바이트?"가 나오면 보통 1바이트로 답하지만, 진짜 핵심은 "true/false 두 값만 담는다"는 거예요. 크기보다 역할을 기억하세요.
✍️
리터럴
코드에 직접 쓴 "날값", 리터럴
앞 절의 L·f 이야기가 여기서 완전히 이해돼요.

리터럴(literal)코드에 직접 적어 넣은 고정된 값이에요. int age = 20;에서 20이 바로 리터럴이죠. 문자 'A', 참 true, 소수 3.14도 전부 리터럴이에요.

핵심은 이거예요. 자바는 리터럴마다 "기본 타입"을 미리 정해 두고 있어요.

📌 리터럴의 기본 타입 정수 리터럴(100, -7)의 기본 타입은 int → 그래서 long이 필요하면 100L
실수 리터럴(3.14, 0.5)의 기본 타입은 double → 그래서 float이 필요하면 3.14f 💡 정리: 정수는 int, 실수는 double이 기본이에요. 이걸 벗어나고 싶을 때만 L·f를 붙이면 돼요.

정수 리터럴은 10진수 말고 다른 진법으로도 쓸 수 있어요. 앞에 정해진 표시를 붙이면 돼요.

🔤
용어 — 진법(2진수·16진수)수를 몇 개의 기호로 나타내느냐예요. 우리가 늘 쓰는 10진수는 0~9 열 개로, 컴퓨터가 속으로 쓰는 2진수는 0·1 두 개로 수를 표현해요. 16진수는 0~9와 A~F(10~15)까지 열여섯 개를 써요. 값 자체는 같고 적는 방법만 다른 거예요 — 아래 표의 0b11010·0x1A·26은 모두 같은 수랍니다.
진법접두사예시10진수 값
10진수 (기본)없음2626
16진수0x0x1A26
8진수003226
2진수0b0b1101026

또, 큰 숫자는 언더스코어( _ )로 자릿수를 끊어 읽기 좋게 쓸 수 있어요. 실행에는 아무 영향이 없고, 사람 눈에만 편해요.

int hex = 0x1A;             // 16진수 → 26
int bin = 0b1101;          // 2진수  → 13
int big = 1_000_000;       // = 1000000 (언더스코어는 무시됨, 가독성용)
long salary = 50_000_000L; // 5천만 (long이라 L)
🔍
언더스코어는 숫자 사이에만 쓸 수 있어요. _1000(맨 앞), 1000_(맨 뒤), 1_.5(소수점 옆)처럼 쓰면 에러예요. "숫자와 숫자 사이 구분자"라고 기억하세요.
🔗
기본형 vs 참조형
"값을 담는 상자" vs "주소를 담는 상자"
자바 타입의 큰 두 갈래. 여기서 char와 String의 차이도 확실히 잡아요.

자바의 자료형은 크게 두 갈래예요. 지금까지 본 8개는 전부 기본형(primitive)이고, 그 외 모든 것(String, 배열, 클래스로 만든 객체 등)은 참조형(reference)이에요.

🔤
용어 — 객체(Object)여러 데이터와 기능을 하나로 묶어 놓은 "덩어리"예요. String(문자열)이나 배열처럼, 기본형 8개를 뺀 나머지가 다 객체에 해당해요. 지금은 "기본형보다 크고 복잡한, 통째로 다루는 값" 정도로만 알아 두면 돼요. 객체를 직접 만들고 다루는 방법은 뒤의 클래스·객체 챕터에서 제대로 배워요.
📦 vs 🔗 무엇을 담느냐의 차이 기본형 — 상자에 값 자체를 담아요. int x = 20; 이면 상자 안에 진짜 20이 들어 있어요. 이 값들은 스택(stack)이라는 빠른 메모리에 놓여요.
참조형 — 상자에 값이 아니라 값이 있는 곳의 "주소"를 담아요. 진짜 데이터(객체)는 힙(heap)이라는 넓은 메모리에 있고, 변수는 그걸 가리키는 주소만 들고 있어요. 🗣️ 비유: 기본형은 지갑에 현금을 직접 넣는 것, 참조형은 "돈은 저 금고에 있어"라는 쪽지(주소)를 넣는 것과 같아요.
🧠 번외편 — 스택·힙이 실제로 어떻게 생겼을까? 「메모리 개념」 부록 방금 나온 스택·힙·주소(참조)를 그림으로 자세히. 코드가 메모리에 오르내리는 과정, GC, 자바스크립트 메모리까지. 새 탭으로 열려요. 새 탭 ↗

가장 자주 만나는 참조형이 바로 String(문자열)이에요. 여러 글자를 담고, 큰따옴표 " "로 씁니다. String은 참조형이지만 워낙 많이 쓰여서 자바가 기본형처럼 편하게 쓸 수 있게 특별 대우해 줘요.

char initial = 'K';          // 문자 1개 → char, 작은따옴표
String name  = "Kim";        // 여러 글자 → String, 큰따옴표

int   n1 = 20;               // 기본형: 상자에 값 20이 직접
String s1 = "hello";         // 참조형: 상자엔 주소, 실제 문자열은 힙에
🎯 자주 틀리는 포인트 — char vs String char = 글자 딱 한 개, 작은따옴표. 'A', '가', '7' ✅ / 'AB' ❌ (두 글자 불가)
String = 글자 0개 이상 여러 개, 따옴표. "A", "Hello", ""💡 따옴표를 헷갈리면 바로 에러예요. "한 글자면 작은따옴표(char), 문장이면 큰따옴표(String)"로 외우세요. "A"'A'는 겉보기엔 비슷해도 타입이 완전히 달라요.
🧠
구분법 한 줄. 소문자로 시작하는 타입(int, char, boolean…)은 대개 기본형, 대문자로 시작하는 타입(String, Scanner…)은 참조형(클래스)이에요. 완벽한 규칙은 아니지만 처음엔 아주 유용한 눈썰미예요.
🔒
상수 · var
못 바꾸는 값(final)과 타입 생략(var)
변수의 두 가지 변형. 가볍게 눈에 익혀두면 돼요.

변수는 값을 바꿀 수 있는 상자였죠. 그런데 때로는 "한 번 정하면 절대 못 바꾸게" 잠그고 싶을 때가 있어요. 원주율 3.14, 최대 인원수처럼요. 그럴 때 final을 붙이면 상수(constant)가 돼요. 상수에 다시 값을 넣으려 하면 에러가 나요.

final int MAX_SIZE = 100;   // 상수 선언 (더는 못 바꿈)
// MAX_SIZE = 200;          // ❌ 에러! final은 재대입 불가

final double PI = 3.14159;
System.out.println(PI);     // 3.14159 (읽기는 자유)
💡
상수 이름은 대문자. final 상수는 관례상 모두 대문자로, 단어 사이는 밑줄로 씁니다. 예: MAX_SIZE, PI, TAX_RATE. 이렇게 하면 코드에서 "아, 이건 바뀌지 않는 값이구나"가 한눈에 보여요.

반대로, 타입을 일일이 쓰기 귀찮을 때도 있어요. 자바 10부터는 var를 쓰면 자바가 오른쪽 값을 보고 타입을 알아서 추론해 줘요. 이걸 타입 추론(type inference)이라고 해요.

var msg = "hi";     // 오른쪽이 문자열 → 자바가 String으로 추론
var count = 10;     // 오른쪽이 정수   → int로 추론
var pi = 3.14;      // 오른쪽이 실수   → double로 추론

// msg, count, pi 는 각각 String, int, double 로 확정돼요.
⚠️ var 쓸 때 주의 1. 초기값이 꼭 있어야 해요var x; ❌ (값이 없으면 타입을 추론할 수 없음)
2. 지역 변수에서만 — 메서드 안의 변수에서만 써요. (클래스의 필드 등에는 못 씀)
3. 타입이 사라지는 건 아니에요var는 "타입을 안 쓴다"일 뿐, 타입은 여전히 고정돼요. var count = 10; 뒤에 count = "hi"; 는 ❌ 입문 단계에서는 타입을 직접 쓰는 습관을 먼저 들이는 게 좋아요. var는 "이런 게 있다" 정도로만 알아두고, 나중에 코드가 길고 복잡해질 때 요긴하게 씁니다.
🔎 번외 — 초기화 안 한 변수는 어떻게 될까?
지역 변수(메서드 안)는 초기화하지 않으면 아예 쓸 수 없어요. 값을 넣기 전에 읽으려 하면 자바가 컴파일 단계에서 "초기화되지 않았다"며 에러를 냅니다. 실수로 빈 상자를 꺼내 쓰는 걸 막아 주는 안전장치예요. 단, 클래스의 필드는 다름 클래스 안에 선언한 변수(필드)는 초기화를 안 해도 기본값이 자동으로 채워져요. int0, double0.0, booleanfalse, 참조형(String 등)은 null. 이 "기본값" 개념은 뒤 챕터(클래스·객체)에서 다시 나오니 지금은 "지역 변수는 꼭 초기화해야 한다"만 챙기세요.
🧠 이 장 핵심 요약
📝
문제풀이 · 점검
배운 걸 가볍게 점검해봐요
시험이 아니라 "내가 이해했나" 확인용이에요. 틀려도 바로 해설이 나와요.
🧪
문제를 풀면 즉시 정답과 해설이 나오고, 위쪽 바에 점수가 쌓여요. 네 가지 유형(객관식 · O/X · 빈칸 · 코드결과)을 섞어 두었어요. 편하게 눌러보세요.
CH 04 🔄 형변환(타입 캐스팅) — 서로 다른 타입의 상자끼리 값을 옮기는 규칙