이번 포스팅에서는 KIVY GUI 앱을 만들어 보면서 프레임워크의 구조에 대하여 알아본다.
키비의 설치에 관하여는 지난 포스팅을 참고한다.
먼저 프레임워크란 무엇인가?
코드, 라이브러리, 프레임워크 라는 단어들이 나올 때면 혼란스러울 때가 많다.
구분이 명확할 때도 있고 그렇지 않을 때도 있기 때문이다.
프레임워크는 어떤 한 종류의 개발 목적에 특화된 개발자의 도구라고 볼 수 있다.
사진가가 사진을 편집할 때 포토샵을 사용한다. 그래픽 프로그램을 만들어서 사용하지는 않는다. 혹은 그림판으로도 편집하거나 보정할 수 있을지는 몰라도 모든 것을 하나부터 열까지 다해야 한다. 사진을 뿌옇게 처리하고 싶은데 그런 기능을 자기가 직접 만들지는 않는다. 포토샵에 필터 기능이 다 들어있다.
프레임워크는 상위의 목적을 가진다. 예를 들면 파이썬에는 장고 django 라는 프레임워크가 있다. 웹사이트를 설계하고 구현하는 프레임워크로 장고를 사용하면 오로지 파이썬만 가지고 웹사이트를 만드는 것 보다 훨씬 빠르고 안정성 있게 개발 할 수 있다. 인터넷 서버사이드 기능과 데이터베이스가 이미 구현되어 있다. 그만큼 장점이 많으나 프레임 워크는 또 다른 하나의 언어 처럼 배워야 사용가능하다. 프레임워크의 메뉴얼이 허용하는 범위내에서 사용하게 된다. 즉 편리함 대신 자유도가 떨어질 수 있다. 하지만 실제로는 대부분 상업용 소프트웨어는 프레임워크 위에서 돌아간다. 오픈소스이건 유료이건 프레임워크를 개발하기 위해 많은 프로전문가들이 참여했기 때문에 일반 개인이 개발한 것 보다 우수하기 때문이다.
프레임워크야 말로 다음의 정신을 잘 나타낸다.
Don't reinvent the don't reinvent the wheel just realign it
(수레바퀴를 다시 발명하지 말라. 그저 조정을 해라.)
다음은 에디슨의 명언이다.
I start where the last man left off.
(나는 나 이전의 마지막 사람이 멈추고 남겨 놓은 것에서 출발한다)
프로그래밍 언어에서는 코드의 재사용성이라고 한다.
키비 프레임워크는 반응형, 멀티터치의 모바일앱을 목적으로 한 프레임워크이다. 물론 데스크탑에서도 사용이 가능하다.
다음의 전체 소스 코드는 전체를 한번 훑어본다. 약간 길어보이지만 대부분은 위젯을 배치하는 단순 반복일 뿐이다. 그 보다는 키비의 구조를 봐야한다.
먼저 모듈 import를 들여다본다. tkinter GUI를 사용해봤다면 비슷하다는 것을 알 수 있다.
Label, TextInput, Button 이것들을 widget 또는 control 이라고 한다.
컴퓨터의 GUI 에서 자주 나오는 것들이 Label Button 같은 위짓들이고 GridLayout 같은 레이아웃 매니저들이 항상 나온다. 이 두개가 있어야 GUI를 쓸만하다. 모듈을 import 하는 것은 다 사용목적이 있어서 이다. 나중에 스스로 코드를 작성할 때 염두해둔다. Label을 사용하려면 Label 모듈을 가져와야 한다.
다음의 TimeShow(Label) 클래스는 kivy 의 사용방식을 나타낸다. 프레임워크에서는 보통 상속 방식을 많이 사용한다. 사용자의 클래스 안에 프레임워크의 클래스를 부모로 받아서 부모 클래스를 __init__ 초기화 시키는 방식으로 작동시킨다. 프레임워크에서 부모 클래스의 세부적인 내용은 몰라도 된다. 아니 알기가 힘들다. 프레임워크를 설계한 사람들이 알고 있지 프레임워크의 사용자는 그런 것까지 알 수는 없다.
만약 그런게 궁굼하다면 오픈소스 커뮤니티에 참여하는 것이 좋다. 프레임워크 같은 시스템의 개발자들은 일반 코딩 입문자들 보다 한참 윗단계에 가있는 사람들이 많다. 오픈 소스에 참여한다면 자극을 받아 실력을 더 키울 수 있을 것이다. 단 오픈소스 커뮤니티라는게 어떻게 보면 사회주의 처럼 세상에 돌려주는 일이다. 공들인 시간에 비하여 돈이 되는 일은 아니니까 부업을 생각하는 사람에게는 추천하지 않는다.
리누즈 토발즈와 빌 게이츠 사례는 늘 이야기 하는데 해외의 많은 개발자 커뮤니티(특히 오픈소스 진영)들은 리누즈의 업적을 더 높게 평가하고 빌 게이츠를 거의 악의 수장에 빗대어 비판하는데 어쨋든 재산 규모만 봐도 차이가 심하다. 어릴 때 공부잘하는 아이가 커서 생각보다 돈을 많이 벌지 못하는 것과 좀 비슷하다. 돈을 벌고 싶으면 머리만 좋아서 되는게 아니라 돈을 버는데 머리를 짜내야 한다.
어찌 보면 학문은 진리를 탐구하는게 최대의 목적인데 돈을 벌기 위해서 공부한다는 말 자체에 어폐가 있는지도...
돈을 벌고 싶으면 장사를 해야한다.
import kivy
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
from kivy.uix.textinput import TextInput
from kivy.uix.button import Button
from kivy.clock import Clock
import time
class TimeShow(Label):
def update(self, *args):
self.text = time.asctime()
fontk = 'font/Cafe24Dangdanghae.ttf'
class KivyGrid(GridLayout):
def __init__(self, **kwargs):
super(KivyGrid, self).__init__(**kwargs)
self.cols = 1
self.clock = TimeShow()
self.clock.font_size = 50
Clock.schedule_interval(self.clock.update, 1)
self.add_widget(self.clock)
self.inside = GridLayout()
self.inside.cols = 2
self.inside.add_widget(Label(text='제목: ', font_name=fontk, font_size=30))
self.title = TextInput(multiline=False, font_name=fontk, font_size=30)
self.inside.add_widget(self.title)
self.inside.add_widget(Label(text='내용: ', font_name=fontk, font_size=30))
self.content = TextInput(multiline=True, font_name=fontk, font_size=30)
self.inside.add_widget(self.content)
self.inside.add_widget(Label(text='글쓴이: ', font_name=fontk, font_size=30))
self.writer = TextInput(multiline=False, font_name=fontk, font_size=30)
self.inside.add_widget(self.writer)
self.add_widget(self.inside)
self.submit = Button(text='제출하기', font_name=fontk, font_size=40)
self.submit.bind(on_press=self.pressed)
self.add_widget(self.submit)
def pressed(self, instance):
title = self.title.text
content = self.content.text
writer = self.writer.text
print('title: ', title, ' content: ', content, ' writer: ', writer)
self.title.text = ''
self.content.text =''
self.writer.text = ''
class KivyApp(App):
def build(self):
return KivyGrid()
if __name__ == '__main__':
KivyApp().run()
여기서는 파이썬의 time 모듈과 키비의 Clock 모듈을 사용해서 시계를 만들었다.
Clock.schedule_interval 메서드는 1초마다 TimeShow 클래스 (즉 Label 위젯)를 갱신한다.
이 코드에서 볼 것은 레이아웃 관리이다. KivyGrid 는 GridLayout 을 받아서 화면을 구성한다. 이 클래스 자체를 레이아웃이라 놓고 보자.
self.cols = 1 은 열이 하나라는 것이다.
self.inside.cols = 2 는 열이 2개라는 것이다.
이렇게 하면 1개의 열을 2개로 나눌 수가 있다. 그러니까 위와 같이 앞쪽 뒤쪽은 하나의 열이고 중간은 두 개의 열이 된다.
위젯 코드는 위에서 아래로 읽으면 된다. 화면에서 보는 것과 같이 add_widget 을 추가할 수록 위에서 아래로 내려온다.
마지막 Button 위젯에서는 버튼을 눌렀을 때의 실행동작을 구현할 수 있다. self.pressed 메서드에 구현한다.
self.submit.bind메서드에 on_press=self.pressed 를 보자. 함수의 참조값을 가지고 있다. () 메서드라고 이 표시를 넣으면 메서드를 즉시 실행시킨다. 주소값만 넘겨준 것은 처음부터 실행하지 말고 버튼이 클릭되었을 때 실행하라는 의미이다. 이제 presssed 를 정의해보자.
pressed 에서는 현재 텍스트 인풋의 텍스트를 다 모아서 콘솔에 출력시킨다. 파일에 출력하거나 db 에 저장하는 것도 당연히 할 수 있다. 이 데이터들을 가지고 무엇을 하건 자유다.
self.title.text 가 '' 로 갱신된다. 속성에 저장한 값이 곧 화면에 표시되는 것이라는 것을 알 수 있다.
위와 같이 실행된다. 키비를 하다가 모르는 것이 생기면 되도록 kivy 의 documentation 을 참고하는게 좋다.