한달간 난 무엇을 했는가

개인적인 사정으로 한달간(2017.02.19~2018.03.18) 휴직을 했다.

1주일이 지날때마다 그 주에 뭘 했는지 기록을 해봤다.

많은 일이 있었기도 했고 없었기도 했는데, 한달간 무엇을 했는지 회고해보자.

1주차

먹고자고놀고먹고자고놀고!

🍕😴😎

운동을 시작했다.

아침에 운동을 나가기 시작했다.

얼마나 오래갈지 의문이지만 일단 해보자.

한달 후에 다시 출근을 하더라도 출근 전에 운동을 하는 습관을 길러보자.

파마를 했다.

큰 사건은 아니지만 뽀글뽀글하게 파마를 했다.
쉬는 동안 계속 길러볼 생각이다. 어떻게 내 머리가 변하는지 관찰해보자.
뭔가 패션에 새로운 시도를 더 해보고 싶다.(가령 타투라던가, 타투라던가, 타투라던가…)

책을 읽었다.

  • 햄릿
  • 비트코인 블록체인

영화를 봤다.

  • 블랙팬서
    와칸다 포에버!!
  • 배드맘스
    믿고보는 Netflix Original
  • 알파고 다큐
    갓세돌…

2주차

경주 여행

여자친구와 경주 여행을 갔다왔다.
처음으로 운전을 제대로 해봤는데 내 스스로 뭔가를 해낸것 같아 자존감이 상승하는 느낌이다.

다른 경험들도 다 좋았지만 스스로 운전을 해서 찾아간 바다가 제일 좋았다.
자주 여행에 갈 수 있으면 참 좋겠당.

운동

운동은 가지 않았다.
ㅠㅠ 벌써!

지브리 전시회

독서모임 멤버중 한분이 티켓을 나눠줘서 가게 되었다.
전시회 마지막 날임에도 불구하고 사람이 으마으마하게 많았다.(마지막 날이라서 더 많은것인가…?)

3주차

AWS summit 2018 발표 준비

잘 쉬고 있던 어느날 이런 메일을 받았다.

띠용!

오잉 내가 왜??

라는 생각이 처음 들었고

아 블로그! Zappa 글 말인가? 어머나…

라는 생각과 함께 걱정이 앞섰다.

하지만 메일 하단에 본 초대로 인해 발표 확정이 된 것은 아니라는 말에
뭐 내가 되겠어? 라는 생각으로 신청을 해버렸고

오모나...

뜨아아아아아아!!!!
발표는 대학교 때도 못했고 하는 것을 좋아하지도 않았던 내가 발표라니…

준비를 빡세게 해야겠다.

독서모임

4주만에 가는 독서모임이다

이번 책은 얆은 시집 ‘지금 알고 있는 걸 그때도 알았더라면’ 과 셰익스피어의 ‘오셀로’ 2권이었다.
독서모임 전에 회사에 잠깐 들렀다가 진영님과 언제나처럼 코코이찌방야에서 카레를 먹고 솔라스로 향했다.

언제나처럼 독서모임에서 많은 이야기를 나누고 왔다.

지금 알고 있는 걸 그때도 알수는 없다.
다만 지금 알고 있는 걸 기반으로 현재에 최선을 다하자

회사

위에서 말한 것처럼 독서모임 가기 전에 잠깐 회사에 놀러갔다.
휴직상태에서 회사에 놀러가는 것은 색다른 경험이었다.
가자마자 모두가 반겨줬고, 빨리 돌아와서 일하라는 농담도 들었다.(전혀 부담되지는 않았다.)
원경님과 헌재님께 발표에 관해서 조언도 듣고, 헌재님한테 청첩장도 받았다 헤헤

언넝 회사에 가고 싶기도하네.

운동

요가를 갔는데 넘나 좋았다.
헬스장은 역시 꾸준히 가는 것이 참 힘든 것 같다.

4주차

휴직의 마지막 주라 그런가 많이 놀러다녔다.
사실 더 놀고 싶었지만 갑작스럽게 다가온 발표덕분에 마냥 놀지는 못한것이 아쉽다 ㅠ

일본라면!

평소에 가보고 싶었던 일본라면 집을 가봤다.
멘야하나비, 라멘트럭, 하카다분코
평일 점심에 먹으러가니 별로 안기다리고 먹을수 있어서 매우좋았다. 헤헤
라멘트럭과 하카다분코에서는 스티커도 얻어왔다. 노트북에 붙여야지

발표 준비

매;ㅈ댜롲매댜;곱;ㅐㅈ댜ㅡㄹ;ㅁㄴ야ㅓ채먄;ㅇ러
망할것같다…

운동

거의 안갔다고 한다…

그래서 한달동안

정말정말 잘 놀고 잘 쉬고 왔다.

