기본 콘텐츠로 건너뛰기

방송대 파이썬프로그래밍기초 10강: 클래스·인스턴스와 캡슐화

0-썸네일-요약노트-파이썬프로그래밍기초-10강

방송대 파이썬프로그래밍기초 10강: 클래스·인스턴스와 캡슐화

함수 여러 개가 같은 데이터를 따로 전달받기 시작하면 상태와 행동을 하나로 묶을 필요가 생깁니다. 원뿔과 BMI 사례를 설계도에서 코드로 옮기며 클래스·인스턴스·self의 관계를 추적하고, 데이터 은닉과 접근자·변경자가 필요한 이유를 판단합니다.

같은 상태를 공유하는 행동은 하나의 객체로 묶는다

원뿔의 부피 함수와 겉넓이 함수는 모두 반지름과 높이를 필요로 한다. 함수마다 같은 값을 반복해서 전달하면 어느 값이 어느 원뿔에 속하는지 관리하기 어려워진다. 객체지향은 반지름·높이라는 상태와 부피·겉넓이 계산이라는 행동을 원뿔 객체 하나에 묶어 이 문제를 해결한다.

객체지향 프로그래밍은 객체와 객체 사이의 상호작용으로 프로그램을 구성하는 패러다임이다. 대규모 프로그램에서 관련 데이터와 연산의 경계를 분명히 하여 운영과 변경을 쉽게 만드는 데 목적이 있다.

객체 후보 찾기: 여러 함수가 같은 데이터 묶음을 계속 사용하고, 그 데이터에 허용되는 행동이 함께 정해져 있다면 하나의 객체로 추상화할 수 있는지 검토한다.

객체지향의 네 특징은 역할이 서로 다르다

추상화·캡슐화·상속·다형성은 모두 객체지향의 특징이지만 같은 뜻이 아니다. 어떤 문제를 해결하는지 기준으로 구분해야 한다.

특징핵심 질문역할원뿔 사례의 관점
추상화여러 대상의 공통 속성과 기능은 무엇인가?문제에 필요한 공통 특징을 뽑아 모델 정의반지름·높이와 부피·겉넓이 계산을 원뿔의 핵심으로 선택
캡슐화관련 데이터와 연산을 어디에 묶을 것인가?데이터 구조와 데이터 연산을 한 단위로 결합크기 값과 계산 메서드를 Cone 안에 배치
상속상위 개념의 특징을 어떻게 내려받을 것인가?상위 개념의 속성과 기능을 하위 개념에 전달공통 입체도형 특징을 특수 도형에 재사용하는 관점
다형성서로 다른 객체를 같은 사용 방식으로 다룰 수 있는가?유사 객체의 사용성을 같은 인터페이스로 유지도형마다 계산은 달라도 같은 이름의 면적 동작을 사용하는 관점

‘속성을 감추는 것’만 캡슐화라고 외우면 부족하다. 먼저 데이터와 그 데이터를 다루는 메서드를 같은 클래스에 결합하고, 이후 외부에서 허용할 접근 경로를 정한다. 데이터 은닉은 캡슐화를 안전하게 사용하는 방법이다.

클래스는 설계도이고 인스턴스는 설계도로 만든 실제 객체다

클래스는 객체가 가질 데이터 필드와 메서드를 정하는 설계도다. 객체 또는 인스턴스는 그 설계도에 따라 메모리에 생성된 실제 사용 단위다. 하나의 Cone 클래스로 크기가 다른 원뿔 객체를 여러 개 만들 수 있다.

class Cone:
    def __init__(self, radius=20, height=30):
        self.radius = radius
        self.height = height

    def get_volume(self):
        return 1 / 3 * 3.14 * self.radius ** 2 * self.height

    def get_surface(self):
        slant = (self.radius ** 2 + self.height ** 2) ** 0.5
        return 3.14 * self.radius ** 2 + 3.14 * self.radius * slant

class Cone: 아래의 들여쓴 블록이 클래스 정의다. __init__은 객체의 초기 상태를 만드는 초기자이며, get_volume()과 get_surface()는 객체의 상태를 사용해 행동을 수행하는 메서드다.

