반응형

Java에서는 변수나 메서드, 클래스의 동작 방식을 제어하는 다양한 키워드가 존재합니다. 이 중에서도 volatile, transient, synchronized는 각각 메모리 동기화, 직렬화, 그리고 스레드 동기화와 관련된 중요한 역할을 합니다.


volatile 키워드

volatile은 멀티스레드 환경에서 변수의 값을 메인 메모리에 직접 저장하고, 모든 스레드가 항상 최신 값을 읽도록 보장하는 역할을 합니다.

적용 대상 변수
주요 기능 캐시된 값을 사용하지 않고 항상 메인 메모리의 최신값을 읽음
주로 사용하는 경우 스레드 간 변수 값 공유 시 데이터 일관성 유지
public class SharedData {
    private volatile boolean flag = false;

    public void writer() {
        flag = true; // 값 변경 시 바로 메인 메모리에 반영
    }

    public void reader() {
        if (flag) {
            // flag가 true로 바뀌면 반드시 이 코드가 실행됨
        }
    }
}

 

단, volatile원자적 연산(atomic operation)을 보장하지 않으므로, 복합 연산이 필요하면 synchronized를 함께 사용해야 합니다.


transient 키워드

transient 키워드는 Java 기본 직렬화(ObjectOutputStream 등) 과정에서 특정 필드를 직렬화 대상에서 제외하고자 할 때 사용합니다.
즉, 직렬화 시점에 해당 필드는 저장되지 않으며, 역직렬화 후에는 기본값으로 초기화됩니다.

적용 대상 변수
주요 역할 Java 기본 직렬화 시 필드 제외

 

class User implements Serializable {
    String username;
    transient String password; // Java 직렬화 시 제외
}

transient 키워드 vs @JsonIgnore 어노테이션

구분 transient @JsonIgnore
적용 대상 변수 변수, 메서드
직렬화 대상 Java 기본 직렬화 (ObjectOutputStream) JSON 직렬화/역직렬화 (Jackson, Gson 등)
주요 역할 직렬화 시 필드 제외 JSON 변환 시 필드 제외
사용 시점 Java 직렬화를 직접 사용하는 경우 REST API JSON 응답/요청 시 민감 데이터 숨길 때
사용 예시
transient String password;
@JsonIgnore
private String password;
비고 Java 기본 직렬화에 한함 JSON 변환 제어에 특화

 

실무에서는 REST API 응답 시 민감 정보를 숨기기 위해 @JsonIgnore를 많이 사용하며, Java 기본 직렬화 목적이라면 transient를 사용합니다.


synchronized 키워드

synchronized는 멀티스레드 환경에서 임계 영역(critical section)을 보호하여, 동시에 한 스레드만 접근 가능하도록 하는 동기화 기능을 제공합니다.

적용 대상 메서드, 코드 블록
주요 기능 스레드 간 동시 접근 방지 및 데이터 일관성 유지
사용 목적 공유 자원 접근 시 레이스 컨디션 예방

 

public class Counter {
    private int count = 0;

    public synchronized void increment() {
        count++; // 이 메서드는 한번에 한 스레드만 접근 가능
    }

    public int getCount() {
        return count;
    }
}

또는 특정 코드 블록만 동기화할 수도 있습니다.

public void add(int value) {
    synchronized(this) {
        count += value;
    }
}

주의할 점은 동기화 과도 사용 시 성능 저하가 발생할 수 있으므로, 필요한 부분에만 최소한으로 적용하는 것이 좋습니다.


요약 비교표

키워드 적용 대상 주요 역할 사용 시기
volatile 변수 메인 메모리와 변수 값 동기화, 최신 값 보장 멀티스레드 변수 값 공유 시
transient 변수 Java 기본 직렬화 시 필드 제외 객체 직렬화 시 제외 필드 지정
synchronized 메서드, 블록 임계 영역 보호, 동시 접근 방지 멀티스레드 환경에서 데이터 무결성 필요할 때

 


실무 팁

  • volatile는 원자적 연산이 아닌 단순 값 변경 공유에 적합하며, 복합 연산은 synchronized를 병행 사용하세요.
  • transient@JsonIgnore는 각각 직렬화 환경(Java 기본 직렬화 vs JSON)에서 필드 제외를 위해 사용하므로, 목적에 맞게 선택해야 합니다.
  • synchronized는 꼭 필요한 부분에 최소한으로 사용해 성능 저하를 방지하세요.

마무리