사실 휴직이라는 경험을 쉽게 할 수 있을까 생각을 했다.
그것도 단 한달동안.

사실 말이 한달 휴직이지, 한달동안 휴가를 준것이나 마찬가지 아닌가!(물론 무급휴가이긴하지만)

난 정말 좋은 회사에 다니고 있다는 생각을 쉬면서 많이 했다.

쉬고 싶다고 말을 꺼내는 것조차 어려운 분위기의 회사가 있을텐데, 지금 다니는 회사는 그런 면에서는 정말 좋은 분위기가 조성되어 있는 회사인것 같다. 나같은 소심이도 휴직한다고 말을 하다니… 정말정말 직원을 더 많이 생각해주는 회사가 아닌가 싶다. 그렇다고 해서 내가 말을 꺼내기 쉬웠다는 것은 아니지만

작년 이맘때 구직할 시기에 속으로 오래 다니고 싶은 회사에 가고싶다고 생각했는데 정말 오래 다니고 싶은 회사에 와버렸다.

이제 열심히 해야지 일.

급하게 휴직이 결정되서 원래 하기로 했던 태스크들은 다른 분들에게 분배가 되었는데 정말 미안했다.
그래도 다시 출근하고 그 태스크를 가져가서 요즘 하고 있는데 아직 휴직 버프가 남아서 그런가 일이 재밌다.

그리고 지나고보니 정말 공부는 별로 안한 것 같다.
이제 공부도 열심히 합시다.
상반기 동안 Go언어 공부를 해보자. Let’s Go!

운동

운동 좀 열심히 할 껄 후회가 된다.
역시 난 운동과 거리가 먼 사람인것인가…

아직 헬스 기간이 남았는데 남은 기간은 좀 잘 다녀보자!

여자친구

쉬는 동안 나를 많이 챙겨주고 같이 놀아줬다.

너무너무 고마운 사람이다.


사실 이 밖에도 한 일은 많지만 넘나넘나 개인적인 일이기에 생략! 😎

2017년 회고

2017년도 훌쩍 지나가버렸다.

2018년 1월도 어느새 훌쩍 지나가버렸다.

지난 2017년을 되돌아보는 시간을 가져보려고 했지만 어쩌다보니 벌써 2월이 되어버려 급하게 회고를 하게 되었다.

2017년에 해보고 싶었던 것들

  • 취업(좋은 회사로)
    ab180으로 취업 성공!! 좋은 회사로 취업하자는 목표까지 성공한 것 같다.
  • 이사하기(좋은 집으로)
    이사도 성공은 했다. 하지만 점점 월세라는 압박이 나를 죄여오는건 기분탓인가…
  • 책 많이 읽기
    생각보다 많이 읽은 것 같다.
    그리고 연말부터 독서모임을 시작했는데 정말 잘한 것 같다.
  • 취미 만들기(컴퓨터 말고)
    상반기에는 자전거를 취미로 잘 타고다녔다.
    그리고 하반기에는 글쎄… 굳이 만들자면 독서…?
  • 건강 관리하기
    완전 실패다.
    스트레스를 줄이고 싶다.
    건강이 최고다.
  • 블로그 활성화하기
    2017년 동안 17개 글을 포스팅했다.
    사실 쓰다가 중간에 멈춘 글들도 꽤 있지만 그래도 TIL에 많이 했으니 나름 성공이 아닐까…

2017년 하반기 목표점검

  • vim 익숙해지기
    이제 어떤 에디터보다 vim이 더 편해졌다.
  • 블로그 한달에 2회 포스팅하기
    대 실패다. 헤헤
  • 책 10권 읽기
    독서모임을 하면서 책을 많이 읽게되었다.
    앞으로도 꾸준히 읽고 싶다.
  • 운동 등록하기
    잠깐이지만 3달 정도 스피닝을 했었다. 너무너무 재밌었지만 효과는 미비했다…
    헬스를 해서 꾸준히 나가는 습관을 들여볼까 한다.
  • B 와 해커톤 참가하기
    장고걸스에서 주관하는 해커톤에 놀러갔다. 반쯤 성공이…?
  • B 와 여행가기
    8월에 일본 오사카에 여행갔었다.
    너무너무 더웠지만 너무너무 좋았다.
    또 여행가고 싶다.
  • 직장에서 인정받는 팀원되기
    이건 글쎄… 잘 모르겠다.

2017년의 책

  • 폭정 : 20세기의 스무가지 교훈 - Timothy Snyder
  • 82년생 김지영 - 조남주
  • 나미야 잡화점의 기적 - 히가시노 게이고
  • 우리에겐 언어가 필요하다 - 이민경
  • 잠 1, 2 - 베르나르 베르베르
  • 언어의 온도 - 이기주
  • 신경끊기의 기술
  • 유시민의 글쓰기 특강 - 유시민
  • 김약국의 딸들 - 박경리
  • 나는 정말 너를 사랑하는 걸까 - 김혜림
  • 과학콘서트 - 정재승
  • 무진기행 - 김승옥
  • 전문가를위한파이썬

