
상편에서 클래스의 골격(변수·메서드 종류)을 봤다면,
하편에서는 “설계 관점에서 클래스” 를 다룬다.
데이터 보호: 정보 은닉, 캡슐화
접근 수준: public / protected / private
안전한 접근: Getter / Setter, @property
재사용/확장: 상속·오버라이딩·super()
인터페이스 강제: 추상 클래스
1. 정보 은닉(Information Hiding)과 캡슐화(Encapsulation)
객체의 내부 상태(데이터)에 외부에서 직접 접근하지 못하게 숨기고, 메서드를 통해서만 접근하게 만드는 설계 기법.
목적:
잘못된 값 대입을 막아 데이터 무결성 보호
내부 구현을 바꾸더라도 외부 코드와의 의존성 최소화
관련 있는 데이터(속성)와 기능(메서드)를 하나의 단위(클래스)에 묶고, 외부에는 필요한 인터페이스만 공개하는 것
정리:
정보 은닉 = 캡슐화를 실현하는 구체적 기법 중 하나
"내부는 숨기고, 외부에는 최소한의 문만 연다"는 구조
2. 접근 수준 -
public/protected/private(파이썬 방식)
파이썬은 public / private 키워드가 없다. 대신, 이름 앞에 붙는 언더스코어 규칙으로 표현한다.
✔ 언더스코어 규칙으로 public / protected / private를 구분하는 파이썬의 접근 제어 방식
별도 언더스코어 없이 정의된 속성 / 메서드
클래스 외부에서 자유롭게 접근 가능
✔ 언더스코어 없이 선언된 속성·메서드는 외부에서 자유롭게 접근 가능함을 보여주는 예시
_변수명_변수명 처럼 언더스코어 1개로 시작
문법적으로 막히지는 않지만, "직접 건드리지 말고, 자식 클래스에서 주로 사용하자"는 관례
✔ 언더스코어 1개로 ‘자식 전용’ 의미를 나타내는 관례 기반 protected 패턴
__변수명 (네임 맹글링)언더스코어 2개(__)로 시작
내부적으로 _클래스이름__변수명으로 이름이 바뀜 (네임 맹글링)
그대로 접근 시 에러
의도:
실수로 내부 구현을 건드리지 않도록 접근을 어렵게 만드는 장치
의도적으로 우회할 수 있지만, 그 순간 캡슐화를 깨는 것이라는 신호
✔ __name이 내부적으로 _클래스명__name으로 변환되는 네임 맹글링 구조
3.
Getter/Setter메서드와@property
Getter / Setter 기본 형태내부 상태는 __balance로 숨김
읽기 / 쓰기 작업은 메서드로만 가능하도록 강제
이 과정에서 검증 로직 삽입 가능
✔ private 변수를 메서드를 통해 안전하게 읽고 쓰도록 강제하는 구조
@property 사용메서드를 "속성처럼" 보이게 만드는 문법
장점:
외부에서는 일반 속성처럼 사용
내부에서는 함수처럼 로직(검증, 로그 변환 등)을 자유롭게 추가·수정
✔ 속성처럼 보이지만 내부적으로 함수 호출로 검증·제어를 수행하는 property 접근 방식
✔ 값 변경 시 검증 로직을 실행하여 잘못된 데이터 입력을 막는 setter 구조
실습1. 접근 제어와 정보은닉 연습
UserAccount 클래스를 정의하세요.
인스턴스 변수:
username: 사용자 이름
__password: private 변수로, 비밀번호 저장
생성자에서 사용자 이름과 비밀번호를 초기화하세요.
다음 메서드를 정의하세요.:
change_password(old_pw, new_pw): 현재 비밀번호가 old_pw와 같을 때만 변경 허용,
틀리면 "비밀번호 불일치" 출력
check_password(password): 비밀번호 일치 여부를 반환(True / False)
✔ 비밀번호를 private으로 숨기고 메서드로만 변경·검증 가능하게 만든 정보 은닉 연습 문제
@property 사용)Student 클래스를 정의하세요.
인스턴스 변수 __score는 private으로 선언합니다.
score에 대한 getter / setter를 @property를 사용하여 정의하세요.
ValueError를 발생시킵니다.
✔ 점수 검증을 property로 처리하여 값 범위를 강제하는 학생 클래스 예시
4. 상속(Inheritance) - 코드 재사용과 확장
기존 클래스(부모, 상위 클래스)의 속성과 메서드를 새로운 클래스(자식, 하위 클래스)가 물려받아 사용하는 것
필요성:
공통 기능은 부모에 모아두고, 자식 클래스는 차이점만 구현 ⇒ 중복 감소, 유지보수 용이
같은 인터페이스로 다양한 타입을 다루는 다형성 기반
✔ 부모 클래스의 기능을 자식이 물려받아 확장하는 상속 관계 개념도
✔ class Child(Parent) 형태로 구성되는 기본 상속 문법 설명
✔ 부모 기능을 그대로 활용하면서 자식 객체가 동작하는 실행 흐름 예시
5.
super()를 이용한 부모 생성자 / 메서드 호출
super()는 부모(상위) 클래스의 메서드를 호출하기 위한 내장 함수
상속 계층이 깊거나 다중 상속 상황에서도 MRO(Method Resolution Order)를 따라 올바른 부모 메서드를 찾아 호출
✔ MRO 기반으로 부모 메서드를 찾아 호출하는 super()의 동작 방식 설명
super().__init__(...)를 호출하지 않으면 부모 측에서 설정하던 속성이 초기화되지 않을 수 있음
✔ 자식 생성자에서 부모 생성자를 호출하여 초기화를 확장하는 예시
✔ 부모 메서드 실행 후 자식 동작을 덧붙여 기능을 확장하는 패턴
super() 관련 주의사항super()는 클래스 내부 메서드에서 사용하는 것이 원칙
보통 생성자에서 super().__init__()형태로 가장 많이 사용
다중 상속 등에서 부모클래스명.메서드(self, ...)를 직접 호출하면 MRO를 무시하게 되어 예기치 못한 동작 가능
⇒ super() 권장
6. 메서드 오버라이딩(Method Overriding)
부모 클래스에 이미 정의된 메서드를 자식 클래스에서 같은 이름, 같은 인자로 다시 정의하여 동작을 바꾸는 것
같은 메서드를 호출해도, 어떤 자식 클래스 인스턴스냐에 따라 동작이 달라지는 것이 다형성
✔ 같은 메서드 이름을 자식에서 다시 정의해 타입별 동작을 다르게 만드는 구조
실습2. 상속과 오버라이딩 실습
[Shape 클래스 조건]
생성자를 통해 다음 두 값을 초기화하세요.
변의 개수(sides)
밑변의 길이(base)
printinfo()메서드를 정의하여 다음과 같이 출력
변의 개수: 4
밑변의 길이: 10
area()메서드를 정의하여 "넓이 계산이 정의되지 않았습니다."라는 메시지 출력
[Rectangle 클래스 조건]
Shape를 상속받습니다.
생성자에서 sides, base, height를 모두 초기화합니다.
area()메서드를 오버라이딩하여 base × height 값을 출력합니다.
[Triangle 클래스 조건]
Shape를 상속받습니다.
생성자에서 sides, base, height를 모두 초기화합니다.
area()메서드를 오버라이딩 하여 (base × height) / 2 값을 출력합니다.
[실행]
Rectangle과 Triangle 객체를 생성합니다.
각 객체에 대해 printinfo()와 area() 메서드를 차례로 호출하세요.
✔ 부모 Shape의 area 메서드를 자식에서 오버라이딩하여 구현하는 실습 예시
7. 추상 클래스(Abstract Class)
직접 인스턴스를 만들지 않고, 공통 인터페이스를 정의하는 용도로 사용하는 클래스
특징:
일부 메서드는 구현 없이 형태만 정의(추상 메서드)하고, 실제 구현은 자식 클래스에 강제
"이 메서드는 반드시 구현되어야 한다."는 설계를 코드로 표현
abc 모듈ABC를 상속 ⇒ 추상 클래스가 됨
@abstractmethod가 붙은 메서드는 자식에서 반드시 구현해야 함
추상 메서드를 그대로 둔 채 인스턴스화 시도 시 ⇒ TypeError
from abc import ABC, abstractmethod
class Base(ABC): 형태로 추상 클래스 선언
추상 클래스를 직접 인스턴스화하는 것은 불가능
추상 메서드를 모두 구현한 구체 클래스(concrete class)만 인스턴스 생성 가능
✔ 추상 클래스가 인스턴스화 불가하며 템플릿 역할을 수행한다는 개념도
✔ 자식 클래스에 구현을 강제하는 추상 메서드의 동작 예시
✔ 추상 메서드를 구현하지 않으면 TypeError가 발생하는 실행 예시
실습3. 추상 클래스 연습문제
[아래 조건을 만족하는 클래스를 구현하세요.]
추상 클래스 Payment를 정의하고, pay(amount)를 추상 메서드로 선언하세요.(abc 모듈 사용)
CardPayment 클래스와 CashPayment 클래스는 Payment를 상속받아 pay() 메서드를 오버라이딩 하세요.
CardPayment: 카드로 {amount}원을 결제합니다. 출력
CashPayment: 현금으로 {amount}원을 결제합니다. 출력
✔ 공통 결제 인터페이스를 추상 클래스로 정의하고 구체 클래스로 구현한 예시
8. 실무 예시
Payment 인터페이스 기준으로 프로세스 작성
새 결제 수단 추가 시 Payment 상속 + pay() 구현만 하면 됨 ⇒ 기존 코드 수정 최소화
✔ 추상 클래스 Payment를 기반으로 카드·계좌이체 결제 로직을 오버라이딩한 구조 예시
다양한 센서 타입(Power, Temp, Humidity 등)을 하나의 인터페이스로 처리
분석 / 수집 코드가 BaseSensor 기준으로 단순해짐
✔ BaseSensor 추상 클래스를 기준으로 다양한 센서(Power·Temperature)를 동일한 인터페이스로 수집하는 구조 예시
9. 클래스(하) 한눈에 보기
정보 은닉: 내부 상태를 직접 노출하지 않고, 메서드 / @property 를 통해서만 접근
캡슐화: 속성과 메서드를 하나의 단위로 묶고, 필요한 인터페이스만 외부에 제공
접근 수준 (파이썬 컨벤션)
public : name
protected : _name
private : __name (네임 맹글링)
@property: 밖에서는 속성처럼 보이지만, 내부에서는 함수 호출로 검증·로그 등 수행
상속: 공통 기능 재사용, 자식에서 차이점만 구현
super()
부모 생성자·메서드 호출
MRO 기반으로 올바른 상위 구현 호출
오버라이딩: 같은 이름의 메서드를 자식에서 다시 정의하여, 타입별로 다른 동작 구현
추상 클래스
인터페이스를 강제하는 틀
@abstractmethod 로 “반드시 구현해야 하는 메서드” 지정
10. 아웃트로 - 클래스 단원 전체 정리
클래스 정의와 기본 문법
인스턴스/클래스/정적 메서드
정보 은닉·캡슐화, 접근 수준
@property 를 이용한 안전한 접근
상속, super(), 오버라이딩
추상 클래스와 인터페이스 설계
까지 전부 정리했다.
이제부터는:
작은 문제라도 클래스로 설계해 보는 연습
@property, 상속, 추상 클래스 등을 실제 코드에 적용
에너지·IoT·데이터 분석 도메인에 맞는 클래스를 직접 설계
를 반복하면,
“문법으로서의 클래스”를 넘어서 “설계 도구로서의 클래스” 를 다루게 된다.