CodeGym /행동 /C# SELF /캡슐화와 접근 제한자

캡슐화와 접근 제한자

C# SELF
레벨 17 , 레슨 0
사용 가능

1. 들어가기

현대 자동차를 설계한다고 상상해봐. 내부에는 수백 개의 복잡한 부품, 민감한 전자장치, 미세한 세팅들이 있지. 아무나 엔진 컨트롤러에 손대서 나사 돌리면 안 되는 건 당연하지. 만약 아무나 막 만지면, 차가 이상하게 움직일 수도 있고, 누가 뭘 망가뜨렸는지 찾으려고 정비소에서 머리 아플 거야.

프로그래밍도 똑같아. 클래스를 만들 때, 내부를 아무나 건드리지 못하게 보호하고 싶지? 누가 실수로 중요한 데이터를 망치거나, 외부에서 몰라도 되는 메서드에 간섭하면 안 되니까. 이게 바로 캡슐화의 핵심이야. 캡슐화는 객체지향 프로그래밍의 세 가지 핵심 원칙 중 하나야.

캡슐화는 구현 세부사항을 숨기고, "밖에서" 뭘 쓸 수 있고, 뭘 숨길지 명확하게 정해주는 거야. 예를 들어, 사용자는 글로브박스는 열 수 있지만, 보닛은 잠가두는 것처럼. 클래스가 외부 코드에 어떤 데이터를 보여줄지, 어떤 건 비밀로 할지 스스로 결정하는 거지. 그래서 코드가 더 믿을만하고, 논리적이고, 유지보수도 쉬워져.

좀 더 엄밀하게 말하면, 캡슐화는 데이터(필드)와 그 데이터와 관련된 동작(메서드)을 하나의 구조로 묶고, 객체 내부 구성요소에 직접 접근을 제한하는 방법이야.

2. 접근 제한자: 내 영역 지키기

C# (그리고 다른 OOP 언어들)에서 캡슐화접근 제한자로 구현돼. 이건 클래스의 멤버(필드, 메서드, 프로퍼티 등)가 어디서 접근 가능한지 정해주는 "라벨" 같은 거야.

이미 몇 번 봤겠지만, 다시 한 번 정리하고, 몇 가지 더 추가해볼게:

제한자 접근 가능...
public
모두! 프로젝트 내 모든 코드(그리고 프로젝트가 라이브러리면 외부에서도)
private
오직 이 클래스 내부에서만
protected
이 클래스와 모든 자식 클래스에서
internal
현재 어셈블리(프로젝트) 내에서만
protected internal
현재 어셈블리 또는 자식 클래스에서
private protected
현재 어셈블리 내 자식 클래스에서만

이번 강의에서는 가장 자주 쓰는 public, private에 집중하고, protected는 간단히만 다룰게. 머리 아프지 않게!

내부와 외부를 나누기

클래스 Dog를 한번 만들어보자:


public class Dog
{
    public string Name;
    public int Age;

    public void Bark()
    {
        Console.WriteLine($"{Name} 말한다: 멍멍!");
    }
}

여기서는 모든 필드와 메서드가 public으로 선언돼 있어. 즉, 아무나 강아지 이름이나 나이를 바꿀 수 있다는 뜻이야:

Dog rex = new Dog("렉스", 5);
rex.Name = "샤릭"; // 갑자기 이름이 바뀜!
rex.Age = -999;     // 나이에 심각한 문제 발생

근데 Name이랑 Age는 진짜 중요한 데이터라 아무나 막 바꾸게 하고 싶지 않잖아.

이렇게 하면 안 돼

모든 필드를 public으로 두면, 클래스의 논리가 깨질 위험이 있어. 외부에서 아무나 건드리면 객체가 이상해질 수 있지. 예를 들어, 강아지 나이를 음수로 하거나, 이름을 "%$#!??"처럼 이상하게 만들 수도 있어.

3. 필드 숨기기: private 쓰기

보통 클래스의 필드는 비공개(private)로 만들어. 그러면 값은 클래스 내부에서만 바꿀 수 있고, 외부에서는 절대 못 건드려.