이름 구분: 일반 함수는 독립된 작업을 표현하고, 메서드는 특정 객체의 상태와 연결된 행동을 표현한다. 문법은 비슷하지만 메서드에는 어느 객체를 사용할지 나타내는 첫 매개변수가 필요하다.

self는 지금 메서드를 실행하는 객체를 가리킨다

인스턴스 메서드의 첫 매개변수는 객체 자신을 참조하며 관례적으로 self라고 쓴다. 정의에는 명시하지만 unit_cone.get_volume()처럼 객체를 통해 호출할 때는 self 자리에 값을 직접 적지 않는다. 점 앞의 객체가 자동으로 연결된다.

초기자에서 self.radius = radius는 오른쪽 매개변수의 값을 객체의 데이터 필드에 저장한다. 왼쪽의 self.radius는 객체가 살아 있는 동안 유지되는 속성이지만, radius만 대입하면 초기자 실행 중에만 존재하는 지역 이름이 된다.

class WrongCone:
    def __init__(self, radius, height):
        radius = radius
        height = height

    def get_volume(self):
        return 1 / 3 * 3.14 * self.radius ** 2 * self.height

이 코드는 초기자에서 객체 속성을 만들지 않았으므로 get_volume()이 self.radius를 찾을 수 없다. 오른쪽 인자를 객체 상태로 보존하려면 반드시 self.radius = radius, self.height = height처럼 객체에 연결해야 한다.

self 점검: 여러 메서드가 나중에도 써야 할 값인가? 그렇다면 초기자의 지역변수가 아니라 self.필드로 저장한다. 메서드 안에서만 잠깐 쓰는 빗면 길이 같은 중간값은 지역변수로 두어도 된다.

UML 클래스 다이어그램은 설계와 코드 사이의 번역표다

UML 클래스 다이어그램은 클래스 이름, 데이터 필드, 생성자와 메서드를 구획으로 나누어 표현한다. 구현 전에 객체가 어떤 상태와 행동을 가져야 하는지 점검하고, 팀이 같은 설계를 공유하는 데 유용하다.

UML의 Cone 항목파이썬 코드 대응읽는 방법
Coneclass Cone:클래스 이름
radius: int, height: intself.radius, self.height객체가 보관할 데이터 필드와 타입 의도
Cone(radius=20, height=30)__init__(self, radius=20, height=30)기본값을 가진 초기자
get_volume(): floatdef get_volume(self):인자 없이 부피 결과를 반환하는 메서드
get_surface(): floatdef get_surface(self):인자 없이 겉넓이 결과를 반환하는 메서드

UML의 타입 표기는 설계 의도를 알려 준다. 다이어그램을 코드로 옮길 때는 필드가 초기자에서 실제로 만들어지는지, 메서드가 다이어그램에 약속한 결과를 반환하는지 대조한다.

객체 생성은 클래스 호출과 초기자 실행의 두 단계로 본다

클래스 이름을 함수처럼 호출하면 인스턴스가 만들어지고 초기자가 실행된다. 생성된 객체를 계속 사용하려면 객체 참조변수에 저장한다.

unit_cone = Cone(50, 100)
default_cone = Cone()

print(unit_cone.radius)
print(unit_cone.get_volume())
print(default_cone.radius, default_cone.height)
  1. Cone(50, 100)이 새로운 객체를 만든다.
  2. __init__이 호출되어 50과 100을 객체의 radius, height에 저장한다.
  3. 완성된 객체의 참조가 unit_cone에 연결된다.
  4. unit_cone.radius는 데이터 필드에, unit_cone.get_volume()은 메서드에 접근한다.

Cone()처럼 인자를 생략하면 초기자의 기본값 20과 30을 사용한다. 클래스는 하나지만 각 인스턴스는 서로 다른 상태를 가지므로 unit_cone.radius를 바꿔도 default_cone.radius에는 영향을 주지 않는다.

파이썬의 기본 데이터도 타입·값·식별자를 가진 객체다

객체지향은 사용자가 만든 클래스에만 적용되지 않는다. 정수와 문자열 같은 파이썬 데이터도 객체이며, type()으로 클래스, id()로 객체의 식별값을 확인할 수 있다. 문자열에는 lower() 같은 메서드가 있다.

