주인장의 프로그래밍 개발 공부방

[자바 프로그래밍 기본] 2. 클래스의 구성 (1) 멤버 본문

Java/자바 프로그래밍 기본

[자바 프로그래밍 기본] 2. 클래스의 구성 (1) 멤버

거신 2023. 1. 5. 21:39

지난 시간에는 클래스(Class)가 무엇인지에 대해서 알아봤고

간단하게 클래스를 생성하는 방법에 대해서 알아봤었다.

그런데 클래스를 생성한다고 해도 클래스는 무엇으로 구성되어 있으며,

무엇을 어떻게 넣어야 하는지 알아야

만들어서 써먹든지 말든지 할 수 있을 것이다.

 

스티브 잡스가 무대에 나와서 "iPhone"이라고 했을 때

관객들은 환호하겠지만

잡스가 거기에서

아이폰이 정작 무엇인지, 뭘 할 수 있는지, 무슨 기능이 들어있는지 설명하지 않고 발표를 끝냈다면

환호하던 관객들은 순식간에 대략 정신이 멍해졌을 것이다.

 

그러니 주인장도 이 글을 읽는 여러분들의 정신이 멍해지지 않도록

클래스가 무엇인지에서 끝내지 않고

클래스 안에는 무엇이 들어있으며,

어떤 걸 할 수 있으며,

어떻게 만드는지

에 대해서 알려주려고 한다.

 

그래서 이번 시간에는 클래스 안에는 어떤 것들이 있는지

그리고 어떤 역할을 하는지에 대해서 알아보고자 한다.

이들을 클래스의 멤버라고 지칭할 텐데

클래스의 멤버를 이해하고 나면 클래스를 생성하는 것부터 시작해

어떻게 이용할 것인가에 대한 전반적인 이미지가 그려질 것이라고 생각한다.

 

목표 : 클래스의 멤버에 대해서 이해하고

전역 변수, 지역 변수, 클래스 멤버, 인스턴스 멤버가 무엇인지 이해할 수 있다.

 

1. 클래스의 구성

 

그렇다면 클래스가 무엇으로 구성되어 있는지부터 살펴보자.

앞서 만들어놨던 볼펜심 설계도를 가져오겠다.

 

예시 1)

class 볼펜심_설계도 {
    int 볼펜심_길이;
    String 볼펜심_형태;
    int 볼펜심_둘레;
    String 볼펜촉_모양;
    Color 잉크색;
    int 잉크양;

    public void 잉크를_뽑아냄() {
        
    }
}

여기에서 우리는 볼펜심_길이, 볼펜심_형태, 잉크양 등이

변수(Variable)라는 것도 이미 알고 있고

잉크를_뽑아냄()

메소드(Method, 함수)라는 것도 이미 알고 있을 것이다.

이 두 개가 바로 클래스를 구성하고 있는 요소가 되겠다.

 

이렇듯 클래스 내부에 필요한 변수메소드를 넣어두고

클래스를 인스턴스로 생성할 때 필요한 변수를 불러와서 값을 이용하거나

메소드를 호출해 해당 기능을 사용할 수 있는 것이다.

 

위와 같이 변수와 메소드들을 클래스의 멤버(Member)라고 지칭하며,

여기에서 변수와 상수를 하나로 묶어 멤버 필드(Member Field)라고 하며

그중 변수를 멤버 변수(Member Variable)라고 하고

메소드를 멤버 메소드(Member Method)라고 한다.

 

그림을 이용해서 좀 더 직관적으로 표현하자면 아래와 같이 표현할 수 있겠다.

 

그림 1)

우리가 객체지향, 클래스, 객체에 대해서 알아보면서 클래스가 어떤 역할을 했는지 앞에서 알아봤었는데

좀 더 압축해서 한 문장으로 설명한다면

설계도 역할을 하는 클래스는 자바 프로그램의 기본 단위라고 할 수 있겠다.

이렇듯 클래스라는 틀 안에서 코드가 생성되고 프로그램이 동작하는 것이기 때문에

자바를 처음 배울 때 만났던 변수와 메소드 등이 전부 클래스 안에 있어야 한다는 걸 어느 정도 눈치챘을 것이다.

변수든 메소드든 절대 클래스 밖에선 존재할 수 없는 것들이다.

 

2. 변수의 유효 범위(Variable Scope)

 

우리는 이전까지 변수라는 녀석에 대해서 단순히 하나의 값을 저장하는 것으로만 알고 있었는데

클래스에 대해서 알아가고 있기 때문에

여기에서는 변수를 이용할 수 있는 유효 범위(Variable Scope)에 대해서 알아보려고 한다.

 

변수는 어디에 선언되느냐에 따라서 유효 범위가 달라지게 된다.

여기에서 유효 범위선언된 그 변수를 호출해서 사용할 수 있는 범위를 말하는 것이다.

