프로그래밍을 하다보면 private, public, protected, internal 과 같은 키워드들을 보신 적이 있으실 겁니다.

사전적 의미로는 사설, 공용, 보호된, 내부적이란 의미를 가지고 있습니다.


그 사전적 의미대로입니다.

private 의 경우, 정의된 형식 내에서만 접근이 가능하게 되있습니다.

public class MyClass {
    private Int32 privateMember;
}


MyClass 클래스에 있는 privateMember 멤버에는 어떻게 접근이 가능할까요?

MyClass 클래스 내에서만 접근이 가능합니다.

정말 MyClass 내에서만 접근이 가능한지 보겠습니다.

public class MyClassInspector {
    public void PrintMember(MyClass mc) {
        Console.WriteLine("MyClass = {0}", mc.privateMember);
    }    
}


MyClassInspector 이란 클래스를 하나 만들고, PrintMember 메서드를 정의합니다.

그리고, 메서드 내에선 콘솔 출력창에 MyClass 의 privateMember 멤버를 출력하도록 되어있네요.

과연 이게 실행이 될까요? 아쉽게도 실행되지 않습니다.

컴파일 오류가 나오게 되죠. privateMember 멤버는 private 으로 선언되었기 때문에 접근이 불가능하다면서요..


왜 private 이란 것을 사용하는 걸까요? 답은 단순합니다.

외부로 노출되면 안되는/민감한 정보들에 대해서 사용합니다. 또는 혼란을 줄 수 있으니, 클래스 내부에서만 사용하기 위해서도 사용됩니다.

예를 한번 보도록 하겠습니다.

public class UserInfo {
    public String Name;
    public String Age;
    public DateTime BirthDay;
    private String UserID;
}


UserInfo 라는 클래스는 Name(이름), Age(나이), BirthDay(생일) 그리고 UserID(주민번호)를 저장하게 되어 있습니다.

이름이나 나이, 생일 같은 경우엔 외부에 노출되어도 크게 상관이 없지만 주민번호의 경우 그렇지 않습니다.

그래서 내부에서만 필요에 맞는 경우에 사용하도록 하고 외부로 노출되지 않도록 해주는 것이죠.



그럼 다음으로 public 을 살펴보도록 하겠습니다.

사전적 의미대로 '공용' 이란 의미를 가지고 있는 이 키워드는 어디서든 접근이 가능합니다.

public class MyClass {
    public Int32 privateMember;
}


MyClass 클래스도, 클래스의 privateMember 멤버도 모두 public 으로 선언되었습니다.

public 키워드를 사용하여 선언할 경우 클래스의 내부, 외부 모든 곳에서 접근이 가능합니다.


왜 public 을 사용할까요?

외부에서 접근이 가능하게 함으로써, 확장된 기능을 만들거나 상속을 하거나.. 또는 필요한 기능들을 사용하기 위해서입니다. 이렇게 함으로써 더 유연한 프로그램 개발이 가능하게 됩니다.


그럼 이제 protected 를 살펴보도록 하겠습니다.

사전적 의미로는 '보호된' 이란 의미를 가지고 있는데, 이 키워드는 '상속 클래스' 및 선언 클래스에서만 접근이 가능합니다.

상속 클래스에 대해서 길게 설명은 하지 않겠습니다. 짧게 비유해서 말하자면, 부모와 자식의 관계입니다.

A 클래스를 B 클래스가 상속하게 되면, A 클래스는 B 클래스의 부모, B 클래스는 자식이 되는셈이죠.

public class Info {
    protected String Name;
    protected String Address;
    protected String Type;
}


위처럼 정의된 Info 라는 클래스의 모든 멤버들은 모두 'protected' 로 선언되었습니다.

위에서 말씀드렸듯, 상속 클래스 및 선언 클래스에서만 접근이 가능하므로, Info 클래스 내에선 사용이 가능하지만 외부에선 접근이 불가능합니다. 하지만, Info 클래스를 상속한 클래스에선 사용이 가능합니다.

public class CarInfo : Info {
    public String GetType() {
        return Type;
    }
    public void SetType(String newType) {
        Type = newType;
    }
}


이런식으로, Info 클래스를 상속한 CarInfo 라는 클래스에선 Info 클래스의 protected 멤버에 접근이 가능합니다.

왜 protected 를 쓸까요? 기능 보완 및 커스터마이징때문입니다.

System.Windows.Forms.Control 클래스만 봐도 외부에서 접근할 수 없는 WndProc 메서드를 Control 클래스를 상속하는 것 만으로 WndProc 메서드에 접근이 가능하게 됩니다. 이렇듯 protected 접근자는 기능 추가, 보완 등을 위해서 사용됩니다.


마지막으로 internal 접근자에 대해서 알아보도록 하겠습니다.

internal 이란 단어는 '내부적인' 이라는 사전적인 의미를 가지고 있는데요. 말 그대로입니다.

internal 접근자가 지정된 변수, 형식은 선언된 어셈블리 내에서만 접근이 가능합니다.

이게 무슨말이냐면, 'TestLib' 이란 프로젝트를 만들고 internal 로 선언한 변수들이나 형식은 TestLib 프로젝트 내에서만 접근이 가능하고, 외부에선 접근이 불가능하게 됩니다.

/* Assembly: TestApp0 */
namespace TestApp0 {
    internal static class InternalClass {
        internal static Int32 InternalMethod() {
            return 777;
        }
    }
    
    public class TestClass {
        public static Int32 TestMethod() {
            /* 같은 어셈블리이므로 접근이 가능함 */
            return InternalClass.InternalMethod();
        }
    }
}

/* Assembly: TestApp1 */
namespace TestApp1 {
    public class TestClass {
        public static Int32 TestMethod() {
            // InternalClass 에 접근 불가,
            // 서로 다른 어셈블리임
            TestApp0.InternalClass ic;
        }
    }
}


internal 접근자는 외부에서의 접근은 제한하고 프로그래밍되는 어셈블리에서는 public 과 같은 효과를 갖게 하려고 할 때 사용합니다. 같은 어셈블리 내에서는 public, 다른 어셈블리에선 private 으로 되는셈이죠.

internal 접근자는 도움 클래스(Helper Class) 등을 만드는데 주로 사용됩니다.


이로써 접근 한정자에 대한 설명을 마치도록 하겠습니다.

긴 글 읽으시느라 고생 많으셨습니다.


감사합니다!


* P.S. protected internal 이란 한정자도 있습니다. protected 한정자와 internal 한정자를 합쳐놓은 것으로써, 어셈블리 내의 상속 클래스에서만 접근이 가능합니다.

+ Recent posts