school = "Korea National Open University"
number = 20

print(type(number))
print(type(school))
print(school.lower())

number는 int 객체를, school은 str 객체를 참조한다. school.lower()처럼 점 연산자를 사용해 문자열 객체의 메서드를 호출한다. 이것은 사용자가 만든 unit_cone.get_volume()과 같은 ‘객체.메서드’ 접근 구조다.

값과 객체 구분: 변수는 객체 자체를 담는 상자라기보다 객체를 가리키는 이름으로 이해하면, 같은 클래스에서 여러 인스턴스를 만들고 각각 다른 상태를 유지하는 구조가 선명해진다.

데이터 은닉은 잘못된 직접 변경을 메서드의 문 앞에서 막는다

원뿔의 반지름이나 높이에 음수가 들어가면 계산 결과가 나와도 실제 의미가 없다. 외부 코드가 데이터 필드를 직접 변경하도록 두면 유효성 검사를 우회할 수 있다. 데이터 은닉은 필드의 직접 접근을 제한하고 정해진 메서드를 통해 읽고 바꾸게 하는 방식이다.

강의자료는 이름 앞에 밑줄 두 개를 붙인 self.__radius, self.__height를 private 데이터 필드로 사용한다. 외부에서는 접근자(getter)로 읽고 변경자(setter)로 설정하도록 인터페이스를 만든다.

class Cone:
    def __init__(self, radius=20, height=30):
        self.__radius = radius
        self.__height = height

    def get_radius(self):
        return self.__radius

    def set_radius(self, radius):
        if radius > 0:
            self.__radius = radius
            return True
        return False

    def get_volume(self):
        return 1 / 3 * 3.14 * self.__radius ** 2 * self.__height

set_radius(-50)은 False를 반환하고 기존 값은 유지한다. 변경자를 거치면 “반지름은 양수”라는 규칙을 한곳에 모을 수 있다. 접근자는 값을 반환하고 변경자는 조건을 검사해 상태를 바꾼다는 책임 차이를 기억한다.

은닉의 목적: 밑줄 개수를 외우는 데 있지 않다. 객체가 유효한 상태만 유지하도록 모든 변경 경로를 통제하고, 외부 코드는 내부 저장 방식 대신 공개된 메서드에 의존하게 하는 것이다.

BMI 클래스는 요구사항을 필드·초기자·질의 메서드로 분해한다

강의자료의 BMI 설계는 이름, 나이, 몸무게, 키를 데이터 필드로 두고 BMI 수치와 상태를 반환하는 메서드를 둔다. 먼저 “무엇을 기억할지”와 “무엇을 계산해 알려 줄지”를 구분해야 한다.

요구사항설계 요소이유
사람의 기본 정보 보관name, age, weight, height 필드객체마다 달라지는 지속 상태
객체 생성 시 필수값 설정__init__사용 가능한 초기 상태 구성
BMI 수치 제공get_bmi()필드로부터 계산되는 결과
BMI 상태 제공get_status()계산 결과를 기준에 따라 해석
이름 확인get_name()은닉된 필드의 공개 읽기 경로

나이와 이름은 BMI 계산식에 직접 쓰이지 않더라도 한 사람의 BMI 기록을 식별하고 설명하는 객체 상태가 될 수 있다. 반대로 BMI 수치는 몸무게와 키가 바뀔 때 다시 계산할 수 있으므로 중복 저장보다 메서드 결과로 제공하는 설계가 자연스럽다.

객체지향 설계는 책임·생성·접근의 순서로 점검한다

  1. 책임 찾기: 어떤 상태와 행동이 한 대상에 함께 속하는지 정한다.
  2. 설계도 작성: 클래스 이름, 필드, 초기자, 메서드와 반환 결과를 UML처럼 정리한다.
  3. 초기 상태 보장: __init__에서 지속할 값을 self.필드에 저장한다.
  4. 인스턴스 생성: 클래스 호출의 인자와 초기자 매개변수를 연결하고 객체 참조를 변수에 저장한다.
  5. 멤버 사용: 객체.필드 또는 객체.메서드()로 올바른 인스턴스에 접근한다.
  6. 상태 보호: 직접 변경으로 규칙이 깨질 수 있다면 필드를 은닉하고 접근자·변경자에서 검사한다.

