본문 바로가기
-- 오늘 있었던 개발 일기

참조 타입(Reference Type)이란?

by code study 2026. 3. 14.

들어가며

Java를 배우다 보면 "참조 타입"이라는 말을 자주 접하게 됩니다.
변수에 값을 직접 저장하는 기본 타입(int, boolean 등)과 달리, 참조 타입은 조금 다르게 동작합니다.
이 글에서는 참조 타입이 무엇인지, 메모리 구조와 함께 쉽게 설명해드리겠습니다.


기본 타입 vs 참조 타입

Java의 변수는 크게 두 가지 방식으로 값을 저장합니다.

항목 기본 타입 (Primitive) 참조 타입 (Reference)
종류 int, long, double, boolean 등 클래스, 배열, 인터페이스, String 등
저장 위치 스택(Stack) 메모리 스택에는 주소, 실제 데이터는 힙(Heap)
저장 내용 값 자체 힙 메모리의 주소
기본값 0, false 등 null

참조 타입의 메모리 구조

참조 타입은 변수에 객체 자체를 저장하지 않고, 객체가 저장된 힙 메모리의 주소를 저장합니다.
그 주소를 통해 실제 객체에 접근하는 방식입니다.

[스택 메모리]          [힙 메모리]
┌──────────┐          ┌──────────────────┐
│  member  │──주소───▶│  Member 객체     │
│ 0x1234   │          │  name = "홍길동"  │
└──────────┘          │  age  = 25       │
                      └──────────────────┘

 

변수 member에는 객체의 실제 데이터가 아닌, 힙 메모리의 주소(예: 0x1234)가 저장됩니다.
Java는 이 주소를 따라가서 실제 객체에 접근합니다.


코드로 이해하기

public class Main {
    public static void main(String[] args) {

        // 기본 타입: 스택에 값 직접 저장
        int a = 10;

        // 참조 타입: 힙에 객체 생성, 스택에는 주소 저장
        Member member = new Member("홍길동", 25);

        System.out.println(member.name); // 주소를 통해 힙의 객체에 접근
    }
}

new Member()를 호출하면 힙 메모리에 객체가 생성되고,
변수 member에는 그 객체의 주소값이 저장됩니다.


참조 타입의 특징

1. null 할당 가능

참조 타입은 아무 객체도 가리키지 않는 상태를 나타내는 null을 저장할 수 있습니다.

Member member = null; // 아무 객체도 참조하지 않음

 

null 상태의 변수를 사용하면 NullPointerException이 발생하므로 주의해야 합니다.

Member member = null;
System.out.println(member.name); // NullPointerException 발생!

2. 같은 객체를 여러 변수가 참조 가능

Member a = new Member("홍길동", 25);
Member b = a; // a와 b가 같은 객체를 가리킴

b.name = "김철수";
System.out.println(a.name); // "김철수" 출력 - a도 바뀜!

 

b = a는 객체를 복사하는 게 아니라 주소를 복사하는 것입니다.
그래서 b를 통해 수정하면 a도 영향을 받습니다.

3. == 비교는 주소를 비교

Member a = new Member("홍길동", 25);
Member b = new Member("홍길동", 25);

System.out.println(a == b);          // false - 주소가 다름
System.out.println(a.equals(b));     // 내용 비교는 equals() 사용

 

참조 타입에서 ==는 내용이 같은지가 아니라, 같은 객체를 가리키는지 비교합니다.
내용을 비교하려면 equals()를 사용해야 합니다.


String도 참조 타입

String은 기본 타입처럼 보이지만 사실 참조 타입입니다.

String s1 = "hello";
String s2 = "hello";
String s3 = new String("hello");

System.out.println(s1 == s2);      // true  - 같은 상수 풀 주소
System.out.println(s1 == s3);      // false - new로 생성하면 힙에 새 객체
System.out.println(s1.equals(s3)); // true  - 내용은 같음

 

"hello"처럼 리터럴로 선언하면 String 상수 풀에 저장되어 같은 주소를 공유합니다.
반면 new String()으로 생성하면 힙에 새 객체가 만들어져 주소가 달라집니다.
그래서 String 비교는 항상 equals()를 사용하는 것이 안전합니다.


정리

참조 타입은 객체가 저장된 힙 메모리의 주소를 변수에 저장하고, 그 주소를 통해 실제 객체에 접근하는 방식입니다.

핵심 포인트는 아래와 같습니다.

  • 변수에는 객체 자체가 아닌 힙 메모리의 주소가 저장된다.
  • 참조 타입 변수끼리 대입하면 주소가 복사되어 같은 객체를 가리킨다.
  • null은 아무 객체도 참조하지 않는 상태이며, 사용 시 NullPointerException이 발생한다.
  • 참조 타입의 내용 비교는 ==가 아닌 equals()를 사용한다.

메모리 구조를 이해하면 객체 복사, NullPointerException, 예상치 못한 값 변경 등 자주 겪는 버그의 원인을 훨씬 빠르게 파악할 수 있습니다.