7. 당신의 행운의 숫자는? 나만의 n면체 주사위 위젯 만들기

김건희·2022년 12월 14일
0

7-1. 객체 지향 프로그래밍

(1) 객체란?

객체가 등장하기까지


아주 먼 옛날(1950년대쯤)... 컴퓨터는 한창 발전하던 시기였어요. 컴퓨터는 연구실이나 기관에서 다루어지고 있었는데요. 점점 기술이 발전하면서 복잡한 일들을 처리해가고 있었습니다. 단순한 사칙 연산에서 벗어나서 말이에요.

이때까지만 해도 프로그래밍에는 변수, 함수 정도가 쓰였는데요. 변수는 값을 기억하는 것, 함수는 값을 계산하는 것이에요.

# 더하기를 하는 함수
def sum(a, b):
    return a + b
	
# 더한 결과를 담아두는 변수
result = sum(3, 4)

예를 들자면 이 정도로 다뤄지고 있었다는 말이죠.

그런데 컴퓨터에게는 해야 할 일을 정말 정확하게 적어줘야 해요. 그러니까 더 어려운 일을 시키려면 프로그램도 복잡해져야 한다는 이야기죠. 프로그램이 복잡해지면서 한 동작에 필요한 변수들이 많아졌어요. 그 많은 변수들을 어떻게 효율적으로 다룰지가 연구 주제였고 다양한 아이디어가 등장합니다.

여러 아이디어 중 많은 변수를 엮어 놓은 덩어리는 자주 언급되었고 구조체(structure), 객체(object), 클래스(class) 등 저마다 다른 이름으로 불렸습니다.


[object도 처음부터 object였던건 아닙니다]

비슷한 시기에 또 다른 아이디어도 있었어요. 함수에 대한 것인데요. 만약 변수가 어떤 동작을 해야 한다면 어떻게 이 둘을 엮을 것인가를 고민합니다.

def run(car_speed, car_direction, speed, direction):
    car_speed = speed
    car_direction = direction
    # ...원하는 동작...
    print('car is running')

run(car1_speed, car1_direction, 30, 'east')
이렇게 변수가 함수와 밀접한 관계가 있는 경우에 잘 엮어 놓으면 좋겠다는 생각이 든 것이죠. 역시나 여기서도 프로그래밍 언어마다 다양한 아이디어들이 쏟아졌습니다. 메시지(message), 메서드(method), 멤버 함수(member function) 등 많은 이름들이 등장했어요.

이 자료는 LISP라는 프로그래밍 언어에 대한 내용입니다. 자세히 들여다보면 함수를 다루는 방법, 변수들을 연관 짓는 방법 등 지금 컴퓨터 이론의 기초에 해당하는 내용이 등장하는데요. LISP가 지금 사용하는 프로그래밍 언어에 많은 영향을 미쳤기 때문에 그 개념들이 살아남은 것일 뿐입니다. 실제로는 이 당시에도 이미 프로그래밍 언어가 다양했기 때문에 많은 아이디어가 제안되었는데요. 안타깝게도 쓰이지 못하고 사라진 것들이 매우 많습니다.

최초로 아이디어가 나타나기 시작한 이후로 수십 년간 더 나은 아이디어들과 아이디어들의 조합이 생겨났습니다. 이 아이디어들이 하나의 패러다임이 되고 객체라는 이름으로 통용되기 시작했고 가장 자주 사용되었습니다. 그래서 객체를 아는 것이 프로그래밍 공부에서 중요한 요소가 되었죠.