오류가 생기면 이 순서를 거꾸로 본다. 메서드가 속성을 못 찾으면 초기자에서 self에 저장했는지, 값이 잘못 바뀌면 외부 직접 변경을 허용했는지, 다른 객체 값이 나오면 점 앞의 객체 참조가 올바른지 확인한다.

핵심 개념 정리

  • 객체지향은 객체의 상태와 행동을 묶고 객체 사이의 상호작용으로 프로그램을 구성한다.
  • 추상화는 공통 특징 추출, 캡슐화는 데이터와 연산 결합, 상속은 상위 특징 전달, 다형성은 유사 객체의 공통 사용성이다.
  • 클래스는 필드와 메서드를 정한 설계도이고, 객체 또는 인스턴스는 그 설계도로 생성한 실제 사용 단위다.
  • __init__은 초기 상태를 만들며 지속할 값은 self.필드에 저장해야 한다.
  • self는 현재 메서드를 실행하는 객체를 참조하고 객체 호출 시 직접 인자로 적지 않는다.
  • UML 클래스 다이어그램은 클래스 이름, 데이터 필드, 생성자와 메서드의 설계 관계를 보여 준다.
  • 정수·문자열도 객체이며 점 연산자로 데이터 필드나 메서드에 접근한다.
  • 데이터 은닉과 접근자·변경자는 외부 변경 경로를 통제하여 객체의 유효한 상태를 유지한다.

객체지향 문제에서는 먼저 함께 움직이는 상태와 행동을 찾아 클래스 책임으로 묶는다. UML의 필드·초기자·메서드를 코드의 self.필드와 반환 메서드에 연결하고, 클래스 호출로 생성된 각 인스턴스의 상태를 따로 추적한다. 마지막으로 외부 직접 변경이 객체 규칙을 깨뜨리는지 확인해 데이터 은닉과 접근자·변경자의 필요성을 판단한다.

예상문제 10선

1. 객체지향 프로그래밍의 설명으로 가장 적절한 것은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ②

  • ① 오답: 객체지향은 관련 데이터와 연산을 캡슐화하여 한 단위로 묶는다.
  • ② 정답: 객체의 상태·행동과 객체 간 상호작용이라는 핵심을 모두 포함한다.
  • ③ 오답: 하나의 거대 함수는 객체별 책임 분리와 반대 방향이다.
  • ④ 오답: 인스턴스 메서드는 실제 객체와 연결하여 사용한다.

2. 클래스와 인스턴스의 관계를 바르게 설명한 것은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ①

  • ① 정답: 공통 정의와 실제 생성 단위를 정확히 구분한다.
  • ② 오답: 설계와 개별 객체의 역할을 서로 바꾸었다.
  • ③ 오답: 클래스는 객체 설계이며 인스턴스는 메모리에 존재하는 사용 단위다.
  • ④ 오답: 같은 클래스로 서로 다른 상태를 가진 인스턴스를 여러 개 만들 수 있다.

3. 다음 초기자가 만든 객체에서 self.radius를 찾을 수 없는 이유는?

def __init__(self, radius):
    radius = radius

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ④

  • ① 오답: 초기자의 첫 매개변수 뒤에 초기 상태를 받을 매개변수를 둘 수 있다.
  • ② 오답: 초기자는 할당을 통해 객체 필드를 만드는 곳이다.
  • ③ 오답: 매개변수는 해당 메서드 실행 공간의 지역 이름이다.
  • ④ 정답: 지속할 객체 상태는 self.radius = radius로 연결해야 한다.

4. unit_cone = Cone(50, 100)의 실행 흐름으로 옳은 것은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ③

  • ① 오답: 객체를 사용할 참조를 삭제하는 과정으로 시작하지 않는다.
  • ② 오답: 객체 생성이 클래스 삭제보다 앞서는 식의 흐름은 성립하지 않는다.
  • ③ 정답: 클래스 호출, 초기 상태 구성, 참조 저장의 순서를 보여 준다.
  • ④ 오답: 객체와 필드가 생기기 전에 필드를 출력할 수 없다.