Java의 volatile, transient, synchronized 키워드는 모두 멀티스레드 처리, 직렬화, 데이터 일관성 유지 등에서 매우 중요한 역할을 합니다.
각 키워드가 가진 특징과 차이점을 이해하고, 상황에 맞게 적절히 활용하는 것이 안정적이고 효율적인 Java 프로그래밍의 핵심입니다.

반응형
반응형

Java에서는 특정한 예약어(keywords)들을 사용해 클래스/메서드/변수의 속성을 제한하거나 제어할 수 있습니다.
이 글에서는 가장 많이 사용되는 final, static, this, super 키워드에 대해 정리하고, 언제 어떻게 사용하는지 코드 예제와 함께 비교해보겠습니다.


final 키워드

final수정 불가(변경 불가능)를 의미합니다. 변수, 메서드, 클래스 등 다양한 곳에 사용됩니다.

적용 대상 의미
변수 값이 한 번만 할당 가능 (상수처럼 사용)
메서드 오버라이딩 불가
클래스 상속 불가

 

final int MAX_COUNT = 10;
MAX_COUNT = 20; // 컴파일 에러

final class Animal {}
class Dog extends Animal {} // 컴파일 에러 (상속 불가)

class Parent {
    final void speak() {}
}
class Child extends Parent {
    void speak() {} // 에러: final 메서드는 오버라이드 불가
}

static 키워드

static공용(클래스 단위) 개념입니다. 인스턴스 생성 없이 사용 가능하고, 메모리 효율성을 높입니다.

적용 대상 의미
변수 모든 객체가 공유하는 클래스 변수
메서드 객체 없이 클래스명으로 호출 가능
블록 클래스 초기화 시 자동 실행되는 정적 블록

 

class Counter {
    static int count = 0;

    Counter() {
        count++;
        System.out.println(count);
    }
}

Counter c1 = new Counter(); // 1
Counter c2 = new Counter(); // 2

this 키워드

this현재 인스턴스 자신을 참조합니다. 주로 변수 이름 충돌 해결이나 코드의 가독성을 높이기 위해 명시적으로 사용합니다.

class Person {
    String name;

    Person(String name) {
        this.name = name; // 왼쪽: 인스턴스 변수, 오른쪽: 매개변수
    }

    void print() {
        System.out.println(this.name); // 현재 인스턴스의 name
    }
}

super 키워드

super부모 클래스 요소에 접근할 때 사용합니다. 생성자 호출이나 오버라이드 메서드 안에서 사용됩니다.

class Parent {
    String name = "부모";
    void greet() {
        System.out.println("안녕 from 부모");
    }
}

class Child extends Parent {
    String name = "자식";

    void greet() {
        super.greet(); // 부모 메서드 호출
        System.out.println(super.name); // 부모 변수 접근
    }
}

요약 비교표

키워드 사용 위치 주요 기능
final 변수/메서드/클래스 값/상속/오버라이드 불가로 제한
static 변수/메서드/블록 클래스 단위로 공유, 인스턴스 없이 접근
this 인스턴스 내부 현재 객체 참조, 변수 충돌 해결, 코드 가독성을 위한 명시적 사용
super 상속 구조 내부 부모 클래스 요소 참조 (메서드, 변수 등)

 


실무 팁

  • final 변수는 상수처럼 사용하며, static final 조합으로 전역 상수를 선언할 수 있습니다.
  • static 메서드는 공용 기능을 제공하는 유틸성 클래스에서 많이 사용됩니다.
  • this는 주로 생성자 파라미터 명과 멤버변수 이름이 같을 때 사용하거나, 코드 가독성을 위해 명시적으로 사용할 때 사용합니다.
  • super는 오버라이딩한 메서드에서 부모의 로직을 확장할 때 유용합니다.

마무리

Java의 핵심 키워드인 final, static, this, super는 객체 지향 프로그래밍에서 매우 자주 사용됩니다.
각각의 의미와 쓰임을 정확히 이해하고, 상황에 맞게 사용하는 것이 중요합니다.

반응형

'개발새발 > Java' 카테고리의 다른 글

Java의 핵심 키워드: volatile, transient, synchronized  (1) 2025.06.16
Java의 메모리 영역  (0) 2024.05.26
인터페이스 vs 추상클래스  (0) 2024.05.26
반응형

자바 변수의 종류

변수는 크게 네 종류로 변수의 선언된 위치에 따라서 클래스변수, 인스턴스변수, 지역변수, 매개변수로 나뉜다.

