파이썬 교육봉사 후기
개요
한 학기동안의 교육봉사가 끝났다. 나름 뜻깊은 시간이었다.
3/29부터 5/29까지 두 달간 매주 30분에서 1시간 반정도의 시간동안 수업을 진행했다.
원래는 직장인들 대상으로 파이썬 업무 자동화같은 것들을 해보고 나도 그 과정에서 몇 가지 프로젝트를 진행하려고 했다.
근데 갑자기 전공 수업 멘토링을 맡게 돼서 조금 난감했던 기억이 있다. 나도 2학년인데 2학년 전공이라니...?
수업 커리큘럼도 상당히 특이했는데 파이썬 기초를 4주, 알고리즘을 4주, 객체지향을 4주로 해서 배우는 식이다.
기초 문법이야 이제 백준으로 숙달됐다는 생각이니 상관없었는데, 문제는 알고리즘이었다.
1-2 때 알고리즘 강의를 듣긴 했지만 백준 뉴비인 1학년에게 c++은 너무 가혹한 언어였고,
그렇다고 겨울 신촌연합 때 열심히 들었나? 하면 그것도 아니다.
제대로 할 줄 아는 것이라고 해봤자 브루트포스에 문자열 정도고 나머지는 그냥 '들어본 무언가'에 불과헀음.
알고리즘
그런 내가 DP니 그리디니 분할 정복이니 하는 것들을 가르쳐야 하니 눈 앞이 까마득해졌다.
다행히 이번 학기에는 이지-갓이 스터디장을 한다고 하기도 했고,
저번과는 다르게 좀 열심히? 들어보려는 생각도 있었기에 일단은 불안 반 걱정 반으로 시작하게 되었다.
학회 강의를 들으면서, 그리고 가르치면서 느낀 거지만 생각보다 많은 지식이 파편화된 채로 존재했다는 것을 알게 되었다.
이유를 찾아보면 지식은 지식대로 머리에 때려박고 실제 응용과 링킹하는 과정이 없었던 것 같다.
필연성이 중요하다고 생각한다. 왜 이렇게 풀어야만 하는지에 대한 의문과 해답.
강의 내용을 잘 이해하지 못했다. 당연히 문제와 그 풀이에서도 필연성을 느끼지 못했다. 왜? 발상적 영역이라고 생각했기에.
실제로 PS를 할 때 문제를 잘 읽지 않았던 기억이 있다. 발상에 의존하니 문제에서 단서를 찾을 필요가 없었던 것이다.
그렇게 '나도 잘 모르는 상태'에서 수업을 하게 되었고,
근본적인 질문들을 처리하다보니 자연스럽게 '알고 있다고 생각하는 것'들에 대해서 많은 고민을 하게 되었다.
분할 정복은 뭐죠? 문제를 부분 문제로 쪼개서 푼 뒤 다시 합치는 방식.
어떻게 하나요? 재귀적으로 호출하면서 베이스 케이스 탐색.
구체적으로는? 피보나치 수열 구현, 합병 정렬 ...
이제는 익숙해질 때도 된 '연속 구간의 최대합'도 다루게 되었다.
첫번째는 브루트포스를 쓰는 것이고 두번째는 분할 정복을 이용하여 구간의 최댓값을 갱신하는 방법,
세번째는 동적 계획법으로 점화식을 세우고 구하는 방법... 이렇게 다뤘던 기억이 난다.
그렇게 하다보니 분할 정복과 DP는 비슷한 점이 많은데 무슨 차이가 있는 거지? 라는 궁금증이 생겼다.
분할 정복은 문제를 부분 문제로 분할하고 해결한 뒤 합치는 것인데, DP도 생각해보니 뭔가 비슷한 느낌?이 있었기 때문.
마침 그 주에 dp 강의가 있어서 들어보니,
DP는 '중복되는 부분 문제'를 저장해서 빠르게 푸는 '메모이제이션'을 쓴다는 차이점이 있다는 것을 알게 되었다.
그 다음 주는 그리디였는데 그러면 DP랑 그리디와는 무슨 차이일까? 라는 생각도 들었다.
그리고 실제로 DP랑 그리디랑 이런저런 알고리즘의 차이를 묻는 질문도 들어와서,
머리를 싸매고 고민을 하다가 든 비유가
모든 곳을 전부 둘러보면 -> 브루트포스
모든 곳을 재귀적으로 전부 둘러보는데 아니다 싶으면 되돌아가면 -> 백트래킹
모든 곳을 쪼개서 둘러보면 -> 분할정복
모든 곳을 쪼개서 둘러보는데 중복되는 부분을 저장하면 -> DP
모든 곳을 둘러보지 않고 매 순간 최적의 선택을 한다면 -> 그리디
였는데, 당시에는 정말 엄청난 비유야! 하면서 나 자신에게 감탄했지만 돌이켜보면 사실 이게 정확한지도 잘 모르겠다 (...)
사실 알고리즘 이론이라는 것이 내가 기존에 인식했던 것처럼 다 따로따로 노는 것은 아니라고 생각한다. 실제로도 아니고.
그리고 여러 가지 이론을 학습해야 한다면 그들 간의 공통점과 차이점을 바탕으로 배우는 것이 효과적이라고 본다.
(이건 나도 특히 국어 학습에서 강조하는 부분이기도 하다)
객체지향
나머지 2~3주는 객체지향을 다뤘다. 사실 OOP는 지금 배우고 있는 과목이기도 하고,
작년에 컴공개를 인상깊게 배우기도 했고, 지금 컴공개 멘토링을 할 때 가르치는 부분도 있어서 열심히 가르쳤다.
사실 파이썬으로 객체지향적인 프로그램을 설계해본 적은 없다. 기껏해야 작년 컴공개 과제 정도?
이번에 랜디봇 프로젝트에서 써먹고 싶긴 했지만 규모가 그리 크지도 않았고, 설계하는데 드는 시간이 더 길어서 포기했었다.
oop의 진수를 맛보고 본질을 어느 정도 깨닫게 된 것은 이번 객체지향 수업 과제를 하면서부터였음.
작년만 해도 무지성으로 '아 일단 private property 쓰면 캡슐화라고 ㄹㅇ ㅋㅋ' 하면서 과제를 했던 것 같은데,
뭐 이 정도면 장족의 발전이 아닌가 싶다.
컴퓨팅적 사고
다시 수업으로 돌아와서, 사실 뭐부터 설명해야 할 지가 굉장히 난감했는데, 일단은 컴퓨팅적 사고부터 시작을 했다.
컴공이 되기 위한 첫걸음은 일단 컴퓨팅적 사고부터 시작한다고 봐도 무방하다고 생각하기 때문이다.
요즘 아이들 대상으로 하는 코딩 교육을 보면 실제로 코딩을 한다기 보다는 '컴퓨팅적 사고'를 기르는 훈련처럼 보인다.
언어는 결국 그 과정에 있어서의 수단일 뿐이다. python을 쓰든 c를 쓰든 아희를 쓰든 엄랭을 쓰든,
1부터 10까지를 더하고 출력하는 코드를 구현하는 데에는 문제가 없다.
다만 파이썬을 쓴다면 파이썬이 가진 라이브러리 생태계, 생산성을 염두에 둔 것이고, 아희나 엄랭을 쓴다면... 이건 잘 모르겠다.
코딩 교육에서 스크래치를 사용하는 것도, 스크래치가 가진 그래픽 인터페이스가 학습 상 이점을 가지기 때문인 것이 아닌가?
무튼 언어는 언어마다의 특징을 가지고 그 특징에 적합한 것들을 구현하기 위함이지 그 자체가 본질은 아니라는 것이다.
유튜브에서 나오는 '샌드위치 코딩 교육' 영상도 컴퓨팅적 사고의 본질은 언어와 관련이 없다는 것을 보여주는 대표적인 사례다.
다른 사례도 구구절절 설명해보자면... python 수업에서 흔히 찾아볼 수 있는 turtle 그래픽 정도?
turtle 모듈도 시각적-일상적 레벨에서 컴퓨팅적 사고를 촉진시킬 수 있는 수단이기 때문에,
전공생들 입문 수업보다는 일반인들 대상 입문 수업에서 주로 활용한다.
실제로 우리 학교 공대생 대상 python 수업에서 종종 쓰는 것을 알 수 있다.
근데 사실 우리가 일상적으로 접하는 '컴퓨팅적 사고'는 결국은 절차지향적 관점으로 귀결된다.
물론 컴퓨팅적 사고가 객체지향과 아예 무관하다! 라는 것은 아니지만,
'우리가 일상적으로 접하는 것'들은 아무래도 절차지향과 더 밀접하다고 할 수밖에 없다.
위의 '샌드위치 코딩'도 그렇다. 빵을 꺼내서 / 잼을 발라라, 의 절차를 거치지 않던가?
이걸 인간과 빵/잼 간의 상호작용으로 볼 수는 있겠지만 어떤 관점을 택하더라도 저 두 명령으로 귀결된다.
* 이런 점에서, 객체지향이라고 해서 절차지향과 완벽하게 반대된다고 생각하지는 않는다. 결국 '지향' 아닌가?
언어적으로 봤을 때 '지향'은 무엇을 '더' 그리고 '덜 고려할 것인가에 대한 의미이기에
객체지향과 절차지향은 결국 주어진 문제를 '어떤 관점'으로 해결할 것인가에 대한 문제인 것이다.
하지만 컴퓨터의 구조 자체는 절차적으로 문제를 해결하도록 되어있기에,
객체지향도 세부적인 처리 로직을 봤을 때는 결국 '절차'와 떼놓을 수는 없는 관계라고 생각한다.
그래서 우리가 컴퓨팅적 사고에 숙달되었다는 것은 절차지향적 관점을 잘 이해한다는 것과 동시에
객체지향적인 프로그램을 설계할 수 있는 준비가 되었다는 것을 의미한다... 정도가 내가 수업했던 내용이고,
나머지는 그냥 다른 교재에서 흔히 볼 수 있는 것들을 예시로 들어주면서 해설하는 방식이었다.
* 참고로 '흔히 볼 수 있는 것들' 이라 하면,
class Animal, class Cat, class Dog 같은 것들 만들어서 상속 관계 구현하고, sound() 메서드 오버라이딩 해서 다형성 설명하는, 객체지향 배웠다 하면 누구나 아는 그런 웰-노운 예시들을 말하는 거다.
왜 추상화라는 이름이 붙었을까? (feat. 일반화와의 차이점은?)
또 '추상화'를 설명할 때가 기억에 남는다.
새내기 때 객체지향에서 가장 이해하기 어려웠던 특성이 이 추상성이었다.
그냥 공통점과 차이점을 엮는 것인데 왜 굳이 일반화(generalization)이 아닌 Abstration이라는 이름이 붙는지도 이해하지 못했고,
굳이 상속과 추상화를 분리하여 설명하는 이유 역시 알지 못했다.
자바스크립트는 왜 프로토타입을 선택했을까
프로토타입으로 검색하면 으레 나오는 서두처럼 저 또한 자바스크립트를 처음 접했을 때 가장 당황스러웠던 게 프로토타입이었습니다.
medium.com
아주 인상깊게 본 글이다. 원래는 자바스크립트의 프로토타입 기반 상속을 설명하는 글이지만,
일반적인 클래스 기반 상속이 만들어진 원인을 서양철학(플라톤의 이데아론)과 관련지어 설명하는 부분이 있다.
요약하자면 플라톤의 이데아론에 의하면 세계에는 '현실 세계의 사물'과 그것들의 본질인 '이데아'가 존재하고,
인스턴스와 클래스의 관계 역시 이러한 서양철학적인 관점이 반영되었다는 것이다.
아리스토텔레스의 분류(classification) : 이는 전통적인 클래스 기반 객체 지향 프로그래밍의 아이디어-일반화(generalization)와 정확히 일치합니다. 여기서 속성은 클래스의 프로퍼티가 되겠죠. 프로퍼티가 유사한 객체가 있다면 일반화 과정을 통해 클래스로 추상화됩니다.
여기서 궁금증이 생겼다. 객체지향의 '일반화'는 뭐지? 추상화랑 상속과는 다른 것인가?
개념이 명확하게 나뉘지 않아 찾아보니 '객체지향의 연관성'에서 분류화, 일반화와 같은 개념이 등장했다.
객체지향의 연관성에는 is-instance-of 관계를 가지는 분류화(classification)와 is-a 관계를 가지는 일반화(generalization)가 존재하고, 일반화는 상속과 유사한 의미로 사용된다는 것을 참고하여 이를 정리하면 다음과 같다.
동일한 특성들을 갖는 '인스턴스(객체)'를 모아 '클래스'를 구성 -> 분류화 (== 객체들에 대한 '추상화')
(즉 '인스턴스' is-instance-of '클래스' 관계가 성립)
동일한 특성들을 갖는 '클래스/'를 모아 '상위 클래스'를 구성 -> 일반화 (== '상속')
('즉 '서브 클래스' is-a(==is a kind of **) '슈퍼 클래스' 관계가 성립)
(** 스프링 입문을 위한 자바 객체지향의 원리와 이해 에서는 is-a 관계가 클래스-클래스 간의 관계인지, 아니면 인스턴스-클래스 관계인지 불분명하기 때문에 이를 좀 더 명확하게 하기 위해 is-a 대신 is-a-kind-of 라는 말을 사용하기를 권장한다고 한다.)
정리하자면 추상화는 기능적인 측면에서 봤을 때 각각의 '인스턴스(객체)'를 '분류화'하여 '클래스'로 나타내는 것이 된다.
그리고, 인스턴스는 '실체가 있는' 객체이고 클래스는 '실체가 없는' 틀이다.
실체가 있는 대상을 실체가 없는 개념으로 표현하는 것이니 '추상화'라는 이름이 붙게 된 것이다.
이제 일반화(상속)과 추상화의 차이점에 대해서만 알면 되...지만,
적다보니까 나름 구구절절 설명도 길어지고, 지금 읽는 '객체지향의 사실과 오해' 얘기도 하고,
개인적으로 찾아본 내용들도 언급해야 하다 보니 별도의 아티클로 다루는 편이 좋을 것 같다.
작성 전 참고한 아티클들을 아래에 기록해두니 궁금한 분들은 참고하시길.
https://bloowhale.tistory.com/27
https://en.wikipedia.org/wiki/Abstraction_(computer_science)
Abstraction (computer science) - Wikipedia
From Wikipedia, the free encyclopedia Jump to navigation Jump to search Technique for arranging complexity of computer systems The essence of abstraction is preserving information that is relevant in a given context, and forgetting information that is irre
en.wikipedia.org
In object-oriented programming theory, abstraction involves the facility to define objects that represent abstract "actors" that can perform work, report on and change their state, and "communicate" with other objects in the system. The term encapsulation refers to the hiding of state details, but extending the concept of data type from earlier programming languages to associate behavior most strongly with the data, and standardizing the way that different data types interact, is the beginning of abstraction. When abstraction proceeds into the operations defined, enabling objects of different types to be substituted, it is called polymorphism. When it proceeds in the opposite direction, inside the types or classes, structuring them to simplify a complex set of relationships, it is called delegation or inheritance.
객체지향 프로그래밍 이론에서 추상화는 작업을 수행하고, 그들의 상태를 보고하고 변경하며, 시스템 상 다른 객체들와 '소통'할 수 있는 추상 "행위자"를 의미하는 객체를 정의하는 능력과 관련되어 있습니다. '캡슐화'라는 용어는 '상태'의 세부 정보를 숨기는 것을 의미하지만, 초기 프로그래밍 언어로부터 데이터 타입의 개념을 확장하여 '행위'를 데이터와 강력하게 연관시키고, 다른 데이터 타입 상호작용하는 방식을 표준화는 것이 '추상화'의 시작입니다. 정의된 작업에 추상화가 진행되어 다른 타입의 객체가 대체될 수 있게 한다면, 이것을 '다형성'이라고 합니다. 만약 추상화가 타입이나 클래스 내부에서 반대 방향으로 진행되어 복잡한 관계 집합을 단순화하도록 구조화한다면, 이것을 '위임' 또는 '상속'이라고 합니다.
위키피디아에서는 추상화를 단순히 공통점과 차이점을 인식하는 것에서 더 나아가,
'캡슐화'와 '다형성', '위임과 상속' 같은 다른 객체지향의 특징과 관련시켜 설명했다. 이 점이 인상깊었다.
https://www.geeksforgeeks.org/abstraction-in-c/?ref=lbp
데이터 추상화 & 캡슐화의 개념과 차이
데이터 추상화(data abstraction)와 데이터 캡슐화(data encapsulation)의 개념과 그 차이에 대해 알아보자. 데이터 추상화와 데이터 캡슐화는 비슷하긴 하지만 다른 객체 지향 프로그래밍의 개념이다. 먼
hodev.tistory.com
그 외에는 그동안 객체지향 과제를 하면서 느꼈던 감상들이나, 설계할 때 도움될 만한 개념인 is-a, has-a 써먹는 법,
setter를 이용하여 예외 처리 없이 유도리 있게 파라미터를 처리하는 방법... 같이
실질적으로 도움이 될 수 있는 부분들 위주로 알려주려고 했던 것 같다.
정리
C++의 객체지향과 파이썬의 객체지향을 비교해보는 것도 흥미로웠지만,
무엇보다 알고리즘 패러다임과 개념들이 가지는 관계에 대해서 인식한 것이 가장 큰 성과였다.
남에게 설명해주는 것은 나나 남이나 항상 도움이 된다는 생각이다.
굳이 교육같은 다이렉트한 방식이 아니더라도, 내가 이해한 것들을 글로 쓰는 것 역시 비슷한 맥락이라고 본다.
아는 것들을 복기하는 과정에서 더 잘 알게 되는 것도 있고, 안다고 생각하는 것이 사실은 잘 알지 못하는 것인 경우도 있기에...
그래서 애매하게 배운 것들을 정리하는 데에 효과적인 것 같다.
애매하게 아는 게 가장 위험하다고 생각한다. 인간은 가끔 '익숙함'을 '이해'와 혼동하기 때문이다.
가르치다 보면 초심자의 눈에서 바라볼 수 있기 때문에 '익숙함의 문제'도 해결할 수 있었다.
이후에도 여건이 된다면 계속하고 싶지만,
지금은 아는 것들을 정리하는 것보다는 새로운 것들을 계속 배워야 하는 시점인 것 같다.