즉, 선언된 위치가 클래스 안에 멤버 변수로 선언되느냐,

아니면 메소드 안에서 변수로 선언되느냐에 따라서 어디에서는 호출할 수 있고

어디에서는 호출할 수 없는 것이다.

 

범위를 생각해보면 당연히 메소드는 클래스 안에 포함되어 있을 테니

클래스가 메소드보다 범위가 더 넓을 것이고

변수도 멤버 변수가 호출할 수 있는 범위가 더 넓을 것이라고 예상할 수 있을 것이다.

반대로 메소드 안에 선언된 변수는 사용할 수 있는 범위가 극히 좁을 것이다.

 

여기에서 클래스에서 선언된 멤버 변수전역 변수라고 표현한다.

그리고 메소드 안에서 선언된 변수지역 변수라고 표현한다.

단어 그대로 클래스 내부 전역에서 사용할 수 있기 때문에 전역변수,

메소드라는 국한된 지역 내에서만 사용할 수 있기 때문에 지역변수인 것이다.

 

그림 2)

그림에서도 알 수 있듯이 전역 변수의 경우에는 선언된 클래스 안에서라면

어디에서든 호출하고 사용할 수 있지만

지역 변수의 경우에는 선언된 메소드 안에서만 사용이 가능하고

메소드의 범위를 벗어나면 사용할 수 없다.

이렇듯 변수를 선언할 때  사용할 수 있는 유효 범위가 있으니

어디에 어떻게 선언할 것인가에 대한 부분을 생각하면서 프로그램을 작성해야 한다.

 

그런데 전역 변수는 변수가 생성되는 시점에 따라 두 가지로 나눌 수 있다.

그것이 바로 클래스 변수인스턴스 변수인데

이 둘은 자바 프로그램이 실행될 때 생성이 되는 시점도 다르고

올라가는 메모리의 위치도 다르다.

 

3. 클래스 멤버와 인스턴스 멤버

 

여기에서 우리는 static이라는 녀석을 만나게 된다.

static, 말 그대로 정적인 무언가를 지칭하는 자바의 예약어이다.

static은 변수에만 붙을 수 있는 것이 아니라 메소드에도 붙을 수가 있는데

이를 클래스 변수, 클래스 메소드라고 하고 합쳐서 클래스 멤버라고 표현한다.

 

혹여나 하는 말이지만 앞의 내용과 혼동하면 안 되는데

앞에서는 클래스"의" 멤버를 알아본 것이고 "클래스 멤버"에 대해서 설명한 것이 아니다.

그렇기 때문에 단순히 클래스 안에 선언된 변수와 메소드 전부

클래스 멤버라고 오해하면 안 된다.

이 들은 단순히 "멤버"인 것이지 "클래스 멤버"가 아니다.

정확하게 구분해서 이해할 필요가 있다.

(분명히 헷갈릴 가능성이 높기 때문에 가능하면 제대로 구분해서 이해하고 있길 바란다.)

 

다시 돌아와서 클래스 멤버멤버 필드멤버 메소드를 선언할 때

앞에 "static"을 붙여주면 된다.

이는 우리가 가장 많이 만나는 main 메소드에서 잘 나타나는데

main 메소드 안에 클래스 변수 값을 출력하는 코드를 간단하게 작성해 보았다.

 

예시 2)

public class Test {
    static String testText = "Hello World!";
   
    public static void main(String[] args) {
    	System.out.println(testText);
    }
}

예시 2)와 같이 선언하려는 변수 또는 메소드 앞에 static을 붙여주면

그 멤버는 클래스 멤버가 되는 것이다.

자바 프로그램의 시작점인 main 메소드가 바로 대표적인

클래스 메소드, 정적 메소드, static 메소드이다.

(전부 똑같은 말이다.)

 

앞에서도 잠깐 언급을 했지만 여기에 static이 붙으면서

인스턴스 변수와는 다르게 프로그램이 실행되면서 메모리에 올라가는 시점이 달라진다고 했었다.

이 블로그의 프로그래밍 기본 지식의 변수 챕터에서

참조형 변수를 다루면서 잠시 메모리 구조에 대해서 알아본 적이 있는데

그 그림에서 표현되지 않은 Static영역(클래스 영역, 메소드 영역)이라는 곳이 존재하는데

바로 클래스 멤버가 프로그램이 실행될 때 올라가는 위치인 것이다.

즉, 프로그램이 실행되고 종료되기 전까지 계속해서 남아있는 멤버인 것이다.

 

그림 3)

Stack위에 공간 있어요!!!!!!!

(그림이 그렇다는 거지 실제 메모리 구조가 이러한 형태로 되어 있는 게 아니다.)

 

반대로 인스턴스 변수, 인스턴스 멤버Static영역이 아닌 Stack영역, Heap영역에 위치하고