public class Main {
	public static void main(String[] args) { // 매개변수
    	int num = 0; // 지역변수
    }
}

public class Page {

	private int state = 0; // 인스턴스 변수
    public static int page = 10; // 클래스 변수
    public int get() {
    	return state;
    }
}
변수명 선언위치 설명 저장 메모리
클래스 변수
(class variable)
= static 변수
클래스 영역 클래스 영역에서 타입 앞에 static이 붙는 변
객체를 공유하는 변수로 여러 객체에서 공통으로 사용하고 싶을 때 정의
Method
인스턴스 변수
(instance variable)
클래스 영역에서 static이 아닌 변수
개별적인 저장 공간으로 객체/인스턴스마다 다른 값 저장 가능

* 객체/인스턴스 생성만하고 참조 변수가 없는 경우 가비지 컬렉터에 의해 자동 제거됨
Heap
지역 변수
(local variable)
메서드 영역 메서드 내에서 선언되고 메서드 수행이 끝나면 소멸되는 변수
초기값을 지정한 후 사용할 수 있음
Stack
매개 변수
(parameter)
메서드 호출 시 '전달하는 값'을 가지고 있는 인수
(지역 변수처럼 선언된 곳부터 수행이 끝날 때까지 유효함)

 

자바의 메모리 영역

자바 프로그램을 실행하게되면, JVM은 OS로 부터 메모리를 할당 받고 Method, Stack, Heap 각 세 영역에 맞춰서 할당하게 된다.

 - 메소드 (Method) 영역 : 전역변수와 static 변수를 저장하며, Method 영역은 프로그램의 시작부터 종료까지 메모리에 남아있음

 - 스택 (Stack) 영역 : 지역변수와 매개변수 데이터 값이 저장되는 공간이며, 메소드가 호출될 때 메모리에 할당되고 종료되면 메모리가 해제. LIFO (Last In First Out) 구조를 갖고 변수에 새로운 데이터가 할당되면 이전 데이터는 지워짐

 - 힙 (Heap) 영역 : new 키워드로 생성되는 객체 (인스턴스), 배열 등이 Heap 영역에 저장되며, 가비지 컬렉션에 의해 메모리가 관리

 - PC Register : JVM이 실행하고 잇는 현재 위치를 저장하며, 스레드가 생성되면서 생기는 공간

 - Native Method Stack : Java가 아닌 다른 언어로 구성된 메소드 실행이 필요할 때 사용되는 공간

 

자바의 각 메모리 영역이 할당되는 시점?

 - Method : JVM 동작 후 클래스가 로딩 될 때 생성

 - Stack : 메소드가 호출될 때 할당

 - Heap : 런타임시 할당

 

원시 타입 vs 참조 타입의 메모리 영역

원시 타입 : Stack에 값이 그대로 저장되는 타입 / 참조가 없어서, 빠르게 값에 접근 가능

참조 타입 : Stack에 Heap의 어딘가를 가리키는 주소가 저장

 

반응형
반응형

인터페이스 vs 추상클래스 비교

인터페이스 (implements) : 인터페이스에 정의된 메서드를 각 클래스 목적에 맞게 기능을 구현

추상클래스 (extends) : 자신의 기능들을 하위 클래스로 확장

  추상 클래스 인터페이스
사용 키워드 abstract interface
사용 가능 변수 제한 없음 static final (상수)
사용 가능 접근 제어자 제한 없음 (public, private, protected, default) public
사용 가능 메소드 제한 없음 abstract method, default method, static method, private method
상속 키워드 extends implements
다중 상속 가능 여부 불가능 가능 (클래스에 다중 구현, 인터페이스 끼리 다중 상속)
공통점 1. 추상 메소드를 가지고 있어야한다.
2. 인스턴스화 할 수 없다. (new 생성자 사용 x)
3. 인터페이스 혹은 추상 클래스를 상속받아 구현한 구현체의 인스턴스를 사용해야 한다.
4. 인터페이스와 추상클래스를 구현, 상속한 클래스는 추상 메소드를 반드시 구현하여야한다.

 

사용 시기 및 목적

추상클래스 : 상속 관계 시, 부모나 조상클래스를 상속하는데 기능까지 같은 경우 추상클래스 사용

                     (상속, 확장하여 사용)

인터페이스 : 상속 관계 시, 부모나 조상클래스를 상속하는데 다른 기능이 필요할 경우 인터페이스 사용

                     (동일한 사용방법과 동작을 보장하기 위해 사용)

반응형

+ Recent posts