하반기부터 책을 많이 읽어보기로 결심했었다.

저 책들이 모두 하반기에 읽었던 책이다.

그리고 11월부터 독서모임을 해서 요즘엔 거의 일주일에 한권 꼴로 읽고 있는것 같다.

책을 무조건 많이 읽기보다는 생각을 많이 하게 되었다.
하지만 아직도 생각으로만 남기지 기록으로 남기지는 못했는데 이제 한번 해보면 좋을 것같다.
책을 읽으면서 들었던 생각을 어딘가에 기록해야겠다.

2017년의 구매

자전거
리디북스 페이퍼 프로
여러가지 책들

또 뭐가 있을까…

이사한 집의 월세, 오사카 여행의 항공권, 3달 동안 열심히 했던 스피닝…?

무엇이 있을지는 모르겠지만 먹고 마시는데에 제일 많이 쓴것 같다.

하지만 올해는 돈좀 모아야겠다…

올해는…

  1. 언제나 늘 주변에 말하고 다니지만 건강이 최고다.
    하지만 정작 내 건강에는 왜이리 무심한지 모르겠다.
    내 건강을 위해 더 열심히 살아야 겠다.

  2. 책은 많은 생각을 하게 하고 글은 많은 생각을 정리하게 한다.
    책을 많이 읽고 글을 많이 쓰고싶다.

  3. 요즘 다시 느끼지만 기초가 많이 부족하다고 느낀다.
    기초를 다잡아야겠다.
    절대 방심하지 말자.

Sphinx로 TIL 문서 페이지 만들기

Today I Learned 을 언제부터인가 쓰고 있었는데 Markdown으로 작성하고 Git으로 관리하니 매우 편했다.

하지만 다시 보고 싶을 때 검색이 용이하지 않아서 뭔가 검색할 수 있는 페이지를 만들면 좋겠다 싶어서 이것 저것 찾아보았다.

Markdown을 정적 웹 페이지로 만들어주는 툴은 많았지만(심지어 이 블로그도 Markdown 기반…) 뭔가 안써본걸 써보고 싶었다.

그렇게 알아보던 중 Python 문서화 툴인 Sphinx를 사용할 수 있지 않을까라는 막연한 생각에 찾아봤는데 역시나 가능했다.

Sphinx???

SphinxPython Documentation Generator 이다.
Python Code의 docstring을 가져와 자동으로 문서화해주는 라이브러리인데 설정도 아주 손쉽게 할 수 있어서 널리 사용되고 있다.

또한 reStructuredText 문서도 테마에 맞는 HTML로 만들어주고 검색페이지도 만들어 줘서 장점이 한둘이 아니다.

그리고 Read The Docs를 사용하면 무료로 호스팅도 가능하다.

자, 그럼 셋팅을 해보자

일단 TIL 디렉토리는 아래처럼 되어있다.

1
2
3
4
5
6
7
8
.
├── README.md
├── mysql
│   └── mysql.md
├── python
│   └── python.md
└── vim
└── vim.md

그리고 Sphinx를 설치하고 sphinx-quickstart를 사용해 기본 셋팅을 하자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
$ sphinx-quickstart
> Root path for the documentation [.]:
> Separate source and build directories (y/n) [n]:
> Name prefix for templates and static dir [_]:
> Project name: TIL
> Author name(s): Yunseop Song
> Project version []: 1.0
> Project release [1.0]:
> Project language [en]:
> Source file suffix [.rst]:
> Name of your master document (without suffix) [index]:
> Do you want to use the epub builder (y/n) [n]:
> autodoc: automatically insert docstrings from modules (y/n) [n]:
> doctest: automatically test code snippets in doctest blocks (y/n) [n]:
> intersphinx: link between Sphinx documentation of different projects (y/n) [n]:
> todo: write "todo" entries that can be shown or hidden on build (y/n) [n]:
> coverage: checks for documentation coverage (y/n) [n]:
> imgmath: include math, rendered as PNG or SVG images (y/n) [n]:
> mathjax: include math, rendered in the browser by MathJax (y/n) [n]:
> ifconfig: conditional inclusion of content based on config values (y/n) [n]:
> viewcode: include links to the source code of documented Python objects (y/n) [n]:
> githubpages: create .nojekyll file to publish the document on GitHub pages (y/n) [n]:
> Create Makefile? (y/n) [y]:
> Create Windows command file? (y/n) [y]: n

Creating file ./conf.py.
Creating file ./index.rst.
Creating file ./Makefile.

Finished: An initial directory structure has been created.