이는 인스턴스로 생성이 되거나 호출이 되면 그제서야 만들어지는 멤버라는 뜻이기도 하다.

 

이러한 특징 때문에 클래스 멤버 인스턴스 멤버를 혼용해서 코드를 작성할 때 제약조건이 생기게 된다.

 

예시 3)

public class Test {
    String testText = "Hello World!";
   
    public static void main(String[] args) {
    	System.out.println(testText);
    }
}

위의 코드는 멤버 변수인 testText에서 static을 지운 것뿐인데

해당 코드는 에러를 뿜뿜하게 된다.

생각해보면 정말 간단한 이유 때문이다.

 

main 메소드는 static으로 만들어진 클래스 메소드, 정적 메소드이다.

즉, 프로그램이 실행되면 Static영역에 위치하는 메소드인 것이다.

그런데 main 메소드의 내부를 잘 살펴보니 어라?

testText라는 인스턴스 변수가 위치하고 있다.

인스턴스 변수, 인스턴스 멤버는 인스턴스가 생성되어야 생성이 된다고 했으니

프로그램이 실행되고 Static영역에 위치하는 시점에서는 testText가 생성조차 되지 않은 상태인 셈이다.

그러니 만들어지지도 않은 녀석을 메모리에 위치시키려고 하니 여기에서 에러가 발생하는 것이다.

그래서 코드를 작성하는 컴파일러 단계에서

이거 백퍼 프로그램 실행하면 에러 나니까 testText를 지우든지, 아님 static으로 선언하든지 해라라고

알려주는 것이다.

이렇게 해당 멤버의 생성 시점에 따라서 오류가 발생할 수도 있으니 꼭 이해해주길 바란다.

 

예시 4)

public class Test {
    static String testText = "Hello World!";
    int testNumber = 10;
   
   // 인스턴스 메소드의 경우에는 내부에 클래스 변수든 인스턴스 변수든 뭘 써도 상관없다.
    public void start() {
    	System.out.println(testText);
        System.out.println(testNumber);
    }
}

반대로 이를 제외한 경우에는 문제가 없다는 것도 알아만 보고 넘어가자.

여기까지 이해했다면 예시 4)에 왜 문제가 없는지 잘 알 것이라고 믿어 의심치 않는다.

 

4. 정리

 

앞서 클래스와 객체에 대해서 알아봤으니 이제 클래스를 직접 만들어보기 위해서

우선 클래스가 어떻게 구성되어 있는지에 대해서 살펴봤다.

클래스는 자바 프로그래밍의 기본 단위이기도 한데

우리가 알고 있던 변수와 메소드들은 모두 클래스에 포함되어 있는 요소인 셈이다.

이들을 우리는 클래스의 멤버라고 표현하는데

클래스 안에 선언된 변수와 상수를 통틀어 멤버 필드라고 하며,

특히 변수는 멤버 변수라고 지칭한다.

메소드는 멤버 메소드라고 하며 이들 멤버는 절대 클래스 밖에선 존재할 수 없다.

 

멤버 필드, 멤버 변수의 경우에는 클래스 내부에서 이용될 수 있는

유효 범위가 존재하는데 어디에서 선언되느냐에 따라서 범위가 달라지게 된다.

클래스 상에 선언된 변수는 선언된 클래스 내부 어디에서나 접근이 가능하고

사용이 가능한데 이를 전역 변수라고 한다.

그리고 클래스 내부의 멤버 메소드 내부에서 선언된 변수는

해당 멤버 메소드 내에서만 접근과 사용이 가능하고 멤버 메소드 외에서는 사용할 수 없다.

그리고 이 변수를 지역 변수라고 한다.

 

그리고 전역 변수멤버 메소드

생성되는 시점에 따라서 각각 클래스 멤버, 인스턴스 멤버로 구분할 수 있는데

변수나 메소드를 선언할 때 앞에 static을 붙여 선언하면 클래스 멤버(정적 멤버, Static 멤버)로 생성할 수 있다.

클래스 멤버는 프로그램이 실행될 때 메모리의 Static 영역에 올라가서 생성되고

프로그램이 종료되기 전까지 계속 남아있게 되고

인스턴스 멤버는 인스턴스가 생성되거나 호출되는 시점에서 생성되기 때문에

메모리의 Stack 영역이나 Heap 영역에서 생성된다.

마지막으로 클래스 멤버인스턴스 멤버는 생성되는 시점이 다르기 때문에

클래스 변수를 인스턴스 변수 또는 인스턴스 메소드에 포함할 수 없다는 특징도 있다.

 

여기까지 읽으면서 궁금한 점이 많이 생겼을 것이라 생각한다.

이제 클래스의 멤버에 대해서 알아봤고

각 멤버들의 생성되는 시점과 변수의 유효 범위까지 알아봤으니

다음번에는 멤버 변수를 초기화하는 방법에 대해서 알아보도록 하자.

Comments