gimmickbutreal

[CS/Java] 정적(Static) 변수 본문

Algorithm/Java

[CS/Java] 정적(Static) 변수

isshosng 2022. 7. 17. 01:55

자바 언어에서는 객체를 통하지 않고 사용할 수 있는 멤버를 생성하는 것이 가능합니다.

이런 기능을 가진 멤버를 Static Member 즉, 정적 멤버라고 합니다.

 

정적 멤버는 클래스당 하나만 생성돼 모든 객체가 공유할 수 있습니다.

 

예시 사진

 

 

쉽게 비유를 한다면, 하나의 클라우드를 스마트폰, PC 등의 다양한 전자기기로 사용할 수 있습니다. 여기서 클라우드를 Static 변수라고 생각하시면 됩니다. 모든 객체(모든 전자기기)가 하나의 변수(클라우드)를 사용하니까요!

 

정적(Static)에 대해 제대로 이해하기 위해선 그 반대 개념인 인스턴스(instance)를 알아야 합니다.

 

먼저 클래스의 멤버는 인스턴스 멤버와 정적 멤버로 나누어집니다. 동일한 클래스를 이용하여 많은 객체들이 생성될 때 각각의 객체(인스턴스)들은 자신만의 변수를 가집니다. 이들 변수는 인스턴스마다 별도로 생성되기 때문에 인스턴스 변수라고 부르기도 합니다. 

 

간단한 예시로 살펴보겠습니다.

1
2
3
4
5
public class Woo0Woo {
    int age;
    int cute;
    boolean chamchamcham;
}
cs

위 우영우 클래스에서 age, cute, chamchamcham은 모두 인스턴스 변수입니다. 각 객체는 이들 변수에 대하여 별도의 기억 공간을 갖고 있으며 각기 다른 값을 갖고 있습니다.

 

이와의 반대로 모든 객체에 공통인 변수가 필요할 때 사용하는 게 정적 변수(static variable, class variable)입니다. 정적 변수는 하나의 클래스에 하나만 존재하며, 정적 변수는 객체보다는 클래스에 연결되어 있습니다. 그러므로 정적 변수를 클래스 변수라고 부르기도 합니다.

 

 

 

모든 객체들은 하나의 정적 변수를 공유하며, 정적 변수를 만들기 위해서는 변수를 정의할 때 앞에 static을 붙이면 됩니다. 정적 변수는 인스턴스를 생성하지 않아도 사용이 가능합니다.

1
2
3
4
5
6
public class Woo0Woo {
    int age;
    int cute;
    boolean chamchamcham;
    static int height;
}
cs

우영우 클래스에 정적 변수 height를 위와 같이 추가합니다. height 변수는 클래스마다 하나만 생성 됩니다. 이 때, 정적 변수는 객체가 생성되기 전에 생성됩니다.

만일 우영우 클래스의 정적 변수 height에 163을 대입하려면 아래처럼 코드를 입력하면 됩니다.

Woo0Woo.height = 163;

이와 같은 형식은 인스턴스 변수를 사용하는 형식과 얼핏 비슷하게 보일 수 있지만, 객체 이름이 아니라 클래스 이름을 사용한다는 점이 다릅니다. 

 

그래서 정적 변수를 어느 상황에서 사용하는데? 라는 의문이 드실 수 있습니다. 현실에서 쓰이는 사례를 간단하게 코드로 보여드리겠습니다.

 

예를 들어서 멋쟁이사자처럼 백엔드 스쿨 1기 교육생들에게 수료증을 발급해준다고 가정해보겠습니다. 그럴려면 수료 예상 인원이 얼마나 있는지 파악해야 합니다. 이럴 때 정적 변수를 사용하면 편리합니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class LikeLion {
 
    private String name; // 교육생 이름
    private int age; // 교육생 나이
    private int id; // 수료증 번호
    static int numbers = 0// 교육생 수
 
    LikeLion(String n, int a) {
        name = n;
        age = a;
 
        id = ++numbers; // 교육생 수가 증가할 때마다 수료증 수도 증가
    }
}
 
public class Cert {
    public static void main(String[] args){
        LikeLion l1 = new LikeLion("최태승", 27);
        LikeLion l2 = new LikeLion("이승훈"26);
        LikeLion l3 = new LikeLion("정윤아"23);
 
        int nums = LikeLion.numbers; // 정적 변수
        System.out.println("발급된 교육증 수 = " + nums);
    }
}
cs

 

위의 코드에서 바로 numbers가 클래스 변수입니다. 클래스 변수는 그 클래스의 인스턴스를 만들지 않고서도 사용될 수 있습니다. 외부에서도 클래스 변수를 사용할 수 있으며 객체가 없으므로 클래스의 이름을 객체처럼 사용하여 접근합니다. 이처럼 객체를 사용하지 않고 사용하기 때문에 속도가 빠릅니다. 클래스가 메모리에 올라가는 시점에 생성돼 바로 사용이 가능하기 때문입니다.

 

이러한 장점에도 불구하고 단점도 있습니다.

먼저, 프로그램 종료시까지 메모리에 할당된 채로 존재한다는 점입니다. Java라는 언어는 JVM라는 기능이 존재하는데 여기서 Garbage Collector를 통해 사용하지 않는 메모리를 알아서 회수해주어 메모리 관리에 매우 편리합니다. 하지만, 이는 Heap 영역만 가능하며 Static 영역은 안타깝게도 이러한 JVM의 혜택을 누릴 수 없습니다.

 

 

 

또한 객체지향적이지 못하는 단점도 있습니다. 

Static은 애초에 객체를 생성하지 않고 클래스를 사용하기 때문입니다. 이러한 이유 때문에 Interface를 구현하는 데 사용할 수도 없습니다. 저는 프로그래밍에서 중요한 3가지를 꼽는다면 개발 시간, 결합도, 표준화라고 말하고 싶습니다. 클라이언트의 요구를 빠르게 충족시켜주어야 하며, 코드의 종속성을 줄여 유지보수를 높이고 정형화된 개발이 시장성이 있기 때문입니다. 이러한 점들을 Interface 특성을 활용해 극대화할 있어 자바에서의 Interface의 역할은 매우 중요하므로 매우 큰 단점입니다. >>이었으나 JAVA 8부터 가능

 

그럼에도 불구하고 고정된 메모리 영역을 사용하여 매번 인스턴스를 생성하며 낭비되는 메모리를 줄일 수 있고 객체를 생성하지 않고 사용이 가능해 빠르다는 확실한 장점이 있으므로 개발자들의 판단아래 유용할 때 사용한다면 좋습니다.

 

이번 포스팅에선 정적 변수에 대해서만 설명했으며, 추후 정적 메소드에 대해서도 포스팅 하겠습니다.

라이낸스 화이팅!

 

참고 링크

https://42place.innovationacademy.kr/archives/8470

https://coding-factory.tistory.com/524