You should now populate your master file ./index.rst and create other documentation
source files. Use the Makefile to build the docs, like so:
make builder
where "builder" is one of the supported builders, e.g. html, latex or linkcheck.

그럼 여러 파일이 생겨서 다음과 같이 바뀐다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
.
├── Makefile
├── README.md
├── _build
├── _static
├── _templates
├── conf.py
├── index.rst
├── mysql
│   └── mysql.md
├── python
│   └── python.md
└── vim
└── vim.md

이 상태에서 make html을 사용하면 _build 디렉토리에 문서 페이지가 생성된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
$ make html
Running Sphinx v1.6.5
making output directory...
loading pickled environment... not yet created
building [mo]: targets for 0 po files that are out of date
building [html]: targets for 1 source files that are out of date
updating environment: 1 added, 0 changed, 0 removed
reading sources... [100%] index
looking for now-outdated files... none found
pickling environment... done
checking consistency... done
preparing documents... done
writing output... [100%] index
generating indices... genindex
writing additional pages... search
copying static files... done
copying extra files... done
dumping search index in English (code: en) ... done
dumping object inventory... done
build succeeded.

Build finished. The HTML pages are in _build/html.

그리고 _build/html/index.html을 열면 다음처럼 깔끔한 페이지를 볼 수 있다.

하지만 이 상태라면 마크다운 문서는 보여지지 않는다.
Sphinx에서 마크다운을 사용하려면 문서에 나온대로 recommonmark라는 패키지를 사용해야한다.

일단 recommonmark를 설치하자.

1
$ pip install recommonmark

그리고 conf.py 파일을 수정하자.

1
2
3
4
5
6
7
from recommonmark.parser import CommonMarkParser

source_parsers = {
'.md': CommonMarkParser,
}

source_suffix = ['.rst', '.md']

그리고 Sphinx에서 바라보는 master_docindex.rsttoctree를 추가해야한다.
index.rsttoctree를 추가하는 이유는 Markdown에서 지원을 하지 않기 때문에 약간의 편법…(사실 어떻게 하는지 잘 모르겠다.)

1
2
3
4
5
6
7
8
.. toctree::
:caption: TOC:
:glob:
:titlesonly:

mysql/*
python/*
vim/*

이렇게 추가를 하고 다시 make html을 하면 TOC가 제대로 추가된 것을 확인할 수 있다.

배포를 해봅시다.

Sphinx를 사용해 TIL 페이지는 완성되었다.

이제 배포만 남았는데 어디로 어떻게 배포할 지를 결정해야 했는데 구글링을 해보던 중 아주아주 좋은 것을 발견했다.

travis-sphinx라는 것인데 내 고민을 한방에 해결해주었다.

travis-sphinx를 사용하면 나는 문서를 커밋해서 Push하면 Travis에서 Sphinx로 빌드해서 gh-pages 브랜치로 배포를 해줘서 Github 호스팅을 사용할 수 있다.

travis-sphinx 설치

우선 pip를 사용해 travis-sphinx를 설치합시다.

1
$ pip install travis-sphinx

.travis.yml

.travis.yml을 추가한다.

1
2
3
4
5
6
7
8
9
10
language: python - "2.7"

install:
- sudo pip install -U -r requirements.txt

script:
- travis-sphinx build -s . --nowarn

after_success:
- travis-sphinx deploy

Github Access Token 추가

Access Token 페이지로 가서 Generate new token을 눌러 Travis에서 사용할 토큰을 생성하자.
권한은 public_repo만 줬다.

생성된 토큰을 복사해 두고 Travis에 설정을 합시다.

Travis Environment Variables 추가

Travis에 설정 페이지로 가서 Environment VariablesGH_TOKEN 이름으로 토큰 값을 추가한다.

배포!

이제 master로 푸시하면 Travis에서 Sphinx로 빌드한 html 파일들을 gh-pages 브랜치로 푸시하게 된다.

이렇게 빌드 내역도 볼 수 있드아

그리고 테마는 Readthedocs를 사용해서 다음과 같이 TIL 페이지를 만들었다.

그렇지만

Sphinx에서 Markdown을 사용할 때 Github Flavor Markdown에서는 지원하는 Table을 지원하지 않는다.

eval_rst라는 기능을 사용해서 rst 문법으로 Table을 사용할 수 있겠지만 아직 그냥 냅뒀다. 아직 답을 못찾은 걸 수도 있지않을까 해서…

그래도

이 페이지를 만들고 더 자주 TIL을 쓰게 되는 것 같아 잘 해둔 것 같다.

서버리스 마이크로서비스(Serverless Microservice) with Zappa -2-

이전의 포스팅Zappa와 함께하는 Serverless Microservice - 희망편이었다면

이번의 포스팅은 Zappa와 함께하는 Serverless Microservice - 파멸편이라고 할 수 있다.

Zappa를 도입하면서 삽질했던 것들을 적어보려한다.

삽질 1. Package

Lambda에서는 순수 Python으로 작성된 모듈만 사용할 수 있다. 별도의 컴파일 과정이 불가능하기 때문이다.

그래서 MySQL-Python 모듈도 쓰지못하는 문제가 있었다.

이럴 때는 Lambda가 돌아가는 환경과 제일 비슷한 Amazon Linux에서 패키지를 빌드해서 사용하는 방법과

같은 기능을 하는 다른 모듈로 대체하는 방법(MySQL-Python -> pymysql)이 있다.

하지만 Zappa에서는 미리 컴파일된 패키지를 제공해서 이를 가능하게 해준다. 모든 패키지는 아니고 사람들이 자주 쓰는 일부 지원하는 패키지가 있다.

찾아보니 docker-lambda라는 프로젝트도 있어서 활용할 수 있을 것 같다. Amazon Linux의 도커 이미지로 도커 컨테이너 안에서 Lambda에 사용할 패키지를 구성해서 테스트해볼 수 있다고 한다.

삽질 2. VPC 설정

배포는 성공했다. 하지만 여전히 500 Server Error 만 뱉어대고 있다.

로그를 살펴보니 DB에 접근을 하지 못하고 있었다.

지금 사용하고 있는 DB는 AWS RDS를 VPC안에서 사용하고 있기 때문에 Lambda에서 접근하지 못했던 것이다.

따라서 Lambda에서도 VPC를 사용하면 문제해결이었다. DB에서 사용하고 있는 VPC의 Subnet과 적절한 Securety Group을 zappa_settings.json 파일에 다음과 같이 설정을 추가하자.

1
2
3
4
5
6
{
"vpc_config": {
"SubnetIds": [ "subnet-12345678" ],
"SecurityGroupIds": [ "sg-12345678" ]
}
}

이제 DB에도 잘 연결되고 만사형통인 줄 알았지만 그게 아니었다.

삽질 3. Internet Gateway 설정

보통의 기능은 정상적으로 동작하지만 외부 망으로 요청을 보내면 연결을 하지 못해서 에러가 났다.

구글링을 해보니 VPC를 사용하는 Lambda는 Public Internet에 접속하지 못한다고 한다. 하지만 역시 방법이 있었다.

해결과정

1. VPC 설정

VPC를 하나 생성하자. 이미 있다면 그것을 사용하면 된다.
CIDR Block은 충분히 크게 잡는 것이 좋다.(ex. 192.168.0.0/16)

2. Subnet 설정

2개의 Subnet이 필요하다. CIDR Block이 겹치지 않게 설정하자.
하나는 Public Subnet 으로, 다른 하나는 Private Subnet 으로 사용할 것이다.

3. Internet Geteway 설정

1번에서 생성(사용)한 VPC를 attach한 Internet Gateway를 생성한다.

4. NAT Gateway 설정

2번에서 생성한 Public subnet 을 선택하고 생성함(Elastic IP 필요)

5. Route Table 설정

1번에서 생성(사용)한 VPC를 사용하는 2개의 Route Table이 필요하다.
이 역시 Public Route Table, Private Route Table 이다.

  • Public Route Table 의 Routes 탭에서 Destination: 0.0.0.0/0, Target을 3번에서 생성한 Internet Gateway로 설정하고, Public VPC를 연결한다.
  • Private Route Table 의 Routes 탭에서 Destination: 0.0.0.0/0, Target을 4번에서 생성한 NAT Gateway로 설정하고, Private VPC를 연결한다.

여기까지하면 AWS에서 설정은 완료된다.

6. zappa_settings.json 파일을 수정한다. SubnetIdsPrivate SubnetSubnet Id를 넣는다.
1
2
3
4
5
6
{
"vpc_config": {
"SubnetIds": [ "subnet-privateSubnetId" ],
"SecurityGroupIds": [ "sg-12345678" ]
}
}

설정이 다 되었다면 zappa update로 다시 배포를 하면 된다.

삽질 4. 잔잔한 버그들!

아주 간헐적으로 배포를 하면 "TypeError: 'NoneType' object is not callable" 이런 에러를 뱉으면서 에러를 내뿜었다.

zappa tail로 로그를 확인해보니 ModuleNotFoundError: No module named 'numpy' Import 에러가!!

로컬에서 잘 동작했고 virtualenv에 패키지가 설치되어 있는지 확인했는데도 뭐가 문제인지 잘 몰랐다.

그래서 혹시 나와 같은 이슈가 있을까 싶어서 찾아봤더니 이런 이슈가 등록되어 있었다.

나와 같은 고민의 냄새가 난다...

평소같았으면 그저 누군가가 해결해주기를 기다렸겠지만 뭔가 파보고 싶었다.

조금 파보니 Zappa가 패키징을 할 때 로컬에서 .whl 파일을 캐싱해서 쓰는데, 나중에 다시 쓰려할 때 파일이 손상되어 있다면 exception이 발생하는 버그를 발견했다.

그래서 버그를 잡고 구글 번역기의 힘을 빌려 아래처럼 코멘트를 달았다.

Thanks to Google Translate! 👍

그리고 조금후에 PR을 달라는 답변이와서 그렇게 난 Zappa의 contributor가 될 수 있었다.(막 엄청 대단한 일은 아니지만 처음이라…)

그렇게 내가 기여한 부분이 포함되어 새 버젼이 릴리즈 되어서 사용해보는데 이번엔 다른 버그를 발견했다.

그래서 바로 다시 PR을 보냈다.(뭐든 처음이 어렵지 두번째는 아니다.)

그러다가 Zappa 슬랙을 눈팅하던 중 나처럼 버그를 발견한 사람이 나왔다.

버그 발견!

이 떄다 싶어 바로 리액션을 줬다.

내가 고쳐줄게!

그렇게 머지가 되서 핫픽스로 릴리즈 되었다. Change Log에 내 이름이!

이 맛에 오픈소스하는건가...

삽질기라고 시작은 했지만

사실 꽤나 재미있었던 과정이었다.

이번 삽질로 AWS 기반의 네트워크 환경에 대해서 좀 더 알게되었고, 그동안 오픈소스에 관심은 많았지만 어떻게 시작을 해야할지 몰랐었는데 이렇게 좋은 오픈소스 프로젝트에 기여도 해볼 수 있어서

뭔가 삽질기보단 성장기라고 해야 더 적절할 것 같다.

앞으로 더 성장(삽질)해야겠다.

서버리스 마이크로서비스(Serverless Microservice) with Zappa -1-

내가 입사할 때 까지만 해도 회사의 백엔드는 Monolithic Architecture로 하나의 거대한 백엔드 시스템에서 여러가지 기능을 담당하고 있었다.

그리고 몇가지 이유로 이제 Monolithic Architecture를 고집할 수 없겠다 싶어 점진적으로 Microservice Architecture화 하기로 결정했다.

1차적으로 백엔드의 특정 기능을 담당하는 API 서버를 분리하기로 결정했는데 이번 기회에 요즘 핫한 Serverless Architecture를 시도해보기로 했다.

AWS의 Lambda, Azure의 Functions 등 여러가지 서버리스 아키텍쳐를 위한 제품들이 나오면서 서버리스 아키텍쳐(Serverless Architecture)가 뜨고 있다.

아니, 이미 꽤나 인기있는 아키텍쳐로 자리잡은 것 같다.

언젠가 서버리스 아키텍쳐를 한번 사용해보고 싶었는데 마침 기회가 왔다.

Microservice와 Serverless

개인적으로 이 둘의 궁합은 매우 잘 맞는다고 생각한다.

마이크로서비스(Microservice)는 하나의 거대한 서비스를 백엔드 시스템으로 사용하는 것이 아닌 여러 개의 작은 모듈처럼 구축한 서비스를 백엔드 시스템으로 연결하여 사용하는 것이다.

각 서비스는 프로그래밍 언어, 프레임 워크 등을 독립적으로 선택할 수 있고, 다른 서비스들과 독립적으로 배포가 될 수 있어서 하나의 서비스로 사용할 수 있어야 한다.

이는 서비스들이 해당 서비스에 특화된 프로그래밍 언어, 프레임워크, 배포환경 등을 선택할 수 있다 는 장점을 가져온다.

또한 기존 다른 서비스들에 의존성이 없기 떄문에 서비스를 배포할 때 고려해야할 것들을 줄일 수 있다.

서버리스(Serverless)는 말 그대로 서버가 없는 환경을 의미한다.

클라우드 서비스가 발전하면서 물리적인 하드웨어 서버가 클라우드 환경의 가상머신으로 대체 된 것처럼, 여러 API들을 수행하는 백엔드 시스템이 각 API들을 수행하는 하나의 코드만을 따로 배포할 수 있게 되었다.

개발자는 그저 비즈니스 로직에 맞는 코드만 작성하면 되고 이를 배포하면 된다. 다른 인프라나 데이터베이스 등의 부가적인 환경에 대해서 신경쓰지 않아도 된다는 것을 의미한다.

Microservice와 Serverless가 공통적으로 추구하는 방향은 비즈니스 로직에 집중하는 것이다.

Microservice를 사용해 서비스를 구축하고 이를 Serverless 환경으로 배포한다면 개발자는 다른 것에는 신경쓰지 않고 오로지 비즈니스 로직을 충실히 수행하는 서비스를 구축하고 배포하면 된다.

자, 그럼 서버리스의 세계로 가봅시다.

회사에서 AWS를 사용하고 있기 때문에 AWS Lambda의 선택은 당연했지만, Lambda를 어떻게 쓰는가에 대한 선택지는 매우 다양했다.

Lambda에서 실행할 코드를 작성해 AWS 콘솔에서 업로드하고 API Gateway도 직접 설정하는 방법도 있지만,

요즘에는 서버리스 프레임 워크도 많이 나와서 매우 쉽게 서버리스 아키텍쳐를 구축할 수 있다.

또한 서버리스를 위한 프레임 워크도 매우 다양한데(Serverless, Apex, Chalice, Zappa 등) CTO님의 제안으로 Zappa라는 프레임 워크를 사용하기로 했다.

Zappa는

AWS Lambda & API Gateway에 Python WSGI Application을 배포해 서버리스 아키텍쳐를 구성해주는 프레임 워크다.

지금까지 사용하며 겪은 바로 Zappa의 (매우 주관적인)장점은 다음과 같다.

  • Python WSGI Application을 배포하기 떄문에 코드의 변경없이 Django, Flask와 같이 WSGI Application을 그대로 배포할 수 있다.(내 생각에 이게 가장 큰 장점이 아닐까 싶다.)
  • 서버리스로 가기 위한 최소한의 셋팅을 다 알아서 해준다. 프로젝트를 압축하여 Lambda에 배포하고 API Gateway에서 Lambda를 사용할 수 있게 알아서 설정해준다. 또한 몇가지 설정만 추가한다면 다른 AWS의 서비스도 사용가능하다.
  • API Gateway의 Stage를 구성하기가 매우 쉽다. 그냥 설정파일에 stage용 설정을 추가하기만 하면 끝이다. 도메인까지 설정해서 쓰면 요긴하기 쓸 수 있다.

하지만 뭐든 그렇듯 물론 장점만 있지는 않다. 내가 생각하는 Zappa의 단점은

  • 모니터링이 힘들다. New Relic을 붙여서 사용하려고 했더니 뭔가 로그가 불규칙적으로 들어온다. 문제가 뭔지 잘 모르겠다.(해결방법을 아시는 분 있다면 공유좀…)
  • 그래서 AWS X-Ray를 쓰려했더니 Node.js, Java, .Net만 지원하다고 한다. 그래서 찾아보니 xrayvision이라는 프로젝트가 있어서 사용 중이다. 하지만 X-Ray가 모니터링 하기에 뭔가 부족한 느낌의 서비스인 것 같다.
  • 아직 성숙한 프로젝트가 아니다. 그렇다고 막 버그 투성이인 프로젝트는 아니다. 그럼에도 단점에 적은 이유는 Zappa로 배포하고 테스트를 진행하던 중 뭔가 안되는 부분이 있었는데, 알고보니 아직 지원을 안하는 것이었다. 하지만 다행히(?) 내가 삽질하던 그즈음에 누군가 PR를 보냈고 머지 되어 지금은 잘 사용하고 있다. 이런것을 보면 오히려 좋은 오픈소스 프로젝트에 기여할 기회가 많다 고 생각할 수도 있다.

자, 그럼 Zappa를 써봅시다.

Zappa Github Page에 가서 보면 알겠지만 매우 간단하다.

3줄로 요약하면

1
2
3
(env) $ pip install zappa
(env) $ zappa init
(env) $ zappa deploy

3줄의 명령어로 Python WSGI Application을 AWS Lambda & API Gateway에 배포할 수 있다.

시작하기 전에

Zappavirtualenv 안에 설치 되어야한다. Zappa가 배포할 때 virtualenv안에 있는 패키지들을 가져와서 압축하기 때문이다.

Zappapip를 사용해서 설치하면 된다.

1
(env) $ pip install zappa

Zappa를 사용하기 위해 설정파일을 만들어야하는데 zappa init 이라는 명령으로 사용하면 된다.

그럼 다음과 같이 몇가지 입력을 받고 설정파일을 만들어주는데 입력은 그냥 디폴트 값으로 넣어도 무관하다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
(env) $ zappa init

███████╗ █████╗ ██████╗ ██████╗ █████╗
╚══███╔╝██╔══██╗██╔══██╗██╔══██╗██╔══██╗
███╔╝ ███████║██████╔╝██████╔╝███████║
███╔╝ ██╔══██║██╔═══╝ ██╔═══╝ ██╔══██║
███████╗██║ ██║██║ ██║ ██║ ██║
╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝ ╚═╝

Welcome to Zappa!

Zappa is a system for running server-less Python web applications on AWS Lambda and AWS API Gateway.
This `init` command will help you create and configure your new Zappa deployment.
Let's get started!

Your Zappa configuration can support multiple production stages, like 'dev', 'staging', and 'production'.
What do you want to call this environment (default 'dev'):

AWS Lambda and API Gateway are only available in certain regions. Let's check to make sure you have a profile set up in one that will work.
Okay, using profile default!

Your Zappa deployments will need to be uploaded to a private S3 bucket.
If you don't have a bucket yet, we'll create one for you too.
What do you want call your bucket? (default 'zappa-8wjmc0weu'):

What's the modular path to your app's function?
This will likely be something like 'your_module.app'.
Where is your app's function?: app.__init__.app

You can optionally deploy to all available regions in order to provide fast global service.
If you are using Zappa for the first time, you probably don't want to do this!
Would you like to deploy this application globally? (default 'n') [y/n/(p)rimary]:

Okay, here's your zappa_settings.json:

{
"dev": {
"app_function": "app.__init__.app",
"aws_region": "ap-northeast-1",
"profile_name": "default",
"s3_bucket": "zappa-8wjmc0weu"
}
}

Does this look okay? (default 'y') [y/n]:

Done! Now you can deploy your Zappa application by executing:

$ zappa deploy dev

After that, you can update your application code with:

$ zappa update dev

To learn more, check out our project page on GitHub here: https://github.com/Miserlou/Zappa
and stop by our Slack channel here: https://slack.zappa.io

Enjoy!,
~ Team Zappa!

위에 보이는 것처럼 배포는 zappa deploy <stage> 를 사용하면 된다.

최초 배포 후에는 zappa update <stage>를 사용하여 업데이트를 하면 된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
(env) $ zappa deploy dev
Calling deploy for stage dev..
Creating zappa-dashboard-dev-ZappaLambdaExecutionRole IAM Role..
Creating zappa-permissions policy on zappa-dashboard-dev-ZappaLambdaExecutionRole IAM Role.
Downloading and installing dependencies..
Packaging project as zip.
Uploading zappa-dashboard-dev-1505403223.zip (10.5MiB)..
100%|█████████████████████████████████████████████████| 11.0M/11.0M [00:04<00:00, 2.34MB/s]
Scheduling..
Scheduled zappa-dashboard-dev-zappa-keep-warm-handler.keep_warm_callback with expression rate(4 minutes)!
Uploading zappa-dashboard-dev-template-1505403250.json (1.6KiB)..
100%|█████████████████████████████████████████████████| 1.66K/1.66K [00:00<00:00, 3.32KB/s]
Waiting for stack zappa-dashboard-dev to create (this can take a bit)..
100%|█████████████████████████████████████████████████| 4/4 [00:14<00:00, 5.26s/res]
Deploying API Gateway..
Deployment complete!: https://pqj13rwzi5.execute-api.ap-northeast-1.amazonaws.com/dev

하지만

이렇게 모든일이 일사천리로 끝난다면 매우매우 좋았겠지만 꼭 예상하지 못한 이슈가 발생하기 마련이다.

Zappa를 도입하기로 했을 때 여러가지 이슈로 삽질을 하게 되었는데,(물론 내가 부족해서 그랬던것이 대부분이지만)

그런 이슈들을 기록으로 남겨두면 좋을 것 같아 다음 포스팅으로 써야겠다.

Python에서 is 와 == 의 차이

2줄 요약

is 는 레퍼런스 체크

== 는 값 체크

내용

Python에서 무언가를 비교할 때 is를 많이 쓰고 했다.

is== 모두 값을 비교한다는 것만 알고 이 둘을 별로 구분없이 사용했다.(하지만 아니었다.)

1
2
3
4
5
>>> a = 1
>>> a is 1
True
>>> a == 1
True

여기까지는 당연하다

1
2
3
4
5
>>> a = 257
>>> a is 257
False
>>> a == 257
True

a is 257False를 반환하는 반면 a == 257True를 반환한다.

이것은 is는 레퍼런스를 비교하고 ==는 값을 비교하기 때문이다.

1
2
3
4
>>> id(a)
140316191538784
>>> id(257)
140316191538808

이와 같이 서로 다른 메모리 주소 값을 가지고 있기 때문에 위와 같은 결과가 나오게 된다.

1
2
3
4
5
>>> a = 1
>>> id(a)
140316194656296
>>> id(1)
140316194656296

a = 1을 하게 되면 메모리 주소가 같기 때문에 True를 반환한 것!

하지만 이는 Python Interpreter에서 [-5, 256] 범위의 Integer를 미리 캐싱(?)하고 있기 때문에 발생하는 일이다.

1
2
3
4
5
6
>>> def test():
... a = 257
... print a is 257
...
>>> test()
True

저렇게 컴파일 된 함수(?)안에서는 똑같은 메모리를 바라보게 되어 비교해보면 True를 반환한다

새롭고 신기한 Python의 세계

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×