public class Dog
{
    private string name;
    private int age;

    public void Bark()
    {
        Console.WriteLine($"{name} 말한다: 멍멍!");
    }
}

이제 외부에서 필드에 직접 접근하려고 하면:

Dog rex = new Dog("렉스", 5);
rex.name = "샤릭";  // 컴파일 에러

컴파일러가 바로 "접근 불가!"라고 알려줄 거야.

왜 이렇게 빡세게 막지? 유연성은?

"유연성"은 특별한 메서드나 프로퍼티(이건 다음 강의에서 더 자세히!)를 통해서 제공해. 이렇게 하면 데이터 변경을 규칙에 따라 통제할 수 있어.

4. 캡슐화 실전: 제어 예제

강아지 나이를 음수로 못 넣게 하고 싶다고 해보자:


public class Dog
{
    private string name;
    private int age;

    public Dog(string name, int age)
    {
        this.name = name;
        if (age >= 0)
            this.age = age;
        else
            this.age = 0; // "이상한" 나이 못 넣게 막음
    }

    public void Bark()
    {
        Console.WriteLine($"{name} 말한다: 멍멍!");
    }

    // 나이 안전하게 바꾸는 메서드
    public void SetAge(int newAge)
    {
        if (newAge >= 0)
            age = newAge;
        // else: 값이 이상하다고 메시지 추가할 수도 있음
    }
}

이제 외부에서 필드를 직접 망칠 수 없어. 나이를 바꿀 땐 전용 메서드로 체크하고 바꿔야 해.

5. 필드 vs 접근 메서드 (getter/setter)

이렇게 필드를 private로 두고, 전용 메서드로 다루는 걸 데이터 캡슐화(data encapsulation)라고 해. 필드 값을 읽을 땐 getter, 쓸 땐 setter 메서드를 만들어.


public class Dog
{
    private string name;

    public Dog(string name)
    {
        this.name = name;
    }

    public string GetName()
    {
        return name;
    }

    public void SetName(string newName)
    {
        // 여기서 이름이 맞는지 체크할 수도 있음
        name = newName;
    }
}

근데! C#에 properties가 생기면서 이런 메서드는 거의 안 써. 프로퍼티가 훨씬 깔끔하고 편하거든(이건 다음 강의에서 더 자세히!).

6. 메서드와 클래스의 접근 제한자

필드만이 아니야! 접근 제한자는 메서드(클래스 멤버 함수)나 클래스 자체에도 쓸 수 있어.

클래스 내부에서만 쓰는 메서드(예: 내부 로직용 보조 함수)는 private로 만드는 게 좋아.

공개 메서드는 클래스의 "인터페이스"야(interface 키워드랑 헷갈리지 마!), 즉 클래스 사용자들이 쓸 수 있는 부분이지.

7. 캡슐화에서 흔한 실수

실수 1: 전부 public으로 선언함.
뭔가 다 열려 있으면 쓰기 편할 것 같지만, 사실 내부를 외부에서 막 바꿀 수 있어서 코드가 위험하고 예측 불가해져. 특히 큰 프로젝트에서 진짜 문제됨.

실수 2: 접근 제한자 바꿨다가 외부 코드가 깨짐.
리팩토링하다가 실수로 메서드나 필드의 접근 제한자를 바꾸면, 그걸 쓰던 다른 코드가 갑자기 컴파일이 안 되거나 이상하게 동작할 수 있어. 특히 공개 API에서는 진짜 조심해야 해.

실수 3: 지역 변수랑 클래스 필드 헷갈림.
가끔 개발자들이 메서드 안에서 선언한 변수는 그 메서드 안에서만 살아있다는 걸 까먹어. 클래스 필드는 모든 메서드에서 쓸 수 있는데 말이지. 변수 이름이 겹치면 진짜 헷갈리고, 이상한 버그가 생길 수 있어.

실수 4: privateprotected를 무시함.
제한된 접근을 쓰면 나중에 못 쓸까봐 걱정하는데, 사실 캡슐화의 목적이 바로 불필요한 걸 숨기고, 진짜 필요한 것만 밖으로 내보내는 거야.

코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION