변수 scope | 자바 입문강좌 16

변수 scope

변수 scope 에 대해 알아보겠습니다. 변수 scope 는 모든 프로그래밍 언어에 관련되어 있습니다. 어떤 변수라도 범위와 수명이라는 개념이 있습니다. 즉 변수가 있을 공간과 시간이 필요합니다.

변수의 범위를 크게 두가지로 나누면 지역변수와 전역변수로 나눌 수 있습니다. 영문으로는 Local 과 Global 이웃나라 일본에서는 국소변수, 광역변수라는 용어를 사용하기도 합니다.

이 아이디어에서 따져볼 점은 변수의 범위를 왜 제한하느냐? 입니다. 그냥 프로그램 하나의 데이터를 모두 한 곳에다 때려넣고 프로그래밍을 하는게 더 편하지 않을까?

더 편하다, 더 좋다. 라는 식으로 나누기는 힘들겠지만 프로그램의 성능, 안정성, 노동의 능률 등 요소를 고려합니다.

수십년간 경험으로 얻은 데이터에서 함수의 지역변수 개념이 프로그램머들의 실수를 줄이고 프로그램의 품질을 높이는데 기여한 것으로 밝혀졌습니다.

프로그래머는 하나의 함수를 만들 때 웬만하면 그 안에서 모든 것을 해결하는게 좋습니다. 범위를 좁힐수록 프로그램의 품질이 좋아진다는 것 입니다.

그렇다면 어떻게 한정할 수 있는지 알아보겠습니다.

변수 scope
변수 scope

지역변수(Local Variable)

main 함수에서 선언한 age 변수를 옆의 함수에서 사용하려고 합니다. 그런데 사용할 수가 없습니다.

    public static void main(String[] args) {
        int age;
        String name;
        showSomething();
    }
    public static void showSomething(){
//        age = 10;
        System.out.println("show something!");
    }

에러메시지가 다음과 같습니다. cannot find symbol 심볼을 찾을 수 없습니다. 심볼이 식별자(identifier) 의 이름을 말하는 것입니다. 변수가 자신의 지역에 들어있지 않기 때문입니다.

java: cannot find symbol
  symbol:   variable age

자바에서 { } 의 안에서 변수를 선언하면 지역변수로 인식합니다.

아래와 같은 경우 지역변수 인데

        {
            int test = 1;
        }

바깥에서는 사용할 방법이 없습니다.

그래서 안에다가 클래스를 만들어서 (inner class) 인스턴스를 만들면 사용할 수 있으나 inner class 인 경우 또 static 키워드를 사용할 수 없기에 복잡하고 번거롭기만 한 코드로 변합니다.

    public static void showSomething(){
        System.out.println("show something!");

        class myScope
        {
            int test = 1;
        }
        myScope mm = new myScope();
        mm.test = 10;
        System.out.println(mm.test);
    }

처음부터 변수의 범위를 제대로 설계해두는게 좋습니다. 어떤 것을 지역변수로 할건지 어떤 것을 전역변수로 할 것인지.

전역변수(global variable)

객체지향프로그래밍인 자바에는 전역변수라는 개념은 없습니다. 자바의 변수 범위는 크게 지역변수와 인스턴스변수, static 변수 세가지 입니다.

허나 이렇게 보면 자바부터 프로그래밍을 시작한 사람들에게는 큰 그림이 잘 안보이기 때문에 전역변수 개념을 설명하도록 합니다.

C언어의 예를 들면 main 함수 바깥쪽 전처리기가 있는 영역에서 선언하는 변수가 전역변수입니다. main 함수의 첫줄부터 프로그램이 시작되기에 이미 전역변수는 데이터영역에 로드가 되있습니다. 그리고 main 함수가 끝나고 프로그램 종료시까지 변수를 메모리에 유지합니다.

전역변수를 main 이 아닌 함수도 사용할 수 있는 이유입니다. 하지만 전역변수의 사용을 권장하는 경우는 거의 없는데요. 포인터변수로 전달하는게 너무 귀찮거나 할 때 한정적인 범위에서 한개, 두개 정도의 전역변수를 사용합니다. 그것도 좀 간단한 프로그램을 만들 때 그렇게 사용할 수 있습니다.

자바에서도 이와 비슷한 범위가 있습니다. 바로 static 변수입니다.

자바 static 변수 | 자바 입문강좌 14

클래스와 인스턴스들이 공유를 하죠. 클래스가 인스턴스들의 대장이라면 대장기가 하나 가질 수 있는 것 입니다. 어쨋든 다른 namespace 에서는 사용할 수 없으므로 그들 에게는 전역변수나 마찬가지입니다.

static 설계의 주의사항

전역변수의 문제가 변수 이름만 띡 써놓아서 나중에 디버그를 하다가 어느 함수 안에서 전역변수가 띡 나온 경우 ‘야 이거 어디서 사용하고 있는거냐?’ 라는 멘탈붕괴 상황에 모두 말을 잊게 만들기도 합니다.