[객체와 관련된 용어들이 이렇게 많지만 파이썬에 다 쓰이지는 않습니다. 왜냐하면 이건 C#을 기초로 하고 있기 때문이에요.]

객체에 대한 이야기를 옛날이야기로 시작한 이유는 객체의 절대적 정의가 없다 는 점을 강조하고 싶었기 때문입니다.

굉장히 많은 아이디어들이 섞여 지금의 객체에 이른 것이고 지금도 진화해 가는 중입니다. 그렇기 때문에 때로는 같은 개념을 다른 말로 쓰기도 하고, 다른 개념을 같은 말로 쓰기도 합니다.

또, 프로그래밍 언어마다 객체가 갖는 뜻이 조금씩 달라요. 많이 쓰이는 언어인 자바, C#의 객체와 파이썬의 객체는 다르고 활용법이나 관용적으로 쓰이는 모습이 다 다릅니다. 그래서 객체의 특성이라고 적어놔도 그 특성이 파이썬에는 없을 수도 있고, 파이썬에만 있을 수도 있습니다. 그래서 관련 자료를 찾아볼 때 용어를 설명하는 문맥을 잘 잡아내야 합니다.

이제 이 점을 꼭 기억하고 객체에 대해서 알아보러 떠나보죠~! 고고!!

객체


Everything in Python is an object, and almost everything has attributes and methods.

"파이썬(Python)에서 모든 것은 객체(object)다. 그래서 거의 모든 것이 속성(attributes) 과 메서드(methods) 를 갖는다." 고 하는데요. 변수의 묶음이 되는 속성과 연관된 함수를 엮어 놓은 메서드로 이루어졌다는 말입니다.

class Car:
    def __init__(self):
        # 변수를 만들면 속성이 됩니다
        self.speed = 0
        self.direction = 'none'

    # 함수를 만들면 메서드가 됩니다
    def run(self, speed, direction):
        self.speed = speed
        self.direction = direction
        print('car is running')

이 정도로 객체를 만들 수 있다는 이야기인데요. 코드가 이해되지 않더라도 괜찮습니다. 객체 안에서 변수는 속성이 되고, 함수는 메서드가 된다는 점만 알면 됩니다. 이 용어들은 혼용되기도 합니다. 속성 대신 변수라는 말을 써도 괜찮고, 메서드 대신 함수라는 말을 써도 큰일나지 않습니다. 컴퓨터의 세상은 생각보다 엄밀하게 정의하지 않아요.

파이썬에서는 부울(bool), 정수, 실수, 문자열, 배열, 딕셔너리, 함수, 모듈, 프로그램.. 등 모든 것이 객체입니다. 이 말을 이해하지 못했다 하더라도 좋습니다. 어쨌든 객체라는 점만 확인하고 넘어갑시다.

파이썬의 모든 것이 객체임을 강조하는 이유는 그렇지 않은 프로그래밍 언어들이 있기 때문입니다. 객체가 없는 언어부터 일부분만 객체인 언어까지 다양합니다. 모든 데이터 형태를 객체로 다룬다는 것은 언어의 특징일 뿐 장점이라고 하기는 어렵습니다.

모든 것을 객체로 다루기 때문에 나타나는 파이썬의 특징들을 천천히 알아보죠.
변수에 관한 내용은 다음 colab 문서 참조!!

(2) 객체 지향 프로그래밍이란?

앞에서 객체에 대한 개념과 객체를 담는(참조하는) 변수에 대해 알아보았는데요. 이렇게 객체를 활용한 프로그래밍을 객체 지향 프로그래밍(OOP: Object Oriented Programming) 이라고 합니다.

앞서 설명한 객체를 기반으로 하는 프로그래밍 언어가 여럿 등장한 후, 객체의 장점에 주목하기 시작합니다. 또, 컴퓨터가 전문가의 영역을 떠나 일반인이 사용할 수 있는 형태로 이용되면서 객체의 장점이 더욱 두드러지게 됩니다.

그러면서 점점 객체'만' 이용한 프로그래밍 방법론이 두각 되고, 이것이 가능하고 충분한 검증이 이루어진 후로는 대세로 자리 잡았지요.

객체 지향 프로그래밍에서는 만들고자 하는 것을 모두 객체로 만듭니다. 이 관점은 프로그램에서 처리하려는 데이터(변수)의 묶음을 가장 중요하게 봅니다. 데이터(변수)를 잘 엮어 처리하고 나면 우리가 원하는 결과를 얻을 수 있다는 것이죠.

도서관 관리 프로그램을 예로 들자면, 책, 방문자, 대여 상태 등을 모두 데이터(변수)의 묶음으로 만들고 처리하는 것입니다. 눈에 보이는 물질은 물론 보이지 않는 개념(e.g. 대여 상태의 변화)도 객체로 만드는 것이 가능했고, 객체 지향 프로그래밍으로 해결할 수 있었기 때문에 주류 패러다임이 될 수 있었죠.


[이렇게나 다양한 프로그래밍 방법들이 있습니다]

반면 이 아이디어 외에도 데이터(변수)를 함수로 어떻게 처리를 해야 할지에 관해 심도 있는 논의가 진행되었습니다. 이 방향으로 발전된 것이 절차 지향 프로그래밍입니다.

절차 지향 프로그래밍은 데이터(변수)를 묶음으로 표현하는 데는 관심이 없고 함수를 이용한 처리에 관심이 큽니다. 그래서 최근 분산 환경에서 데이터 처리에 매우 효율적이기 때문에 각광받고 있죠.

객체 지향 프로그래밍과 절차 지향 프로그래밍은 모두 프로그램을 어떻게 사용할지에 따른 관심 차이로 발전한 프로그래밍 패러다임입니다. 두 가지가 흑과 백처럼 배척되는 것이 아닙니다. 물론 이 두 가지 말고도 다른 관점을 가질 수도 있지만 이 두 가지 패러다임이 특히 효율적이었기 때문에 많은 주목을 받고 있습니다.

한편 객체 지향 프로그래밍은 이후로 객체끼리의 상호 작용을 하는 방법, 데이터(변수)를 안전하게 보관하는 체계, 거대한 프로그램도 오류 없이 작성할 수 있는 설계 등 큰 발전을 이루게 됩니다.

이 외에도 객체 지향 프로그래밍은 소프트웨어와 프로그래밍 전반에 오랜 기간 동안 사용된 개념으로 노드 하나에 다루기에는 그 양이 매우 많습니다. 따라서, 이번 노드에서 다루는 내용은 객체 지향 프로그램의 동작 원리가 아닌 구현 방법에 대해 설명하겠습니다. 즉, 어떻게 사용하고 어디에 활용하는지를 주로 다루어볼 예정입니다.

7-2. 클래스 기본 문법

(1) 클래스 선언 및 인스턴스화

파이썬에서 개발자가 객체를 직접 설계하기 위해서는 class 키워드를 이용합니다. 기본 클래스 문법을 익혀 보겠습니다.

클래스 선언


클래스 선언은 class 키워드를 이용합니다. class 키워드를 쓰고 클래스 이름을 쓴 다음 :(콜론)을 씁니다. 클래스 이름 다음에 소괄호를 적어 주어도 되지만 보통은 생략합니다.

위 코드에서 보면, Car라는 클래스 자체도 객체이고, Car()를 호출할 때마다 새로운 Car 타입의 객체가 생성됩니다. 둘 다 id가 존재하기 때문입니다. 그러나, id(Car)의 값은 몇 번 호출되더라도 동일하지만 id(Car())는 호출될 때마다 다른 id 값을 가진다는 것도 알 수 있습니다.

Car라는 클래스는 type 유형의 객체입니다. Car()가 호출될 때 Car 타입의 객체가 생성됩니다.

클래스 사용 - 객체 인스턴스화


클래스를 이용하려면 클래스로 객체를 만들어 주어야 하는데요. 이를 인스턴스화라고 합니다.

인스턴스화는 어떻게 할까요? 선언한 클래스 이름에 괄호를 적어 줍니다. 그리고 생성된 인스턴스를 적당한 변수에 할당해서 사용합니다.

클래스명에 괄호를 추가해 객체를 만든 후, mycar와 mycar2란 변수에 이 객체를 할당했습니다. mycar 변수에 Car 클래스의 인스턴스를 할당한 것입니다. 종종 "클래스를 호출(call) 했다"라는 표현을 쓰기도 합니다. 위 코드에서는 인스턴스가 생성될 때마다 객체를 할당받은 변수들에게 다른 id가 부여되는 것을 알 수 있습니다.

표기법

그런데 잠깐만!! 이 인스턴스화하는 방법, 어디서 많이 본 것 같지 않나요? 네 맞아요.
함수를 호출하는 것과 클래스로 객체를 만드는 것은 문법이 너무 비슷합니다. 클래스에서도 상속을 사용할 때는 클래스를 선언 시 소괄호를 붙이기도 하고, 초깃값을 설정할 때 인스턴스화 시 인자를 전달하기도 합니다. 함수와 매우 비슷하죠? 이건 어떻게 구분할까요?

파이썬에서는 클래스명과 함수명을 다르게 표기하는 방법을 사용합니다. 강제사항은 아니에요. 하지만 나만 다르게 표기하면 오해가 생기기 쉬우니 주의하세요!

PEP는 Python Enhancement Proposals의 약자로 파이썬 개선사항을 위한 공식 문서입니다. 그중에서도 PEP8은 파이썬 코딩 스타일(변수명, 코드 표기법 등등)을 개정한 문서인데요, 여기에서 다음과 같이 사용할 것을 권고하고 있습니다.

클래스명 표기법: 카멜 케이스

  • 카멜 케이스: 각 단어의 앞 글자를 대문자로 쓸 것.
  • 예시: mycar —> MyCar

함수명 표기법: 스네이크 케이스

  • 스네이크 케이스: 단어는 소문자로 쓰고 각 단어의 연결은 언더바(_)를 사용할 것
  • 예시: mycar —> my_car

그리고 추가로 클래스명은 주로 명사로, 함수명은 주로 동사로 명명합니다.
(이 부분은 파이썬 코드를 깨끗이 작성하는 "Clean Code" 규범과 관련된 내용이니 참고로만 알고 계세요)

다른 사람이 만들어놓은 경우에는 type() 함수를 이용해서 확인해 보는 것도 좋은 방법이겠네요!

(2) 클래스 속성과 메서드

클래스의 속성과 메서드

앞서 클래스는 개발자가 객체를 설계하기 위한 것이라고 했습니다. 그리고 맨 처음에 객체에는 속성과 메서드가 있다고 배웠습니다.
그럼 클래스에서 속성과 메서드를 구현할 수 있어야겠죠?

클래스의 속성은 상태(state)를 표현합니다. 속성은 변수로 나타냅니다.
클래스의 메서드는 동작(behavior)을 표현합니다. 메서드는 def 키워드로 나타냅니다.
그럼 이어서 Car 클래스를 계속 코딩하도록 하겠습니다.
색상은 "red", 종류는 "sports car"라는 속성을 갖고 주행과 가속이라는 동작을 갖는 클래스를 정의해 보겠습니다.

먼저 간단하게 손코딩으로 해볼게요. 코랩 문서 참조!!

(3) 생성자

생성자 init


클래스에 의해 만든 인스턴스 객체의 속성값을 사용자는 어떻게 초기화할 수 있을까요? Car 클래스를 만들 때부터 색깔과 카테고리를 지정해 주고 싶다면 어떻게 그 값을 전달해 줄 수 있을까요? init 을 사용해서 만들 수 있습니다. 아래 캡처본은 파이썬 공식 문서에서 설명하고 있는 init의 문법입니다.

(4) 클래스 변수와 인스턴스 변수

이번에는 클래스 내 변수를 선언하는 방법을 설명하도록 하겠습니다. 클래스에서 변수를 선언하는 방법은 2가지가 있었습니다. 하나는 보통 변수와 동일하게 변수명을 쓰고 값을 할당하는 방법, 두 번째는 init 메서드 안에 self.와 함께 설정하는 방법입니다.
이어질 내용은 코랩 문서 참조.

profile
게임광 AI 그루~~

0개의 댓글