http://bcho.tistory.com/1216 를 통하여 tf-idf를 이용하여 문서를 벡터화 하고, nmf를 이용하여 문서의 특성을 추출한 다음, 코싸인 유사도를 이용하여 유사 문서를 검색하는 알고리즘에 대해서 알아보았다. 이번글에서는 이 알고리즘을 직접 sklearn을 이용해서 구현해보도록 하자. sklearn은 이용하면 분산 학습을 이용한 대규모 데이타 처리는 불가능하지만, 작은 수의 문서나 모델에는 사용이 가능하다. 무엇보다 sklearn의 경우 대부분의 모델을 라이브러리화 해놓았기 때문에, 복잡한 구현이 없이 쉽게 사용이 가능하다.
df_features 변수에 문서별 특징과 문서 제목을 가지고 데이타 프레임을 만들어서 생성하였다.
인덱스는 문서의 이름이 될것이고 0~39 컬럼은 각문서별 특징이 된다. 출력해보면 대략 다음과 같은 모양이 된다.
문서 유사도 계산
문서별로 특징을 계산이 끝났으면 특정 문서와 유사한 문서를 찾도록 해보자.
앞의 글에서도 설명했지만, 문서의 유사도는 코싸인 유사도를 사용한다.
공식을 다시 기억해보면
여기서 A는 문서 A의 특성 행렬, B는 B 의 특성 행렬이 된다. |A|와 |B|는 각 문서 특성 행렬의 벡터의 길이인데, 앞에서 정규화 Normalization 을 하면서 각 문서의 행렬의 크기가 1이 되었기 때문에, 여기서 코싸인 유사도는 A*B / |A|*|B| = A*B / 1*1 = A*B 가된다.
즉 두 문서의 특성 행렬을 곱한 값이 코싸인 유사도가 된다.
데이타 프레임을 이용하면, 하나의 문서 특성 행렬을 전체 문서에 대해서 곱할 수 있다. .dot 함수를 이용하면 되는데,
article = df_features.loc['WHAT car is this!?']
“WHAT car is this!?” 라는 문서의 유사한 문서를 찾아보도록 하자. df_features에서 “WHAT car is this!?” 의 특성 행렬을 찾아내서 article 변수에 저장하고
similarities=df_features.dot(article)
전체 문서의 특성행렬에서 각 문서의 특성 행렬과 article 문서의 특성행렬을 곱한다. 그러면 article 문서에 대해서 각문서에 대한 유사도가 계산이된다.
top=similarities.nlargest()
이 값을 큰 순서대로 소팅해서 top 이라는 변수에 저장해놓고, 유사도가 높은 문서데로 문서의 제목과 유사도를 출력해본다.
texts = df.loc[top.index]['text'].tolist() i =0 for text in texts: print('TITLE :'+top.index[i]+" Similarities:"+str(top[i])) #print(text+'\n') i = i+1
다음은 실행 결과이다.
TITLE :WHAT car is this!? Similarities:1.0 TITLE :Re: WHAT car is this!? Similarities:0.999080385281 TITLE :Re: New break pads & exhausts after 96K km (60K mi) on '90 Maxima? Similarities:0.980421814633 TITLE :Insurance Rates on Performance Cars SUMMARY Similarities:0.945184088039 TITLE :Re: What is " Volvo " ? Similarities:0.935911211878
간단하게 tf-idf와 NMF를 이용한 문서 유사도 측정을 구현해봤다. 조금 더 높은 정확도와 대규모 학습을 위해서는 이보다는 Word2Vector를 이용한 문서의 벡터화와, 딥러닝을 이용한 문서의 유사도 분석을 하면 훨씬 정확도를 높일 수 있다. 전체 기본 개념은 유사하다고 보면 된다.
이 그림은 2차원에서 1차원으로 PCA 분석을 이용하여 차원을 줄인 예인데, 2차원에서는 파란색과 붉은색이 구별이 되는데, 1차원으로 줄면서 1차원상의 위치가 유사한 바람에, 두 군집의 변별력이 없어져 버렸다.
t-SNE
이런 문제를 해결하기 위한 차원 감소 방법으로는 t-SNE (티스니라고 읽음) 방식이 있는데, 대략적인 원리는 다음과 같다.
먼저 점을 하나 선택한다. 아래는 검정색점을 선택했는데, 이 점에서 부터 다른점까지의 거리를 측정한다.
다음 T 분포 그래프를 이용하여, 검정 점(기준점) 을 T 분포 상의 가운데 위치한다면, 기준점으로부터 상대점 까지 거리에 있는 T 분포의 값을 선택(위의 T 분포 그래프에서 파란점에서 위로 점섬이 올라가서 T분포 그래프상에 붉은 색으로 X 표가 되어 있는 값)하여, 이 값을 친밀도 (Similarity)로 하고, 이 친밀도가 가까운 값끼리 묶는다.
이 경우 PCA 처럼 군집이 중복되지 않는 장점은 있지만, 매번 계산할때 마다 축의 위치가 바뀌어서, 다른 모양으로 나타난다. 단 데이타의 군집성과 같은 특성들은 유지 되기 때문에 시각화를 통한 데이타 분석에는 유용하지만, 매번 값이 바뀌는 특성으로 인하여, 머신러닝 모델의 학습 피쳐로 사용하기는 다소 어려운점이 있다.
아래 그림은 같은 데이타로 t-SNE 분석을 각각 한번씩한 결과를 시각화 해서 표현한 결과 인데, 보는 것과 같이 군집에 대한 특성은 그대로 유지 되지만 값 자체는 변화가 된것을 확인할 수 있다.
안녕하세요. T-SNE관련 예제를 찾고있었는데 덕분에 잘 배울 수 있었습니다.
한가지 질문이 있는데 plt.scatter(xs,ys,c=labels) 에서 c=labels 를 빼고 실행을 하면 구동이 되는데
c=labels 를 넣고 실행하면 아래와 같은 키 에러가 발생하는데, 원인이 무엇인지 알고 계신지 궁금합니다.
C:\Program Files\Anaconda3\envs\tensorflow\lib\site-packages\pandas\core\indexes\base.py in get_loc(self, key, method, tolerance)
3077 try:
-> 3078 return self._engine.get_loc(key)
3079 except KeyError:
이번에는 클러스터링 알고리즘중 밀도 방식의 클러스터링을 사용하는 DBSCAN(Density-based spatial clustering of applications with noise) 에 대해서 알아보도록 한다.
앞에서 설명한 K Means나 Hierarchical 클러스터링의 경우 군집간의 거리를 이용하여 클러스터링을 하는 방법인데, 밀도 기반의 클러스터링은 점이 세밀하게 몰려 있어서 밀도가 높은 부분을 클러스터링 하는 방식이다.
쉽게 설명하면, 어느점을 기준으로 반경 x내에 점이 n개 이상 있으면 하나의 군집으로 인식하는 방식이다.
그러면 조금 더 구체적인 개념과 용어를 이해해보자
먼저 점 p가 있다고 할때, 점 p에서 부터 거리 e (epsilon)내에 점이 m(minPts) 개 있으면 하나의 군집으로 인식한다고 하자. 이 조건 즉 거리 e 내에 점 m개를 가지고 있는 점 p를 core point (중심점) 이라고 한다.
DBSCAN 알고리즘을 사용하려면 기준점 부터의 거리 epsilon값과, 이 반경내에 있는 점의 수 minPts를 인자로 전달해야 한다.
아래 그림에서 minPts = 4 라고 하면, 파란점 P를 중심으로 반경 epsilon 내에 점이 4개 이상 있으면 하나의 군집으로 판단할 수 있는데, 아래 그림은 점이 5개가 있기 때문에 하나의 군집으로 판단이 되고, P는 core point가 된다.
아래 그림에서 회색점 P2의 경우 점 P2를 기반으로 epsilon 반경내의 점이 3개 이기 때문에, minPts=4에 미치지 못하기 때문에, 군집의 중심이 되는 core point는 되지 못하지만, 앞의 점 P를 core point로 하는 군집에는 속하기 때문에 이를 boder point (경계점)이라고 한다.
아래 그림에서 P3는 epsilon 반경내에 점 4개를 가지고 있기 때문에 core point가 된다.
그런데 P3를 중심으로 하는 반경내에 다른 core point P가 포함이 되어 있는데, 이 경우 core point P와 P3는 연결되어 있다고 하고 하나의 군집으로 묶이게 된다.
마지막으로 아래 그림의 P4는 어떤 점을 중심으로 하더라도 minPts=4를 만족하는 범위에 포함이 되지 않는다. 즉 어느 군집에도 속하지 않는 outlier가 되는데, 이를 noise point라고 한다.
이를 모두 정리해보면 다음과 같은 그림이 나온다.
정리해서 이야기 하면, 점을 중심으로 epsilon 반경내에 minPts 이상수의 점이 있으면 그 점을 중심으로 군집이 되고 그 점을 core point라고 한다. Core point 가 서로 다른 core point의 군집의 일부가 되면 그 군집을 서로 연결되어 있다고 하고 하나의 군집으로 연결을 한다.
군집에는 속하지만, 스스로 core point가 안되는 점을 border point라고 하고, 주로 클러스터의 외곽을 이루는 점이 된다.
그리고 어느 클러스터에도 속하지 않는 점은 Noise point가 된다.
장점
DBSCAN 알고리즘의 장점은
K Means와 같이 클러스터의 수를 정하지 않아도 되며,
클러스터의 밀도에 따라서 클러스터를 서로 연결하기 때문에 기하학적인 모양을 갖는 군집도 잘 찾을 수 있으며
fromsklearn.clusterimport DBSCAN importmatplotlib.pyplotasplt importseabornassns # create model and prediction model = DBSCAN(min_samples=6) predict = pd.DataFrame(model.fit_predict(feature)) predict.columns=['predict'] # concatenate labels to df as a new column r = pd.concat([feature,predict],axis=1)
다음은 모델을 선언하고, 데이타를 넣어서 학습을 시킨다.
학습이 끝난 결과를 다음과 같이 3차원 그래프로 시각화 해보자. 아래 시각화는 3차원인데, 학습은 4차원으로 하였다. 그래서 다소 오류가 있어 보일 수 있다. 다차원 데이타를 시각화 하기위해서는 PCA나 t-SNE와 같은 차원 감소 (dimensional reduction) 기법을 사용해야 하는데, 이는 다음 글에서 다루도록한다.
우연히 검색해서 들어왔는데 좋은정보 감사합니다.
그런데 다 이해가됫는데 하나가 이해가 안되서 혼란스럽네요.
이를 모두 정리해보면 다음과 같은 그림이 나온다 <== 요 그림에서요.
가장 왼쪽에 있는 포인트는 왜 noise point 아니고 마지막 그림에 포함이 되는걸까요?
앞의 코드에서 계층형 클러스터링을 한 mergings 변수를 fcluster 함수에 전달하고 두번째 인자에 y의 임계값을 3으로 지정하였다. Predict 컬럼에는 원본 입력데이타에 대한 예측 결과 (어느 클러스터에 속해있는지를 0,1,2로 입력 데이타의 수만큼 리턴한다.)를 리턴한다.
이를 원본 데이타의 라벨인 labels[‘label’]값과 Cross tabulation 분석을 해보았다.
세로축이 예측 결과, 가로측이 원래 값이다.
원래 label이 0인 데이타와 1인 데이타는 각각 잘 분류가 되었고, 2인 데이타는 34개만 정확하게 분류가 되었고 16개는 원본 레이블이 1인 데이타로 분류가 되었다.
지금까지 Hierachical clustering model에 대해서 알아보았다. K Means와 같은 군집화 모델이라도 내부 알고리즘에 따라서 군집화 결과가 다르기 때문에, 샘플 데이타의 분포를 보고 적절한 클러스터링 모델을 고르는 것이 필요하다. 다행이 sklearn의 경우 복잡한 수식 이해 없이도 간단한 라이브러리 형태로 다양한 클러스터링 모델 사용할 수 있도록 해놨기 때문에, 여러 모델을 적용해가면서 적정한 데이타 분류 방식을 찾아보는 것이 어떨까 한다.
백앤드 엔지니어와 백그라운드를 가진 경험상, 머신러닝을 공부하면서 헷갈렸던 부분중 하나가, 데이타에 대한 시각화이다. 머신러닝은 모델을 구현하는 것도 중요하지만, 학습할 데이타를 선별하고, 만들어진 모델을 검증하기 위해서는 데이타를 이해하는 것이 필수적이고 이를 위해서는 데이타를 시각화 해서 보는 것이 매우 중요하다.
그동안 그래프를 그리는 것을 스택오버플로우등에서 찾아서 복붙을 해서 사용하다가 matplotlib를 정리해야겠다고 해서 메뉴얼을 봤지만 도무지 이해가 되지 않아서, 결국 온라인 강좌를 들어서 정리해봤는데, 역시 강좌를 들으니까는 훨씬 빠르게 이해가 된다.
오늘은 matplotlib를 이용하여 기본적인 그래프를 그리는 방법에 대해서 정리하도록 한다.
기본 그래프 그리기
기본적인 그래프를 그리기 위해서는 matplotlib.pyplot에서 plot(x,y)를 사용하면 된다. x,y는 각각 X축과 Y축의 값이 된다.
frommatplotlibimport pyplot as plt importnumpyasnp x = np.arange(1,10) y = x*5 plt.plot(x,y) plt.show()
색깔 바꾸기
그래프를 그릴때 선의 색을 지정하기 위해서는 plot에서 인자로 컬러를 주면된다. 컬러표는 아래를 참고하면 되고 붉은색은 r, 파란색은 b으로 정의한다.
frommatplotlibimport pyplot as plt importnumpyasnp x = np.arange(1,10) y = x*5 plt.plot(x,y,'r') plt.show()
선 종류 변경하기
선을 그릴때, 다양한 선의 종류를 선택할 수 있다. 디폴트가 직선이고, 점으로 표현하는 마커나 점선등을 선택할 수 있다.
선의 선택은 plot에서 세번째 인자에 선의 종류를 지정하면 되고, 색을 같이 지정하려면 다음문자에 색을 지정하면 된다 다음은 동그란 마커 ‘o’를 붉은색 ‘r’로 표현하기 때문에, 세번째 인자를 ‘or’로 전달하였다.
frommatplotlibimport pyplot as plt importnumpyasnp x = np.arange(1,10) y = x*5 plt.plot(x,y,'or') plt.show()
다음은 선에 대한 종류표이다.
라벨과 타이틀
그래프를 그릴때 그래프의 타이틀과 X,Y축의 라벨을 표현하기 위해서는 타이틀은 plt.title(“타이틀명"), X,Y축에 대한 라벨은 plt.xlabel(‘X축 라벨명'), plt.ylabel(‘Y축 라벨명') 을 사용한다.
frommatplotlibimport pyplot as plt importnumpyasnp x = np.arange(1,10) y = x*5 plt.plot(x,y) plt.xlabel('x axis') plt.ylabel('y axis') plt.title('matplotlib sample') plt.show()
구간 확대/축소
그래프는 입력되는 x,y의 최소,최대 구간으로 자동으로 그려지는데, 이 구간을 키우거나 줄이기 위해서 x,y의 구간을 정의할 수 있다. x축은 plt.xlim(최소,최대), y축은 plt.ylim(최소,최대)로 정의하면 된다.
아래는 x축을 2~3, y축을 5~20으로 확대해서 그래프를 그리는 예제이다.
frommatplotlibimport pyplot as plt importnumpyasnp x = np.arange(1,10) y = x*5 plt.xlim(2,3) plt.ylim(5,20) plt.plot(x,y) plt.xlabel('x axis') plt.ylabel('y axis') plt.title('matplotlib sample') plt.show()
레전드
그래프를 그릴때 여러개의 그래프를 같이 그릴 수 있는데, 이경우 각 그래프가 구분이 안되기 때문에, 그래프마다 라벨을 달고 이 라벨명을 출력할 수 있는데, 이를 legend라고 한다.
아래는 first와 second 라는 두개의 그래프를 그리고, 우측 상단에 legend를 표현한 예이다.
legend를 사용하기 위해서는 plt.plot에서 label 변수에 그래프의 이름을 정의하고, plt.legend(‘위치')를 정해주면 legend를 그래프상에 표현해주는데, legend의 위치는 아래 표를 참고하면 된다.
frommatplotlibimport pyplot as plt importnumpyasnp x = np.arange(1,10,0.1) y = x*0.2 y2 = np.sin(x) plt.plot(x,y,'b',label='first') plt.plot(x,y2,'r',label='second') plt.xlabel('x axis') plt.ylabel('y axis') plt.title('matplotlib sample') plt.legend(loc='upper right') plt.show()
어노테이션
다음은 어노테이션이라는 기능으로, 그래프에 화살표를 그린후, 그 화살표에 문자열을 출력하는 기능이다. 예를들어 “이값이 최소값" 이런식으로 화살표를 그려서 표현할때 사용하는데 plt.annotate 함수를 사용하면 된다.
plt.annotate(‘문자열',xy,xytext,arrowprops) 식으로 사용한다.
문자열은 어노테이션에서 나타낼 문자열이고, xy는 화살표가 가르키는 점의 위치, xytext는 문자열이 출력될 위치, arrowprops는 화살표의 속성으로 칼라등을 정의한다.
from matplotlib import pyplot as plt import numpy as np x = np.arange(1,10) y = x*5 plt.plot(x,y) plt.annotate('annotate',xy=(2,10),xytext=(5,20),arrowprops={'color':'green'}) plt.show()
서브플롯
여러개의 그래프를 그리고 싶을때가 있는데, 이 경우 서브플롯이라는 것을 사용한다. 서브플롯은 그래프가 그려질 위치를 격자형으로 지정하는데, plt.subplot(nrow,ncol,pos) 식으로 사용한다.
nrow,ncol은 그래프를 그린 plain의 크기를 지정하는데, 3,2면 3줄로, 가로는 2칸으로 된 그래프 plain 설정한다. 그리고 마자막 pos는 몇번째 plain에 그래프를 그릴지 지정하는데, 아래와 같이 상단에서 부터 우측,아래 방향으로 1,2,3,4,5,6 순서가 된다.
1
2
3
4
5
6
아래 그림은 2,1 크기의 plain 을 만들어놓고 그래프를 위,아래로 두개를 그리는 예제이다.
일반적으로 모바일 로그 분석은 클라우드 기반의 무료 솔루션을 이용하다가 자체 구축으로 가는 경우가 많다.
클라우드 기반의 무료 로그 분석 솔루션으로는 구글 애널러틱스, 야후의 플러리, 트위터의 패브릭 그리고 구글의 파이어베이스 등이 있다.
이런 무료 로그 분석 솔루션들을 사용이 매우 간편하고, 핵심 지표를 쉽게 뽑아 줄 수 있으며, 별도의 운영이 필요 없다는 장점을 가지고 있다.
그러나 이런 클라우드 기반의 무료 솔루션의 경우에는 요약된 정보들만 볼 수 있고 또한 내가 원하는 지표를 마음대로 지정을 할 수 없기 때문에, 어느정도 서비스가 성장하고 팀의 여력이 되면 별도의 로그 수집 및 분석 솔루션을 만드는 것이 일반적이다.
오픈 소스 기반의 분석 솔루션
오픈 소스를 조합해서 모바일 로그 수집 시스템을 만들면 대략 다음과 같은 모양이 된다.
API 서버에서 로그를 수집해서 카프카등의 큐를 통해서 로그를 모으고, 실시간은 스파크 스트리밍, 배치는 하둡이나 스파크 스트리밍 프레임웍을 이용합니다. 대쉬 보드는 만드는 곳도 있지만, 주피터 노트북이나 제플린 노트북과 같은 노트북을 이용한다.
요즘은 데이타 저장 및 분석에 ELK (Elastic Search + Logstash + Kibana)와 같은 솔루션도 많이 사용하고 있다.
그런데 이런 오픈 소스 솔루션 기반으로 로그 분석 시스템을 개발하면 몇가지 문제가 발생한다.
개발에 드는 노력 이런 오픈소스 스택으로 시스템을 개발하려면, 이 프레임웍에 대해서 잘 아는 전문가가 필요합다. 일반적인 스타트업에서는 구하기도 힘들고, 기업이 어느정도 규모가 되더라도 빅데이타 관련 기술을 다룰 줄 아는 엔지니어는 여전히 귀한 엔지니어이고, 이런 엔지니어들이 있다하더라도, 시스템 설계및 구현에는 수개월의 기간이 소요 되게 된다.
시스템 구매와 운영 다음 문제는 모바일 데이타는 양이 많기 때문에, 위에서 언급한 빅데이타 관련 오픈 소스를 사용하게 되는데, 이러한 시스템은 하드웨어 자원이 수십에서 수백대가 필요하거니와, 이를 설치하고 운영하는 것 역시 쉽지 않다. 로그를 수집하고 분석하는 로직을 만들어야 하는 엔지니어들이 정작 데이타 분석 보다는 시스템 운영과 유지보수에 많은 시간을 낭비해야 한다는 문제가 발생한다. 규모가 작은 스타트업이나 엔지니어링 능력이 되지 않는 기업들은 이런 빅데이타 분석은 엄두도 내지 못하는 상황이 되고, 디테일한 데이타 분석을 하지 못하게 되니 자연히 경쟁력이 떨어지게 될 수 있다.
연산 시간 그리고 수집 수백대의 서버를 가지고 있다하더라도, 데이타 연산 시간은 수십분에서 수시간이 소요된다. 특히 데이타 분석 서버들이 분석을 하고 있을때는 다른 분석을 하고 싶은 사람들은 연산이 끝날때 까지 기다려야 하고, 수시간을 들여서 연산한 결과라도 연산이 잘못되었으면 다시 로직을 수정해서 수시간 동안 다시 연산을 해야 한다. 비지니스 조직 입장에서는 지표 분석 결과를 얻는데, 수시간이 걸리니 의사 결정의 민첩성이 떨어지게 된다.
클라우드 기반의 분석 솔루션
근래에 이런 빅데이타 분석이 클라우드 컴퓨팅 기술과 만나면서 한번의 큰 변화를 겪게 되는데, 흔히들 빅데이타의 민주화라고 이야기 한다. 빅데이타 분석이 클라우드 컴퓨팅과 만나면서 겪은 큰 변화는 다음과 같다 .
클라우드 스케일의 연산
먼저 스케일이 달라집니다. 클라우드의 대용량 자원을 이용하여, 연산을 하기 때문에, 훨씬 더 빠른 연산을 저 비용에 할 수 있다.
예를 들어 구글의 빅쿼리의 경우에는 1000억개의 문자열(ROW)를 Regular expression을 이용하여 스트링 Like 검색을 하고 이를 group by 로 그룹핑하여 연산 하는 쿼리를 수행할때
“8600개의 CPU, 3600개의 디스크, 350GB의 네트워크 대역폭"
이 사용이 되고, 쿼리 수행 시간은 약 20~30초, 클라우드 사용 비용은 20$ (2만원) 정도가 소요 된다.
오픈 소스 기반으로 왠만한 규모로는 동시에 단일 연산으로 이렇게 수천개의 CPU를 같이 돌릴 수 있는 인프라를 사내에 가지고 있기도 힘들뿐 더러, 이만한 리소스를 20$라는 저렴한 비용에 사용하기란 거의 불가능에 가깝다.
이런 빠른 연산으로 인해서, 현업에서는 연산 결과를 기다리지 않고 바로바로 볼 수 있고, 비용 역시 저렴하기 때문에, 어느정도 자금력과 개발력이 있는 기업이 아니더라도 고성능의 빅데이타 분석 시스템 구현이 가능하게 된다.
NoOPS
다음 장점으로는 운영이 필요 없다는 것인데, 앞에서도 설명했듯이, 오픈 소스를 이용해서 빅데이타 분석 시스템을 직접 구축한 경우에는 시스템 인스톨과, 구성, 그리고 운영에 많은 시간이 소요 되는데, 클라우드 기반의 빅데이타 솔루션은 설정과 운영을 클라우드 서비스 제공자가 대행을 하기 때문에, 엔지니어링 팀은 별도의 설정과 유지보수 없이 본연의 역할인 데이타 분석에만 집중할 수 있게 된다. (아마 직접 하둡이나 스파크 클러스터를 운영해본 사람이라면 이 의미를 잘 이해하리라 본다.)
이렇게 클라우드가 빅데이타 영역에 도입되면서 이제는 빅데이타 분석이 뛰어난 엔지니어링 지식과 자금력이 없더라도 단시간내에 저비용으로 효율적인 데이타 분석이 가능하게 되었기 때문에, 이를 빅데이타의 민주화라고 부른다.
파이어베이스 애널러틱스
파이어베이스는 얼마전에 구글이 인수해서 클라우드 서비스 형태로 제공하고 있는 통합 모바일 개발 프레임웍이다. 웹은 지원하지 않고 모바일만 지원하는 형태의 프레임웍이며, 리얼타임 데이타 베이스, 광고 네트워크 통합, 푸쉬 서비스, 사용자 개인 인증 서비스등 여러가지 기능을 가지고 있는데, 그 중에서, 파이어베이스 애널러틱스는 모바일 빅데이타 분석에 최적화된 시스템이다.
빅쿼리와 파이어베이스의 조합
게임 체인저
파이어베이스는 모바일 데이타 분석에서 거의 게임 체인저라고 할만한 기술인데, 기존의 클라우드 기반의 모바일 데이타 분석 솔루션은 가장 큰 문제점이, 개발자가 정의한 로그 이벤트 (커스텀 로그)를 수집할 수 없다는 문제와 그리고 수집한 원본 데이타를 볼 수 없기 때문에, 원하는 지표를 마음대로 수집하고 분석하는 것이 불가능했다.
그런데 파이어베이스 애널러틱스는 이 두가지 기능을 지원하기 시작하였다.
커스텀 이벤트 정의를 통해서 개발자가 원하는 로그를 손쉽게 정의해서 수집이 가능하고, 또한 수집한 로그는 모두 구글의 빅데이타 저장 및 분석 플랫폼인 빅쿼리에 저장되고 바로 분석이 가능하다.
빅쿼리
파이어베이스 애널러틱스의 데이타는 빅쿼리에 저장이 되는데, 앞에서 예를 든것과 같이, 빅쿼리는 한번 연산에 수천개의 CPU와 디스크를 사용하여, 하둡이나 스파크에서 수시간이 걸리는 연산을 불과 수십초만에 처리가 가능하다.
빅쿼리의 또 다른 장점중의 하나는 이런 연산 속도 뿐만 아니라 RDBMS와는 다르게 JSON과 같이 트리형 (계층 구조를 가지는) 데이타형을 그대로 저장하고 쿼리가 가능하다는 것이다.
파이어베이스 애널러틱스는 뒤로는 빅쿼리 연동을 통해서 모든 원본 데이타의 수집과 분석을 지원하고 앞으로는 파이어베이스 에이전트를 모바일 디바이스에 탑재 하는 방식으로 최소한의 코드 개발로 모바일 앱으로 부터 모든 데이타를 수집할 수 있다. 파이어베이스 애널러틱스는 안드로이드와 iOS 플랫폼을 지원한다.
게임 프레임웍 지원
반가운 소식중의 하나는 파이어베이스 애널러틱스가 이제 유니티3D나, 언리얼(C++) 과 같은 게임 엔진을 지원한다. 현재 두 플랫폼에 대한 지원은 베타로 공개되어 있다.
기본적으로 gradle 빌드 스크립트에 파이어베이스 애널러틱스 모듈을 import 하고, FirebaseAnalytics 객체만 선언해주면 기본적인 사용자 로그 (앱 실행, 종료등), 일일 방문자, 동시 접속자, 접속 디바이스 종류, 사용자 연령과 성별들을 모두 수집해준다.
빌드 스크립트 수정 및 소스코드에 한줄의 코드만 추가해주면 된다.
다음으로, 각각의 이벤트를 추가하고자 한다면, 위와 같이 Bundle 객체를 정의해서, 넘기고자 하는 인자를 정의해주고 logEvent라는 메서드를 호출해주면 파이어베이스로 로그가 전달된다.
유니티 3D 예제 코드
유니티 3D에서 파이어베이스에 로그를 남기는 것도 다르지 않다.
다음 코드를 보자
Firebase.Analytics.Parameter[] param = {
new Firebase.Analytics.Parameter("sessionid", sessionid),
new Firebase.Analytics.Parameter("score", (string)ApplicationModel.score.ToString())
Parameter라는 배열로, 파이어베이스에 남길 로그의 인자들을 정의한후에, LogEvent 메서드를 이용하여 이벤트 명과, 앞에서 정의된 인자들 (Parameter)를 남겨주면 로그는 자동으로 파이어베이스로 전달된다.
파이어베이스 애널러틱스를 이용한 모바일 데이타 분석
그러면 파이어베이스를 이용하여 모바일 로그 분석을 어떻게 할 수 있는지 알아보자. 마침 유니티 3D가 얼마전 부터 베타로 지원이 되기 때문에, 간단한 게임을 이용한 로그 수집을 설명한다.
샘플 게임 설명
샘플에 사용한 게임은 간단한 RPG 형태의 게임으로 다음과 같이 구성된다.
시작 화면
시작화면에서는 로그 분석을 위해서, 사용자의 나이와 성별을 입력 받는다.
게임 화면
다음 게임이 시작되면, 화면을 터치하여 토끼 캐릭터를 이동 시키고, 돼지를 클릭하면 돼지를 공격한다.
돼지를 공격할때 마다 데미지는 돼지의 종류에 따라 일정 값 범위내에서 랜덤으로 판정되고, 생명 값이 남아있지 않으면 돼지가 죽게 된다.
맵내에 돼지는 7개가 유지되도록 되어 있으며, 돼지가 줄면, 돼지는 하늘에서 부터 떨어지게 되어 있다.
게임은 120초 동안 진행되며, 120초가 지나면 자동으로 종료된다.
종료 화면
게임이 종료되면 점수를 표시한다.
데이타 분석 지표 디자인
그러면 이 게임으로 어떻게 데이타를 분석할것인지에 대해서 고민해보자.
일일 접속 사용자나 사용자에 대한 사용 시간,횟수등은 파이어베이스 애널러틱스에서 기본적으로 수집이 되기 때문에, 조금 더 의미 있는 데이타를 수집해보도록 한다.
캐릭터 이동 히트맵
이 예제에서 다소 중점을 둔 부분중의 하나는 캐릭터 이동 히트맵이다.
게임에서 난이도 조정등에 사용할 수 있는 정보중의 하나가 NPC 캐릭터의 이동 동선과, 플레이어 캐릭터의 이동 동선이다. 주로 플레이어가 죽는 위치를 데드존 (Dead zone)이라고 하면, 이 데드존 위치를 찾아낼 수 있고, 이 데드존에서 플레이어와 NPC의 타입,레벨 등을 조사하여 난이도를 조정한다거나, 또는 AI(인공지능) 플레이어 캐릭터의 경우에는 이동 동선을 추적함으로써 맵 내에서 AI가 원하는 데로 잘 움직이는지를 추적해볼 수 있다.
아래는 데드존을 기반으로 캐릭터와 NPC의 레벨을 분석해놓은 예제이다.
<그림. 게임맵상에서 데드존의 플레이어와 NPC 캐릭터간의 레벨 분석 >
아래는 흥미로운 분석중의 한예인데, 게임맵에서, 각 위치별로 자주 발생하는 채팅 메세지를 표시한 내용이다.
<그림. 게임맵상에서 자주 사용되는 채팅 메세지 분석>
그림 출처 : http://www.cs.cornell.edu/courses/cs4152/2013sp/sessions/15-GameAnalytics.pdf
이런 시스템 역시 쉽게 개발이 가능한데, 파이어베이스 애널러틱스를 이용하여 채팅 로그를 수집한 후, 자연어 분석 API를 이용하면, 명사와 형용사등을 추출하여 자주 오가는 말들을 통계를 낼 수 있다.
다음으로 일반적인 분석 시스템에서 수집되지 않는 커스텀 로그 분석 시나리오중 사용자 나이별 점수대를 분석해본다.
게임실행에서 종료까지 실행한 사용자
마지막으로 유용하게 사용되는 퍼널 분석의 예로 게임을 시작해서 종료할때까지의 도달율을 측정해봤다.
게임을 인스톨하고 시작한다음, 캐릭터를 움직이고, 캐릭터를 이용하여 공격을하고, 2분동안 플레이해서 게임을 종료한 사용자의 비율을 분석해본다.
로그 메세지 디자인
그러면 이러한 게임 로그를 분석하기 위해서 수집할 로그 메세지는 어떤 형태가 될지 디자인을 해보자.
로그 이벤트는 아래와 같이 7가지로 정의한다.
START_SESSION,END_SESSION 은 게임을 시작과 끝날때 발생하는 이벤트이다.
NPC_CREATE,NPC_MOVE,NPC_DIE 는 NPC(돼지)를 생성하고 이동하고, 그리고 죽었을때 각각 발생하는 이벤트이다. 이동은 이벤트의 수가 많기 때문에, 10초 단위로 수집하였다.
PLAYER_MOVE,PLAYER_ATTACK 은 플레이어 캐릭터의 이동과 NPC를 공격하는 이벤트를 수집한다.
각 이벤트를 플레이하는 판과 연결하기 위해서 각 플레이는 고유의 sessionid가 생성되서 게임이 시작될때부터 끝날때 까지 모든 이벤트에 저장된다.
Event name
Param
Key
Value
Type
Note
START_SESSION
This event is triggered when player press “START” button after submitting player’s age & gender
sessionid
Unique session Id for this play
String
age
Player’s age
String
sex
Player’s gender
String
true : man
false : woman
PLAYER_MOVE
It record location of player in game map periodically (every 2sec)
sessionid
Pos_X
Pox_Z
PLAYER_ATTACK
This event is occurred when player attack NPC.
sessionid
Unique session Id for this play
npc_id
Attacked NPC ID
type
Type of NPC
pos_X
NPC location X
pos_Z
NPC location Y
damage
Damage that NPC get in this attack
life
Left life for this NPC
NPC_CREATE
When new NPC is created, this event is logged.
sessionid
Unique session Id for this play
npc_id
Attacked NPC ID
type
Type of NPC
pos_X
NPC location X
pos_Y
NPC location Y
NPC_MOVE
Every 2sec for each NPC, it records the location of NPC.
sessionid
Unique session Id for this play
npc_id
Attacked NPC ID
type
Type of NPC
pos_X
NPC location X
pos_Y
NPC location Y
NPC_DIE
It is triggered when NPC is dead by attack
sessionid
Unique session Id for this play
npc_id
Attacked NPC ID
type
Type of NPC
pos_X
NPC location X
pos_Y
NPC location Y
END_SCENE
It is triggered when game stage(session) is over
sessionid
Unique session Id for this play
score
Score for this play
이렇게 정의된 로그는 파이어베이스 애널러틱스에 의해서 빅쿼리로 자동으로 저장되게 된다.
실시간 디버깅
이런 로깅을 삽입하면, 로그가 제대로 저장이 되는지 확인이 필요한데, 파이어베이스 애널러틱스는 특성상 로그 이벤트가 1000개가 쌓이거나 또는 컨버전 이벤트가 발생하거나 또는 1시간 주기로 로그를 서버에 전송하기 때문에 바로 올라오는 로그 메세지를 확인할 수 없다.
그래서 이번에 새로 소개되니 기능이 “DEBUG VIEW”라는 기능인데, 이 특정 디바이스에 디버깅 옵션을 지정하면, 실시간으로 올라오는 로그를 확인할 수 있다.
로그는 모바일앱에서 업로드한 후 약 10~20초 후에, 화면에 반영된다.
대쉬 보드를 이용한 지표 분석
대쉬 보드는 파이어 베이스 애널러틱스에서 기본으로 제공되는 지표로 모바일 서비스에 공통적으로 필요한 지표들을 분석하여 웹으로 출력해준다.
DAU/WAU/MAU 분석
가장 기본적인 지표로는 월간,주간,일간 방문자 수로를 그래프로 출력해준다.
평균 플레이 시간 분석
다음은 평균 플레이 시간으로, 사용자가 하루에 평균 얼마나 앱을 사용하였는지, 동시 접속자수 (Session)과, 한번 접속했을때 얼마나 오래 앱을 사용 하였는지 (Session duration)등을 분석하여 그래프로 출력해준다.
국가별 접속 내역 분석
다음은 국가별 접속 내용으로, 글로벌 서비스에는 필수로 필요한 분석 내용이다.
사용자 데모그래픽 정보 분석
사용자에 대한 데모 그래픽 정보 즉 성별과, 나이를 분석해주는데, 앱에 별도로 사용자 로그인 기능이 없거나, 사용자 정보를 추적하는 기능이 없더라도, 파이어베이스 애널러틱스는 여러군데에서 수집한 로그를 기반으로 사용자의 성별과 나이를 분석해 준다.
특정 이벤트에 대한 분석
다음은 특정 이벤트에 대한 분석이 가능하다. 게임에서 사용자가 스테이지를 넘어가는 이벤트등 파이어베이스에 정의된 이벤트 이외에도 사용자가 정의한 이벤트에 대한 분석이 가능하다.
또한 이벤트가 발생한 사용자에 대한 데모 그래픽 정보 (연령,성별,국가)를 같이 분석해서 해당 이벤트가 어떤 사용자 층에서 발생하였는지를 분석해 준다.
예를 들어 게임의 보너스 스테이지를 많이 클리어한 사용자의 통계만을 볼 수 있고, 그 보너스 스테이지를 클리어한 사용자의 나이,성별, 국가 정보등을 볼 수 있다.
게임 플레이 완료율에 대한 퍼널 분석
다음은 앞에서 데이타 분석 모델을 정의할때 정의한 문제로 사용자가 게임을 시작해서 플레이를 끝낸 사용자 까지를 퍼널(깔때기) 분석을 적용한 예이다.
해당 시간에 총 93번의 게임이 플레이 되었으며, 캐릭터까지는 이동하였으나, 공격을 하지 않은 플레이는 3번, 그리고 끝까지 게임 플레이를 끝낸 사용자는 총 62번으로 측정되었다.
이외에도 상품 구매에 대한(인앱)에 대한 분석이나, 디바이스 종류, 앱 버전, 그리고 어느 광고 네트워크에서 사용자가 인입되었는지 등의 분석등 다양한 분석이 가능한데, 대쉬보드의 자세한 지표에 대해서는 http://bcho.tistory.com/1132 를 참고하기 바란다.
노트북을 이용한 커스텀 로그 분석
앞에서는 파이어베이스에서 제공되는 로그와 분석 방법에 대해서만 분석을 진행하였다. 이번에는 커스텀 로그와 원본(raw)데이타를 이용한 데이타 분석에 대해서 알아보자.
모든 원본 데이타는 앞에서도 언급했듯이 구글의 빅쿼리에 저장되기 때문에, SQL 쿼리를 이용하여 자유롭게 데이타 분석이 가능하고 그래프로도 표현이 가능하다.
별도의 개발이 없이 자유롭게 쿼리를 실행하고 그래프로 표현할 수 있는 도구로는 노트북이 있는데, 빅쿼리는 주피터 노트북과 제플린이 지원된다. 주피처 노트북 오픈소스를 구글 클라우드에 맞춘 버전은 Google Cloud Datalab이라는 것이 있는데, 여기서는 데이타랩을 이용하여 분석하였다.
캐릭터 이동 히트맵 분석
앞에서 NPC_MOVE와 PLAYER_ATTACK을 이용하여, NPC의 이동 동선과, PLAYER가 공격을 한 위치를 수집하였다.
이를 히트맵으로 그려보면 다음과 같다.
좌측은 NPC가 주로 이동하는 경로이고 우측은 플레이어가 NPC를 주로 공격한 위치로, 많이 간곳일 수록 진하게 칠해진다.
NPC 캐릭터는 전체 맵에 걸쳐서 이동을 하는 것을 볼 수 있고, 주로 우측 나무 근처를 많이 움직이는 것을 볼 수 있다. 오른쪽 사용자가 공격한 위치를 보면 주로 중앙에 모여 있기 때문에 우측 나무 근처로 움직인 NPC는 생존 확률이 높았을 것으로 생각해볼 수 있다.
그리고 NPC 이동 맵에서 중간중간에 진하게 보이는 점은 NPC 가 생성되는 위치이기 때문에, 이동이 많이 관측되었다.
연령별 플레이 점수 분석
다음으로 플레이어 연령별 점수대를 보면, 최고 점수는 30대가 기록하였고, 대략 4900점대인데 반해서, 전체적인 평균 점수는 40대가 높은 것을 볼 수 있다. (이 데이타는 연령별로 수집된 데이타의 양이 그리 많지 않기 때문에 정확하지는 않다. 어디까지나 분석 예제용으로만 이해하기 바란다.)
분석에 사용된 코드는 아래에 있다. 이 코드는 데모용이고 최적화가 되어있지 않기 때문에, 운영 환경에서는 반드시 최적화를 해서 사용하기 바란다.
참고로, 모든 데이타 분석은 주로 파이썬을 이용하였는데, 근래에 빅데이타 분석용 언어로 파이썬이 많이 사용되기 때문에, 파이썬을 공부해놓으면 좀 더 쉽게 데이타 분석이 가능하다. 또한 파이썬으로 데이타를 분석할때 많이 쓰이는 프레임웍으로는 팬다스 (pandas)와 넘파이 (numpy)가 있는데, 이 둘 역시 같이 익혀놓는것이 좋다.
파이어베이스 노티피케이션 서비스를 통한 이벤트 기반의 푸쉬 타게팅
파이어베이스 애널러틱스와 연계해서 유용하게 사용할 수 있는 기능은 파이어베이스 노티피케이션 이라는 서비스가 있다.
파이어 베이스 노티피케이션 서비스는 파이어베이스에서 제공되는 웹 콘솔을 이용하여 관리자가 모바일 서비스에 손쉽게 푸쉬 메세지를 보낼 수 있는 서비스이다.
푸쉬 타게팅을 위한 별도의 서버 시스템을 개발하지 않고도 마케팅이나 기획자등 비 개발인력이 타게팅된 푸쉬 메세지를 손쉽게 보낼 수 있게 디자인된 서비스인데, 특히 파이어 베이스 애널러틱스와 연계가 되면 세세한 타게팅이 가능하다.
이벤트 로그 기반의 타케팅
푸쉬 타겟을 정할때, 파이어베이스 애널러틱스에서 수집한 이벤트를 조건으로 해서 푸쉬를 타게팅할 수 있다.
예를 들어
게임 스테이지 3 이상을 클리어한 플레이어한 푸쉬를 보낸다.
NPC를 10,000개 이상 죽인 플레이어에게 푸쉬를 보낸다.
아이템을 100개이상 구매한 사용자에게 푸쉬를 보낸다.
와 같이 서비스에서 수집된 이벤트에 따라서 다양한 조건을 정의할 수 있다.
<그림. 파이어베이스 노티피케이션에서 특정 사용자 층을 타게팅 해서 보내는 화면 >
이런 타게팅은 파이어베이스 애널러틱스에서 Audience로 사용자 군을 정의한 후에, (로그 이벤트 조건이나 사용자 이벤트 조건 등), 이 조건에 타겟해서 푸쉬를 파이어베이스 노티피케이션 서비스에서 정의한다.
사용자 정보 기반의 타게팅
서비스의 로그 이벤트 정보뿐 아니라, 사용자에 대해서도 푸쉬 타게팅이 가능한데, 특정 성별이나 나이에 대해 푸쉬를 보내거나, 특정 단말을 사용하는 사용자, 특정 국가에 있는 사용자등 다양한 사용자 관련 정보로 푸쉬를 보낼 수 있다.
사용자 정보 역시 앞의 이벤트 로그 정보처럼 개발자가 커스텀 필드를 추가하여 사용자 정보를 로그에 수집할 수 있다.
스케쥴링
이런 타게팅 푸쉬는 바로 웹에서 보낼 수 도 있지만, 특정 시간에 맞춰서 미리 예약을 해놓는 것도 가능하다.
비용 정책 분석
파이어베이스 애널러틱스에서 원본 데이타를 수집 및 분석 하려면 빅쿼리를 연동해야 하는데, 빅쿼리 연동은 파이어베이스의 무료 플랜으로는 사용이 불가능하다. Blaze 플랜으로 업그레이드 해야 하는데, Blaze 플랜은 사용한 만큼 비용을 내는 정책으로 다른 서비스를 사용하지 않고, 파이어베이스 애널러틱스와 빅쿼리 연동만을 사용할 경우에는 파이어베이스에 추가로 과금되는 금액은 없다. (0원이다.)
단 빅쿼리에 대한 저장 가격과 쿼리 비용은 과금이 되는데, 빅쿼리 저장 가격은 GB당 월 0.02$ 이고, 90일동안 테이블의 데이타가 변하지 않으면 자동으로 0.01$로 50%가 할인된다.
스파크는 개발자가 비지니스 로직을 함수로 정의한 후에, 이 함수를 스파크 클러스의 노드들로 보내서 수행할 수 있다. 스파크가 지원하는 프로그래밍 언어에 따라서, 이 함수를 넘기는 방법이나 특성이 다른데, 여기서는 Python을 이용하는 방법에 대해서 설명한다. (스칼라는 아직 공부를 못해서)
파이썬으로 함수 넘기기
파이썬으로 함수를 넘기는 방법은 크게 3가지가 있다.
람다 표기법을 이용하는 방식
모듈 상의 탑레벨 함수(Top-level function)
파이썬 클래스 안에서 함수를 정의하여, 클래스 안에서 그 함수를 스파크로 넘기는 방식
각각의 방식에 대해서 살펴보도록 하자.
첫번째로 람다 표기법을 사용하는 방식이다. 람다 표기법이란, 함수를 정의하는데, 있어서 함수명이 없이 간략하게 함수의 기능만을 저장하는 표기법으로, 주로 간단한 결과를 구현할때, 코딩을 간결하게 (양이 적게) 표현하고자 하는데 사용한다.
다음은 필터 연산에서 함수를 람다 표기법으로 정의해서 넘기는 예제이다. “l” 이라는 RDD에 Apache 라는 문자열이 있는지 없는지를 행마다 체크하는 로직이다.
같은 로직을 함수를 정의해서 함수 자체로 넘길 수 가 있는데, 위의 람다 표현식으로 된 함수를 containsApache라는 함수로 정의하여 필터로 넘기는 예제이다.
마지막으로는 파이썬 클래스에서 클래스의 함수를 넘기는 방식이다.
다음은 MyClass 클래스를 정의한 다음. 클래스를 생성할때, filter에 사용할 문자열을 받은후, count라는 메서드에서, 그 문자열로 필터링을 한 후, 라인 수를 count하여 리턴하는 방법이다.
이 때 주의할 점은 self.query를 filter에 인자로 넘겼는데, 이 경우에 스파크로 넘어가는 것은 self.query 변수 내용 하나가 아니라, 이 객체 전체가 스파크로 넘어가게 된다. 동작상에는 문제가 없지만, 전체 객체가 스파크로 넘어가기 때문에 메모리 사용률이 많아지고, 전체 객체를 넘기는 과정 역시 인자만 넘기는 방식에 비해서 상대적으로 시간이 많이 걸리기 때문에 좋은 방법은 아니다.
이런 문제를 피하는 방법은 클래스내에서 무슨 값을 넘길때는 self.xxx식으로 스파크에 넘기는 것이 아니라, 그 값을 복사하여 넘기는 방법을 사용하면 된다. 예를 들어서 위의 예제의 경우에는 아래와 같이 변경하면 된다.
즉 스파크에 self.query를 넘기는 것이 아니라 이 값은 로컬 변수인 x에 x=self.query로 저장한 후, 스파크에는 이 x 값을 넘기게 되면, 실제 모든 객체가 스파크에 전달되지 않고, 이 로컬 변후 x 만 넘어가기 때문에 메모리가 과 사용되는 것을 예방할 수 있다.
http://www.lfd.uci.edu/~gohlke/pythonlibs/#numpy 에서 *.whl 파일을 다운로드 받은후
pip install numpy-1.9.2rc1+mkl-cp27-none-win_amd64.whl (64 비트 기준)
으로 설치 하면 된다.
설치후 확인을 위해서는 위와 같이 from numpy import * 를 한후에, random.rand(4,4)가 제대로 실행되는지 확인하자
참고
머신러닝이나 빅데이타 분석을 위해서는 NumPy 뿐만 아니라 matplot등 다양한 수학 모듈을 깔아야 하는데, 방화벽등이 있거나 하면 깔기가 매우 까다롭다. (의존성 관계도 복잡하고). 그래서 수학용 모듈을 모아 놓은 파이썬 인스톨패키지가 있다. http://www.scipy.org/install.html
Python 쪽에서는 Django등을 많이 사용하고 있지만, 설치도 쉽고, 가볍고 해서, 특정 목적이나 가벼운 테스트 웹 애플리케이션 개발등에는 충분히 활용이 가능하다.
(자바의 Jetty 와 같은 느낌?)
1. easy_installer에 설치
먼저 bottle을 설치하려면, installer부터 설치하는 것이 수월하다. python은 linux의 yum이나 rpm , 또는 Java의 maven과 유사하게 Pypi(Python Package Index - https://pypi.python.org/pypi) 라는 툴을 제공한다.
먼저 https://pypi.python.org/pypi/setuptools#windows 에서 ez_setup.py를 다운로드 받아서 실행한다
실행이 끝나면 ${Python 설치디렉토리}/Scripts/easy_install.exe 가 설치 된다.
2. bottle 설치
easy_install bottle 을 실행하면 bottle 라이브러리가 설치된다.
3. 간단한 애플리케이션 제작
bottle이 설치되었으면 간단한 애플리케이션을 만들어보자
아래 hello_world.py
importbottle
@bottle.route('/')
defhome_page():
return"hello world\n"
@bottle.route('/testpage')
deftest_page():
return"this is test page"
bottle.debug(True)
bottle.run(host='localhost',port=8080)
4. 실행
%python hello_world.py
다음으로 브라우져에서 http://localhost:8080/testpage 로 접근하면 다음과 같은 결과를 얻을 수 있다.
파이썬의 패키지는 디렉토리 구조를 그대로 사용함 (명시적으로 자바처럼 package라고 정의 안함)
- __init__.py : 해당 패키지가 import될때 실행되는 스크립트
- __all__ : __init__.py내에 __all__ = ['하위패키지명',..] 식으로 정의하는데, 이는 from {package) import * 를 할때, 리턴되는 모듈 명이다. 자바처럼 import * 하면 모두가 import되는게 아니라, 예를 들어 윈도우즈의 경우 module.py 파일과 Module.py 파일을 같은 파일로 취급(대소문자를 가리지 않기 때문에), 명시적으로 import * 시 패키지내의 어떤 모듈을 -import 할지를 정해줘야 한다.
- import : import는 import하고자 하는 module 명을 명시한다.
- from : 어느 패키지에서 import할지를 지정 예) from package import module 또는 import package.module
자바에 비해서 특이한건 __init__.py를 통해서 해당 패키지 로딩시에, 특정 스크립트를 수행할 수 있다는 것.. 응용할 분야가 많을듯.
댓글을 달아 주세요
비밀댓글입니다
좋은 글 너무 감사합니다
비밀댓글입니다