전역변수는 아니지만 static 변수도 꼭 사용할 곳에만 사용해야 합니다. 특히 static 변수는 프로그램이 런타임에 들어가는 순간부터 끝날 때까지 메모리를 잡고 있으므로 설계단계에서 static 을 얼마나 사용할 수 있는지 파악이 끝나야 사용할 수 있습니다.

365일 돌리는 게임서버라고 생각하면 static 변수는 사용자가 접속하건 말건 늘어난 가입자 숫자만큼 잡고 있을지도 모릅니다.

이런 문제를 해결하는 방법은 여러가지가 있으나, 암튼 이전 학습에서 static 개념을 이야기할 때 현재 변수가 어떤 메모리를 점유하고 있으며 얼마나 수명이 되었는가? 인스턴스의 GC(Garbage Collection) 상황과 함께 static 변수들의 상황에 대해서도 체크해야 합니다.

프로그램을 작성하는 것은 사람의 노동력이 주로 들어가지만,
개발된 프로그램을 구동시키는 하드웨어는 비쌉니다.

그래서 유지보수하는 시간이 많이 들어갑니다.
비싼 하드웨어 자원에 낭비는 치명적이기 때문에
베타 테스트를 디버깅과 최적화까지 해야하기 때문이죠.

간단한 코드 테스트시에는 다음과 같은 static 을 사용이 편리하기도 합니다.

public class Main {
    public static void main(String[] args) {
        myStatic.showMemberList();
    }
}
class myStatic{
    private static int count = 0;
    private static String name = "John Doe";
    public static void showMemberList(){
        System.out.println(count);
        System.out.println(name);
    }
}

인스턴스 변수(멤버변수)의 범위

인스턴스는 실행시간에 힙 메모리에 동적으로 할당된다고 설명했습니다.

이들의 범위는 명확합니다. 일단 인스턴스가 생성되기 전에 없죠.

사용도 도트연산자 . 로 인스턴스만 사용할 수 있기 때문에 어차피 다른 곳에서 사용할 수 없습니다. 멤버(소속)라는 사실 자체만으로도 이미 scope 가 확정되버린 것 입니다. 또 접근제어자가 달려있어서 사용할 수 있는 메소드가 이미 정해져 있죠.

이는 캡슐화를 지향하는 객체지향 프로그래밍의 특징이기도 합니다.

아래와 같이 인스턴스 변수는 범위가 이미 정해져 있습니다,

public class Main {
    public static void main(String[] args) {
        myMember m1 = new myMember();
        m1.serialNumber = 1001;
        m1.connectionName = "first connection";
        m1.showMemberList();
    }
}
class myMember{
    int serialNumber;
    String connectionName;
    public void showMemberList(){
        System.out.println(this.serialNumber);
        System.out.println(this.connectionName);
    }
}

앞에 인스턴스 참조를 보면 어디 소속인지 확인이 가능합니다. 전역변수가 문제가 되었던게 갑자기 serialNumber 이렇게 하늘에서 떨어졌기에 알수가 없는 것 이었습니다.

디버거로 추적하면 어디서 왔는지는 알 수 있지만 그렇게 하면 너무 시간이 오래 걸립니다. 이 코드를 누군가 유지보수한다는 생각이 있었다면 그렇게 하지 않았을 겁니다.

요약

이 포스팅에서 변수 scope (변수 유효 범위) 라는 대단히 추상적이고 어려운 내용에 대하여 커버하였습니다.

혹시 이해가 잘 가지 않는다면 너무 걱정할 필요는 없습니다. 자바로 프로그래밍을 시작했다면 좀더 컴퓨터구조에 대한 배경지식을 쌓는 것을 권합니다.

컴퓨터공학의 배경지식은 매우 방대하고 또 앞으로 배워야 할 것들이 계속 쌓이고 있어서 이 분야에 있는 사람들은 실력과 지위를 막론하고 매일 새로운 지식을 공부합니다. 입문 강좌에서 제시하는 아이디어는 전체 지식에 비하여 아주 작은 부분에 불과합니다.

입문 단계에서는 프로그래밍을 지속할 수 있는 근육과 체력을 기르는 것에 역점을 두는 것이 좋습니다. 기초가 충실할 수록 중급 단계에서 빨리 도약할 수 있고 기초가 부실하면 중급단계를 버티는게 어렵습니다.

자바 입문강좌도 어느새 16화가 되어서 조금 내용을 도전적으로 강화하고 있습니다.

외부참조문서

C++ | 함수 | 지역변수, 전역변수 | 국소변수, 광역변수 | 로컬변수 | 글로벌변수 변수 scope

2 thoughts on “변수 scope | 자바 입문강좌 16”

Leave a Comment