5. 추상화와 캡슐화의 차이를 바르게 설명한 것은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ①

  • ① 정답: 모델링 단계와 상태·행동 결합이라는 서로 다른 역할을 구분한다.
  • ② 오답: 직접 변경 제한은 은닉의 관심사이며 클래스 삭제와 무관하다.
  • ③ 오답: 상속과 다형성의 역할을 추상화·캡슐화로 잘못 연결했다.
  • ④ 오답: 객체 식별값 확인은 두 설계 개념의 정의가 아니다.

6. 객체의 반지름이 양수라는 규칙을 가장 안정적으로 유지하는 설계는?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ④

  • ① 오답: 직접 대입을 허용하면 유효성 검사를 우회할 수 있다.
  • ② 오답: 지속할 반지름을 저장하지 않으면 다른 메서드가 사용할 수 없다.
  • ③ 오답: 접근자는 읽기, 변경자는 검사와 설정을 담당한다.
  • ④ 정답: 변경 경로를 한 메서드로 모아 객체의 유효한 상태를 보장한다.

7. a = Cone(3, 4), b = Cone()일 때 기본값이 20과 30이라면 두 객체의 반지름은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ②

  • ① 오답: 명시한 인자와 생략 시 기본값의 적용 대상을 바꾸었다.
  • ② 정답: a는 전달값 3, b는 생략된 자리의 기본값 20을 가진다.
  • ③ 오답: 각 인스턴스는 독립된 상태를 가지므로 a의 인자가 b에 복사되지 않는다.
  • ④ 오답: 명시적으로 전달한 3은 기본값 20을 대체한다.

8. self의 역할로 가장 적절한 것은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ③

  • ① 오답: self는 호출에 연결된 현재 인스턴스 하나를 가리킨다.
  • ② 오답: 전역변수의 접근 수준을 바꾸는 기능이 아니다.
  • ③ 정답: 같은 클래스의 여러 객체 중 어느 객체의 필드와 메서드를 사용할지 정한다.
  • ④ 오답: 초기자에도 self를 사용해 객체 상태를 생성한다.

9. UML의 get_bmi(): float를 코드로 옮길 때 확인할 사항은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ④

  • ① 오답: UML은 수치를 반환하는 메서드를 약속하고 있다.
  • ② 오답: 초기자는 객체 상태를 만들고 BMI 계산 책임은 별도 메서드에 있다.
  • ③ 오답: 반환 타입 의도는 문자열이 아니라 실수다.
  • ④ 정답: 필드와 메서드의 책임 및 반환값 타입을 설계에 맞게 연결한다.

10. 여러 원뿔의 크기를 독립적으로 관리하고 잘못된 반지름 변경을 막으려면?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ②

  • ① 오답: 전역 상태 하나로는 여러 원뿔의 독립된 값을 유지하기 어렵다.
  • ② 정답: 인스턴스별 상태와 캡슐화된 변경 규칙을 함께 확보한다.
  • ③ 오답: 클래스 복사는 중복을 만들고 직접 변경은 유효성 검사를 우회한다.
  • ④ 오답: 객체에 상태가 없으면 여러 메서드가 같은 원뿔 정보를 공유할 수 없다.

참고 자료와 작성 기준

이 글은 해당 차시 강의자료를 바탕으로 학습 목적에 맞게 재구성한 비공식 학습자료입니다. UML-코드 대응, 객체 상태 추적, 오류 교정과 문제 해설은 학습자의 이해를 돕도록 구성하고 검토했습니다.

  • 작성·편집: 올에이클래스 학습연구팀
  • 주요 근거: 한국방송통신대학교 컴퓨터과학과 「파이썬프로그래밍기초」 강의록 10강 「객체지향」, 1~26쪽
  • 범위 구분: 27쪽의 11강 「모듈」 예고는 본문에서 제외
  • 보충 자료: 외부 자료를 사용하지 않음
  • 편집 원칙: 올에이클래스 편집 정책
  • 최종 내용 검토: 2026-09-07

댓글