1.1 객체와 클래스
오늘은 Python 프로그램이 어떻게 구성되는지 배울 거야. 그리고 제일 중요한 건: Python에서 모든 프로그램은 클래스와 객체로 구성돼. Python은 객체 지향 언어이고, 모든 게 객체야: 숫자, 문자열, 함수, 그리고 심지어 클래스조차도 객체야.
그렇다면 클래스란 뭐야?
비유로 시작해볼게. 작은 배를 만들려고 한다고 상상해봐. 먼저 설계도를 만들어야 하고, 그 다음 공장에 보내서 그 설계도로 배를 만들 거야. 아니면 열 대를 만들 수도 있고, 몇 대든지 만들 수 있어. 하나의 설계도로 수십 대의 동일한 배를 만드는 거야, 이게 중요한 포인트야.
Python 프로그래밍도 똑같아.
설계도
프로그래머는 설계자 같아. 설계자는 설계도를 그리고, Python 프로그래머는 클래스를 작성해. 그 다음 설계도를 기반으로 부품을 만들듯이, 클래스 기반으로 객체가 만들어지는 거지.
우리가 처음 클래스를 작성하고 (설계도를 만들고), 그리고 프로그램 실행 중에 이 클래스들 기반으로 Python이 객체를 생성해. 설계도를 기반으로 배를 만드는 것처럼 말이야.
설계도는 하나지만, 배는 많을 수 있어. 배마다 이름이 다르고, 다른 화물을 운반해. 그래도 여전히 비슷해: 같은 구조를 가진 동일한 배들이고 비슷한 작업을 수행할 수 있어.
또 다른 비유를 들어볼게...
개미집
개미집은 객체 간 상호작용의 좋은 예야. 단순한 개미집에는 세 종류의 개미 클래스가 있어: 여왕개미, 전사 개미, 그리고 일꾼 개미.
각 클래스의 개미 숫자는 달라. 여왕개미는 개미집에 하나고, 전사 개미는 수십 마리, 일꾼 개미는 수백 마리 있어. 셋은 다른 클래스와 같은 클래스를 가진 개미들과 엄격히 규칙적으로 상호작용해.
이건 딱 완벽한 예야. 일반적인 프로그램도 똑같아. 메인 객체가 있고, 이 객체가 나머지 클래스의 객체를 만들어. 객체들이 서로, 그리고 프로그램의 "외부 세계"와 상호작용을 시작해. 이 객체들의 행동은 내부적으로 엄격히 프로그래밍돼 있어.
이 두 비유는 하나의 동전의 양면이야. 진실은 그 중간에 있어. 첫 번째 예시 (설계도와 배)는 클래스와 그 클래스의 객체 사이의 관계를 보여줘. 그리고 두 번째 예시 (개미집)는 프로그램 실행 중 존재하는 객체와 작성된 클래스 사이의 관계를 보여줘.
제일 먼저, 프로그램에 존재하는 모든 객체를 위한 클래스를 작성해야 하고, 그들의 상호작용도 설명해야 해. 복잡해 보이지만, 생각보다 쉬워.
Python에서는 프로그램 실행 중 모든 것이 객체야, 그리고 프로그램을 작성하는 일은 다양한 객체 간 상호작용을 기술하는 것에 불과해. 객체들은 그저 서로의 메소드를 호출하고 필요한 데이터를 전달해.
문서화
그렇다면, 메소드에 어떤 데이터를 전달해야 하는지 어떻게 알 수 있을까? 다 있어, 이미 너를 위해 만들어져 있어.
일반적으로 모든 클래스는 무엇을 위해 만들어졌는지를 설명하는 문서를 가지고 있어. 또한 대부분의 공개 메소드에도 설명이 있어: 메소드가 하는 일과 거기에 전달해야 하는 데이터.
클래스 사용을 위해선, 클래스가 무엇을 하는지 대략적으로 알고, 각 메소드가 무엇을 하는지 정확히 알아야 해. 하지만 그것이 어떻게 작동하는지는 알 필요 없어. 일종의 마법 지팡이 같은 느낌이지.
자, 파일 복사 코드를 살펴보자:
src = open('source.txt', 'r')
dst = open('destination.txt', 'w')
for line in src:
dst.write(line)
src.close()
dst.close()
이 코드를 한 줄씩 읽어보면, 대략적으로 이 코드가 무엇을 하는지 알아챌 수 있을 거야. 물론, 약간의 경험과 연습이 필요하겠지만. 시간이 지나면, 이 코드는 너에게 익숙하고 이해하기 쉬운 코드처럼 보일 거야.
1.2 프로그램 설계
프로그램 설계는 일종의 예술 이야. 이게 쉬우면서도 동시에 어려워. 쉬운 건, 어떤 명확한 규칙이 없다는 점이야: 금지되지 않은 건 전부 가능해. 근데 어려운 건, 너무 많은 방법이 있기 때문에 최선을 찾기 어렵다는 점이야.
프로그램 설계는 책을 쓰는 것 같아. 한편으로는 그냥 글자를 쓰고, 단어를 나열하고, 문장을 작성하는 거지만, 또 다른 한편으로는 줄거리, 주인공의 성격, 내부 갈등, 대립, 서술 방식, 긴장감 등을 생각해야 하거든.
제일 중요한 건, 너의 코드는 다른 프로그래머들을 위해 작성된다는 점을 이해하는 거야.
모든 제품 개발은 변경을 수반해: 여기를 추가하고, 저기를 삭제하고, 여기를 다시 고치는 거야. 이렇게 작은 반복을 통해 크고 커다란 프로젝트가 탄생하지.
코드를 작성할 때 가장 중요한 요구 사항은: 다른 프로그래머가 코드의 의미를 이해할 수 있어야 한다는 거야. 잘못됐지만 이해할 수 있는 코드는 고칠 수 있어. 올바르지만 이해할 수 없는 코드는 개선할 수 없어. 그냥 버려야 해.
그렇다면 좋은 코드를 작성하는 방법은?
세 가지를 기억하면 돼:
- 메소드 내부에 좋은 코드를 작성할 것 — 가장 쉬운 부분이야.
- 프로그램에서 어떤 엔티티가 있어야 하는지 결정할 것.
- 프로그램을 논리적 부분으로 올바르게 나눌 것.
이제 이 개념들이 뭘 의미하는지 살펴보자.
메소드 내부에 좋은 코드 작성하기
만약 너가 적어도 초급 수준의 영어를 한다면, 코드가 때때로 영어 문장처럼 읽기 쉬운 것을 눈치챘을 수도 있어:
-
class Cat(Pet)– "Cat" 클래스는 "Pet" 클래스를 확장한다. while stream: – "스트림이 비어있지 않은 동안 ..."-
a if a < b else b– 만약a가b보다 작으면,a를 반환하고, 그렇지 않으면b를 반환한다.
일부러 이렇게 만들어진 거야. Python은 그 중 하나야: 문서화된 코드 작성이 쉽게 설계된 언어야. 좋은 Python 코드에서는 많은 메소드가 영어 문장처럼 읽혀.
코드를 작성할 때 목표는 최대한 단순하고 간결하게 작성하는 거야. 단순히 너의 코드를 다른 사람들이 얼마나 쉽게 읽을 수 있을지 생각해. 그러면 올바른 방향으로 나아갈 수 있을 거야.
Python에서는 읽기 쉬운 코드를 작성하는 것이 관례야. 이상적으로는, 각 메소드가 화면에 전부 표시될 수 있도록 (보통 20-30 줄 정도로) 작성해야 해. 이건 Python 커뮤니티의 기본 규칙이야. 개선할 수 있다면, 코드는 개선해야 해.
좋은 코드를 작성하는 가장 좋은 방법은 꾸준한 연습이야. 많은 코드를 작성하고, 다른 사람의 코드를 읽고, 더 경험 많은 동료에게 코드 리뷰를 요청해봐. 그리고 "이 정도로도 괜찮아"라고 말하는 순간, 너의 성장은 멈추게 돼.
프로그램의 엔티티 결정하기
너는 다른 프로그래머들에게 이해하기 쉬운 코드를 작성해야 해. 만약 프로그램 설계에서 10명 중 9명의 프로그래머가 클래스 A, B, C를 설계한다면, 너도 클래스 A, B, C를 프로그램에 포함시켜야 해. 다른 이들이 이해할 수 있는 코드를 작성해야 해.
탁월하고 빠르고 독창적인 코드는 좋지 않은 코드야.
다른 프로젝트를 분석해야 해: 이건 IT 산업에서 수십 년 동안 쌓아온 지혜를 얻는 가장 좋은 방법이야.
참고로, 이미 손쉽게 접근할 수 있는 멋진, 인기 많고, 잘 문서화된 프로젝트가 있어 — Python SDK. 여기서 시작해봐.
클래스와 클래스 구조를 분석해봐. 왜 특정 메소드가 static인지, 왜 특정 파라미터가 있는지 생각해봐. 왜 특정 메소드들이 존재하는지, 클래스 이름이 왜 그렇게 되어 있고, 왜 그 패키지에 위치해 있는지 고민해봐.
이 모든 질문에 답을 알게 되면, 다른 사람들이 이해할 수 있는 코드를 작성할 수 있을 거야.
하지만 하나 경고하고 싶은 건, Python SDK 메소드의 코드를 분석하지 말라는 거야. 많은 메소드들이 성능 극대화를 위해 재작성됐어 — 가독성은 의문이지.
프로그램을 논리적 부분으로 올바르게 나누기
보통 프로그램은 여러 부분, 모듈로 나뉘어져. 각 부분은 프로그램의 서로 다른 측면을 책임져.
컴퓨터에는 본체, 모니터, 키보드가 있잖아. 이들은 각각 별개로 비교적 독립적이야. 게다가 이들 간의 상호작용은 USB, HDMI 같은 표준으로 정리돼 있어. 키보드에 커피를 흘리더라도 물로 씻고 말리면 계속 사용할 수 있어.
반면, 노트북은 모놀리틱 아키텍처의 예야: 논리적 부분들이 있긴 하지만 훨씬 더 통합돼 있어. Macbook Pro의 키보드를 청소하려면 반쯤 분해해야 해. 그리고 노트북에 커피를 흘리면 새 것 구매를 고민해야 할 거야.
1.3 자신의 클래스 만들기
프로그래밍을 처음 배울 땐, 작은 것부터 시작하는 게 중요해 — 자신의 클래스를 만드는 것부터 배워봐.
물론, 너는 이미 클래스를 만들었겠지만, 프로그램에 어떤 클래스가 있어야 하고, 그 클래스가 어떻게 불려야 하며, 어떤 메소드를 가져야 하고 그들이 어떻게 상호작용해야 하는지 이해하는 법을 배워야 해.
엔티티 목록
어디서부터 시작해야 할지 모르겠다면, 시작부터 해봐.
프로그램 설계 초기 단계에서는, 간단히 프로그램에 필요한 엔티티(객체) 목록을 작성할 수 있어. 그런 다음, 각각의 엔티티를 별도의 클래스로 프로그래밍하면 돼.
예시
예를 들어, 체스 게임을 작성하려고 한다고 해봐. 체스판과 6가지 유형의 말이 필요할 거야. 말들은 각각 움직이는 방식이 다르고, 가치도 달라서 — 당연히 각각 독립된 클래스가 되어야 해. 초기 단계에서, 클래스를 많이 만드는 것이 좋아.
초보 프로그래머가 두 개의 클래스를 대신 열 개를 작성하는 건 드문 일이야. 반대로 열 개 대신 두 개나 하나를 작성하는 건 초보들이 자주 하는 일이야. 그래서 클래스는 많을수록 좋아. 그래야 너의 코드가 다른 사람들에게 더 이해하기 쉬워질 거야. 아마 너에게는 더 어렵겠지만 😛
체스
체스를 위해 클래스를 작성하기로 했다면, 클래스들이 어떻게 보일지 상상해봐.
체스판은 단순히 8x8 배열일까? 아니, 체스판을 위한 별도의 클래스를 만들어봐. 클래스 내부에 배열을 저장해. 그러면 "체스판" 클래스에 많은 유용한 메소드를 추가할 수 있어. 예를 들어, 셀이 비어 있는지 혹은 채워져 있는지를 확인하는 메소드 같은 거 말이야.
요컨대, 초반에는 "프로그램이 다양한 엔티티를 가지고 있고, 각 엔티티에는 타입이 있다"는 원칙을 따를 수 있어. 이 타입이 바로 클래스야.
GO TO FULL VERSION