MICRO SOFTWARE 로고

 

기만콘이 끝나고...

 

마소에서 클라우드를 주제로

원고를 모집하는 글을 발견하였다.

 

 

뜨거운 여름에 내가 발표한 주제

'Python으로 AWS를 활용한 분산처리'

 

'어쩜 이렇게 타이밍이 기가 막힐까?'

 

나도 무언가를 해봐야겠다~ 다짐했던 2019년!

새로운 경험의 기회가 온듯했다.

 

나는 기만러 강대명 님에게

"내가 글을 써보는 건 어떨까요?"라고 묻자

그는 "무조건 쓰세요."라고 한다.

 

397호 기고자 최성훈 님에게

어떻게 하면 기고를 하는지 물어보았다.

 

조병승 편집장님 소환(?)

 

 

물어만 봤는데 소환된 조병승 편집장님.

 

"글을 써본 적 없지만 한번 써보고 싶었다."

"이번 주제가 클라우드인데 내가 기고해봐도 되는가"

"지난 기만콘에서 발표한 자료를 기준으로 글을 써보고 싶다"

 

일방적인 문의를 하였다.

 

기만콘 발표자료와 블로그의 글을 검토한 조병승 편집장은

"진행하시죠"라고 말했다.

 

그리고 그는 이어 말했다.

 

방법이야 어쨌든 깃발 꼽기에 성공한듯하다.

 

그는 곧바로 가이드 문서를 내게 건네며, 설명을 시작했다.

 

간략히 정리해보자면 아래와 같다.

 

- 가능하면 구글독스로 작성

- 폰트 크기는 10포인트 기준으로 12페이지 이상

- 초고 교정교열을 위해 마감일을 맞춰야 함.

 

(이 외에도 몇 가지 사항이 더 있긴 하다.)

 

 

내가 생각하는 중요한 기준은

 

내가 얼마나 해야 하는지

그리고 언제까지 해야 하는지이다. 

 

어느 정도 예상은 했지만...

나처럼 글을 써보지 않은 사람은 

부담스러운 양이다. 

 

일단 작성하기 시작했다.

 

발표자료와 블로그 글을 기준으로

한 줄씩 써 내려가기 시작했다. 

 

기만콘 발표할 때나 블로그에 글을 작성할 때는

발견하지 못한 문제점들이 보이기 시작했고

'이래서 계속해서 자료를 업데이트하는구나'

스스로 느끼게 되었다.

 

가장 어려웠던 점은

나는 프리랜서로 혼자 작성하는 글이지만

어떤 이들은 회사 소속으로 글을 작성하고,

회사의 지원을 받으며,

자료로 활용되는 이미지를 비롯하여, 

전체적인 진행과정이 수월하다는 것이다.

 

어쩌겠는가?

 

나는 프리랜서 생활을 만 5년을 했다.

이 정도야 외롭지만 잘 해내야지.

 

글을 쓰다 보니 나 스스로 답답한 부분이 있었다.

같이 작업한 클라우드 엔지니어의 글도 옮기고 싶어 진 것이다.

 

나는 이직한 클라우드 엔지니어들에게 연락을 했고,

읽는 이를 위해 적은 양이라도

같이 글을 써주길 원한다며 설득해보았다.

비록 익명이지만 도와준다 하였고,

클라우드 엔지니어의 글까지 모두 담을 수 있었다. 

 

덕분에 글의 흐름이 더욱 명확해졌고,

읽는 이에게는 개발자의 관점뿐만 아닌

엔지니어의 관점으로도 볼 수 있게 되었다.

 

기만러 강대명 님과

자바의 정석 저자 남궁성 님이

글을 베타 리딩 해주었고,

이어서 마소에서 교정교열 작업이 진행되었다.

 

밤낮 없이 교정교열을 하는 조병승 편집장

 

교열 작업은 손이 엄청 많이 간다.

한 번씩 나에게 내용을 다시 한번 체크를 하고,

그 과정 속에서 하나하나 내 글이 변신하는 모습을 봤다.

 

이 경험은 매우 좋은 경험이었다.

전문가의 도움을 받아

나의 글이 변해가는 모습을 보는 경험을 했다는 것은

앞으로도 큰 도움이 될 것이라고 생각했다.

 

 

 

드디어 내가 기고한 잡지가 나왔다.

 

398호 소개글

https://www.imaso.co.kr/archives/category/masolog

 

https://www.imaso.co.kr/archives/5443

 

마이크로소프트웨어 398호 클라우드의 어떤 것(Something Cloud)

안녕하세요,버그를 찾아 헤메는 버그베어,마이크로소프트웨어 조병승입니다. 2019년 10월 31일, 마이크로소프트웨어 398호 클라우드의 어떤 것(Something Cloud)편을 발행합니다. 만병통치약, 불로장생, 무병장수... 모든 것을 하나로 해결할 수 있는 특효약이 정말 있을까? 영원하거나 절대적인 답은 없다. 묵묵히 방법을 찾아 여러 갈래 길을 걷다 보면, 가려는 방향에 맞는 길을 찾을 수 있다. 하지만, 목적지가 바뀐다면? 어쩌면, 클라우드가 가

www.imaso.co.kr

 

 

 

398호 자기소개

 

기고기념

 

기고 기념으로 많은 분들이 축하해주었고,

원고료로 고기도 사먹었다.

 

 

 

그런데 마소콘에 연사로 섭외되었다.(?)

헐?

1순위 섭외 대상이라는 듣기 좋은 말과 함께 제안이 왔고,

기만러 강대명 님은 이제 그냥 묻지 말고 하라는 듯한 반응을 보였다.

 

이번에도 나는 깃발을 꼽았다.

 

 

기만 콘에서의 발표자료에 

마소 기고 내용을 혼합하여

발표자료를 새로 업데이트했다.

 

기만콘은 25분

마소콘은 40분

 

발표시간의 차이가 15분이 있다.

얼추 내용을 상세하게 추가해도 되지만

이번에는 데모를 만들어보기로 했다.

 

데모는 최대한 간단한 데모를 만들었다.

(https://kimminjun.dev/12 데모 자료 링크)

 

그리고 재미있던 일...

가장 간결하게 작성된 설명(자료)을 찾다 보니

벨로퍼트님의 블로그로 접근하게 되었고,

발표자료에 담으려고

벨로퍼트님에게 연락하였다.

 

그런데 벨로퍼트님이 웃으며 아래 사진을 내게 보냈다. 

 

김민준 동명이인

 

참고로 벨로퍼트님도 '김민준'이다.

자신에게 마소콘 연사냐고 물어봤다고...

 

 

아무튼 ㅋㅋㅋ

 

 마소콘 발표날까지 시간이 순삭 되었다.

 

2019년 11월 23일 토요일 

https://www.imaso.co.kr/masocon2019

 

 

마소콘에 콘퍼런스 트랙의 5번째 세션을 맡았다.

 

점심에 도착하여 식사를 하고,

올챙이 부스에서 조현종 대표님과 놀다가

올챙이 패드를 겟했다.

Tadpole DB HUB

 

13시가 되자 황후 순님의 리비에서

송지하 개발자의 발표가 시작되었다.

 

리비 발표전에 사진 한장 남겼다.

그리고 같은 시간 세미나실에서는

황후순님의 세미나가 시작되었다.

모자가 뒤집어진줄도 모르고 신난 기만러

 

나는 14시 40분부터 발표라서,

준비한 데모 및 발표자료를 다시 한번 확인했다.

 

14시 20분쯤 뒤에 있는 대기실에 처음 가봤고,

연사들이 모여서 대기하는 듯했다.

 

그리고 드디어 내 차례..

14시 40분부터 15시 20분까지

40분간 발표를 했다.

 

어떻게 끝난 건지 모르겠고,

무대에서 내려오니

질문을 하신 분은 명함을 건네며

연락 한 번 달라하였다.

 

그리고 IT 조선 기자가 연락처를 받아갔다.

 

행사가 종료되고 기자님이 나에게

'조금 더 쉽게 설명해줄 수 있느냐' 하였으나

내가 생각하는 범위 내 가장 쉽게 설명한 것이기 때문에

어떻게 도와드릴 방법이 없었다...

 

행사 참여자 중에 꽤 많은 비중으로

주니어 혹은 개발자를 꿈꾸는 학생들이 있던 것으로 보인다.

청중에 대한 레벨을 전혀 생각하지 못했다.

이 경험을 통해 조금 더 내가 준비한 것에 대해 가장

쉬운 방법을 정리해보는 것도 앞으로 도움이 되지 않을까 싶다.

 

내 바로 뒤 순서가 김세준 님이었는데

데모를 하고, 질문을 주고받고 하다 보니

발표시간이 약간 초과되었다..ㅠㅠ

죄송해하고 있었는데 연락이 왔다.

 

좋은 말씀해주셨다.

 

애저로 많은 강의를 준비하시고 계시고,

강의 콘텐츠에 대한 고민이 깊으셨다.

나는 AWS도 초보지만 Azure는 다루어보질 않았다.

 

원하는 강의 내용이 있는지 물어보시길래

의견을 전달했다.

 

행사가 끝나고 저녁식사를 했다.

같이 식사하신 분이 그러셨다. 

 

"발표자료도 좀 올리고 그래라."

 

나는 스피커 덱이나 슬라이드 셰어를 사용하지 않았다.

올릴 게 없었기 때문에... -_-

올려도 누가 봐줄까 싶기도 했고... -_-

심지어 계정도 없었다...

 

계정을 만들고 자료를 업로드했다.

그리고 기만러님이 자료를 뿌려주셨다.

 

꽤나 많은 분들이 공유를 해주셨다.

 

(1,000 뷰가 넘어가는 것이 신기...)

 

https://www.slideshare.net/MinJunKim5/masocon-2019-serverless-kimminjun

 

연락을 주고받던 기자님의 기사도 업로드되었다.

http://it.chosun.com/site/data/html_dir/2019/11/23/2019112301329.html

 

[마소콘 2019] "서버리스는 서버가 없는 것이 아닙니다. 효율적으로 사용하는 것입니다"

"서버리스(Serverless)를 직역하면, 혹자는 서버가 없다고 오해하지만, 컴퓨터에 서버를 놓고 쓰는 게 아니라는 뜻입니다. 클라우드 공급자..

it.chosun.com

 

마소 스피커 덱에도 내 자료가 올라갔다.

https://speakerdeck.com/microsoftware

 

마소 스피커덱

 

 

글을 쓰는 이유는

다른 누군가 도전을 고민할 때 나의 글을 읽고

조금은 도움이 되지 않을까 싶었다.

 

물론 나 스스로의 정리도 하고 싶었다. 

 

끝~

 

 

'Home > Life' 카테고리의 다른 글

MICRO SOFTWARE(마소)와 함께한 2019년  (0) 2019.12.31
2019 제1회 기만콘 (후기)  (1) 2019.12.25

2019년 7월 20일 토요일

네이버 D2 스타트업 팩토리에서
기만콘이 진행되었다. 

 

http://fairbrite.com/DevStarLeague/events/12

 

 

늦은 후기를 적어본다.

 

 

 

 

 

 

 

 

기만콘이 무엇일까? 

 

 

 

 

 

(모시는글 사진)

 

 

 

그렇다.

기만의 황제 강대명이 직접 기획한 콘퍼런스다.
 

그냥 같이 게임을 즐기는 IT 종사자들이
(대부분 개발자...)

있다 보니 자연스럽게 콘퍼런스 얘기가 오갔고,

뜬금없이 "콘퍼런스를 우리도 해보자"라는
말과 함께 기만콘이 시작되었다.

 

 

 

(멤버들은 나름대로 랭킹전도하고 스타를 즐기고 있다.)

 

 

 

 

 

(원래는 이름이 없는 세미나였다.)

 

 

 

기만의 황제님은 마음대로 인원을 정하고 봤다.

(동의는 필요 없는 기만러)

 

 

 

 

(진짜인가 장난인가..)

 

 

 

처음에는 진짜 장난인 줄 알았다...

 

이름도 '기만콘'이라고

내 마음대로 붙여서 불렀더니

진짜 '기만콘'이 되었다.ㅋㅋ

 

각자 주제를 선정하기 시작하더니...

결국 신청 페이지까지 만들어졌다.

(http://fairbrite.com/DevStarLeague/events/12)

 

 

 

 

 

(기만의 황제가 신났다.)

 

 

 

 

 

 

(발표 내용 및 순서)

 

 

 

홍보는 별도로 진행하지 않았고,

페이스북을 통해 각 연사들의 글로 행사를 알렸다.

그리고 완판 했다...

 

(이것이 기만의 황제의 능력인가...)

 

 

 

 

(빛승민이 완판을 알리고 있다.)

 

 

 

 

그런데 당일 정말 더운데
태풍까지 기만콘에 온다고 하더라.

 

 

 

(태풍도 반겨주는 기만러)

 

 

기만콘 전날...

 

기만의 황제 강대명 님은 직접 마트에 가서

참가 신청비(5,000원)로 간식을 구매했다.

기만콘의 취지는 받은 돈을

참석자들에게 모두 돌려주는 취지였다.

 

(노쇼방지)

 

 

 

(참석자들을 위한 간식)

 

 

 

 

 

(영수증을 공개)

 

 

 

모든 비용처리를 투명하게 하려는

기만의 황제 강대명의 마음이 느껴지는 사진이다.

 

 

 

행사 당일

 

 

갓 대명님은 그래도 더 많이 나눠야 한다며,
집으로 오라고 한다(?)...

(혼자 들고 가기 힘들다고...)

 

 

 

(먹다가 죽으라고 간식을 엄청 많이 준비한 기만러)

 

 

 

 

 

(그리고 또 영수증)

 

 

 

 

80명 행사에 이렇게 많은 간식을
준비하는 행사는 처음이다.

 

 

장소에 도착하니 홍연의님이 맞이해주셨다.

그는 오늘의 문지기를 담당하신다고 한다.

 

(장소를 제공해준 LINE 감사합니다.)

 

 

 

 

 

 

 

 

의자를 나르고, 테이블을 세팅한다.

 

 

그리고 간식을 놓고 보니 음료가 없네...

(난 힘들어서 쉴 겸 흡연을 하러 갔고...)

 

기만러와 기만러의 피카추가 음료를 사 왔다.

 

 

 

(그리고 또 영수증)

 

 

 

행사 운영은 김정환 님이 해주셨다.

http://fairbrite.com/

 

 

 

(김정환님)

 

 

사람들이 하나둘씩 들어오기 시작한다. 

그리고 기만의 황제 강대명은

마치 자식 결혼식을 하는 부모님처럼 손님들 맞이하기 시작한다. 

 

 

 

(준비 완료)
(가득 차버린 자리(?))

 

 

 

HOST MC 갓대명의 진행으로
제1회 기만콘이 시작되었다.

 

 

 

(세상에서 가장 신난 기만러가 행사에 대해 설명하고 있다.)

 

 

 

 

13:10 ~ 13:20 : 김대희

- 개발자 스타리그 역사

 

머희님은 어떤 사람들이 어떻게 모였고,

어떻게 이곳까지 오게 되었는지 설명해주었다. 

 

 

 

 

(주말이라 참석자중 윤종열님은 이쁜 꼬마까지 데려왔다.)
(어깨는 왜 그런가?)

 

 

 

간략하게 준비된 그룹 활동에 대해 설명이 끝났고,

곧바로 빛승민(이승민)의 발표가 시작되었다.

 

 

13:20 ~ 13:40 : 이승민

- New Android Declarative UI patterns - Compose

 

당시 빛승민(이승민)은 패스트캠퍼스에서 주말 강의를 하는 중이라

가장 먼저 발표를 했다.

 

 

 

(빛승민의 자기소개)
(새로운 안드로이드의 UI 패턴을 설명하는 빛승민)
(GDE답다... 그저 빛...)

 

 

 

 

빛승민의 발표가 끝나고,

빛처럼 사라진 이승민 님 뒤로
머 희님의 발표가 시작되었다.

 

 

13:40 ~ 14:00 : 김대희

백엔드 개발자가 허우적대는 리액트 이야기

 

미안하다... 나는 흡연하러 갔다.

(머 희님의 발표 사진을 소지하고 계신 분은 제게 보내주세요.)

 

(피카피카추)

 

 

 

(진짜 사진을 갖고 계신분이 연락주셨다)

 

 

몽고 디비 커뮤니티의 김인범 님 사진 감사합니다.

 

머희님의 발표가 끝나고

장소를 제공해준 LINE에서

'개발자 문화'에 대해 발표를 하였다.

 

그리고 다음 타자 까꿍 성(남궁성)님

 

14:25 ~ 14:50 : 남궁성

- 성인에게 코딩을 가르쳐보니...

 

자바의 정석 저자이자
현재 강사로 활동 중인 남궁성 님.

전설의 포켓몬처럼 외부행사에서 뵙기 힘든 분인데

기만의 황제는 전설의 포켓몬도
세상으로 꺼낼 수 있는 능력이 있다.

 

 

 

(가장 호응이 좋았던 발표 남궁성!)
(라떼는 말이야...)
(지속성을 유지하는것이 가장 중요하다는 남궁성 강사님)
(중간중간 웃음이 터지는 팩트를 준비하셨다.)

 

 

 

남궁성 님의 발표가 끝나고
술종민(부종민)님의 발표가 진행되었다.

 

14:50 ~ 15:20 : 부종민

websocket

 

술종민(부종민)님은 발표를 시작하자마자

QR코드를 참석자들에게 제공하였다.

 

 

(자신을 스프링개발자라고 소개를 하는 부종민님)

 

 

QR코드로 접근하면
부종민 님이 준비한 사이트에 접속되었고

현장에서 접속한 사람들은
웹소켓을 직접 확인할 수 있었다.

 

 

 

 

 

 

 

부종민 님의 발표가 끝나고 잠시 휴식을 갖고,

갓경일(이경일)님의 발표가 시작되었다. 

 

 

15:30 ~ 16:10 : 이경일

- 당신도 할 수 있는 레거시 프로젝트 개선 이야기

 

갓경일(이경일)님은
스프링캠프의 발표자료를 재탕하였다.

(그러고 보니 스캠 자료 안 하고 술 종민님은 새로운 것을 했었구나...)

 

 

 

 

(모두가 기대한 이경일님의 발표)

 

 

스프링 캠프에서 가장 인기가 많았다는
이경일 님의 발표를 들을 생각에
배가 고파 빵을 집어 들었다.

(냠냠)

 

 

 

 

 

 

예상대로 중간중간 소고기를 좋아하는
갓경일님의 재치가 돋보였다.

 

 

그리고 등장한 이스트럭(강동운)님..

 

16:10 ~ 16:40 : 강동운

하둡 밑부터 파 해쳐 보자 팍팍! HDFS와 NameNode 그리고 HA

 

 

 

(그는 소싯적 스타 초고수였다고 한다.)

 

 

 

예상보다 DBA들의 참석률을
높인 계기가 된 세션이다.

 

 

그리고 내 순서-_-...

 

16:40 ~ 17:05 : 김민준

- Python으로 AWS을 활용한 분산 처리

 

 

발표는 무엇인가?
나는 왜 여기 있는가? 
...

어떻게 시간이 흘러간 건지 모르겠다.

 

 

 

(내용 설명중...)
(프롤로그...)

 

 

원래 파이콘에서 발표해보려고 준비했었는데

파이콘에 선정되지 않아 기만콘에서 했다.

 

마지막 순서였던 나의 발표가 끝났다.

 

기만의 황제 강대명 님은 후원받은 책들은

직접 눈앞에서 랜덤 함수를 이용하여 나눠주는
경품 이벤트를 진행했다.

'자바의 정석'저자가 있는데

'자바의 정석'이 경품으로 나가니

작은 사인회가 진행되는 상황이 연출되었다.

 

아무래도 주제가 너무 각각 다른 주제라

사람들이 안 올 줄 알았는데 의외로 많이 왔고,

끝까지 남아서 내 발표까지 들어준 사람도 많았다.

 

행사가 종료되고 뒷정리를 진행하는데

모든 참석자들이 정리를 도와주었다.

의자도 나르고 테이블도 나르고...

 

커뮤니티에서 세미나를 진행한다는 것이 쉽지 않고

고된 일이란 걸 느낄 수 있는 소중한 경험이었다.

 

 

 

 

(기만의 황제 강대명은 다음을 기약하는듯한 수상한 글을 남겼다.)

 

 

 

참가 신청비로 받은 금액 중
남은 비용은 기부하게 되었다.

 

 

 

 

(기부천사)

 

 

 

 

그럼 제2회 기만콘을 기대해보자.

'Home > Life' 카테고리의 다른 글

MICRO SOFTWARE(마소)와 함께한 2019년  (0) 2019.12.31
2019 제1회 기만콘 (후기)  (1) 2019.12.25
  1. 주디아줌마 2019.12.27 07:58

    저도 참석했지만 유익하고 재밌었어욧


MASOCON 2019 데모 자료 입니다.




발표 내용을 참고해주시면 됩니다. 


- 사이트 : https://www.imaso.co.kr/masocon2019

- 발표자료 : https://www.slideshare.net/MinJunKim5/masocon-2019-serverless-kimminjun (슬라이드쉐어)

https://speakerdeck.com/microsoftware/masokon-2019-seobeoriseureul-hwalyonghan-bunsan-ceori-gimminjun (스피커덱 - 마소콘공식)




데모를 무엇으로 준비할지 고민이 엄청 많았습니다.

공공기관의 API는 대부분 한도가 있다보니 적절한 예시를 찾아야 했는데...

관세청에서 찾았습니다.


관세청API에서 '관세환율'을 이용했습니다.


먼저 관세청API에 대해 설명을 하자면, 1:N 의 데이터 입니다. XML로 리턴받으며 GET방식으로 1개씩 받아올 수 있습니다.


아래 이미지는 관세청 API 문서의 일부입니다.


(출처 : https://unipass.customs.go.kr


형태는 일반적인 공공기관의 API와 크게 다르지는 않습니다. 






요청메시지는 단순하게 날짜와 수출입 구분만 넣습니다. 




응답 메시지는 국가부호/화폐단위명/환율/통화부호/적용개시일자/수출입구분 총 6개의 필드로 구성되어 있습니다. 







요청/응답에 대한 예시입니다. 








인증키는 개별적으로 신청하여 받으시면 됩니다. 과정에 대해서는 생략합니다. 


구조도입니다. 


1. AWS Console을 이용하여 실행.

2~5. API Gateway로 처리, Lambda에서 데이터(날짜범위)값을 갖고 옴.

6~8. SNS를 통해 Invoke된 Lambda는 각각 할당 받은 만큼 처리한다.

9. 처리가 완료된 데이터는 DynamoDB로 저장한다.




Lambda는 3개가 필요하고 API Gateway 1개 그리고 SNS 와 DynamoDB가 필요합니다.
언어는 Python(v3.6)을 사용했고, 발표내용에 나온것처럼 Layers를 이용하여 라이브러리를 패키징하여 재사용 하였습니다.


일단 Lambda에 있는 Layers부터 이미지를 통해 보여드리겠습니다.



Lambda에 접근을 하면 좌측 메뉴중에 가장 하단에 '계층'이 존재합니다. 

이미지는 제가 이미 등록해둔 라이브러리 패키징이네요. 등록한 'python36-lib'를 계속해서 재사용하여, Lambda를 실행합니다.


우선 위의 API에 필요한 날짜값을 갖고오는 Lambda를 준비합니다.





Designer에 Lambda이름 밑에 Layers를 등록되어 있는모습이 보입니다.

Layers는 최대 5개를 등록할수 있어요. (라이브러리가 중복되거나 하는 문제가 발생할 수 있습니다.)





그리고 API Gateway도 확인할 수 있어요. API Gateway를 생성하여 Lambda와 연결한 상태입니다.

API Gateway를 이용하여 처음 시작하는 Lambda가 위의 이미지의 Lambda를 호출해서 날짜값을 갖고 올꺼예요.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#-*- coding:utf-8 -*-
import datetime
from datetime import date
import json
 
def lambda_handler(event, context):
        
    strdate = ''
    for i in range(13660):
    # for i in range(1, 31):
        datedata = datetime.date.today() + datetime.timedelta(-i)
        if (i != 1):
            strdate = strdate + ',' + datedata.strftime('%Y%m%d')
        else :
            strdate = datedata.strftime('%Y%m%d')
        # print(datedata.strftime('%Y%m%d'))
 
    return strdate
 
# if __name__ == '__main__':
#     lambda_handler('','');
cs



yyyymmdd의 값을 ( , ) 로 붙여서 Text를 return 해주는 함수예요.
정말 심플하게 Source를 준비했어요. 31개로 돌려보고 365개로 돌려보고...
발표 당시에 데모를 돌리는데 양이 너무 적다보니 금방 끝나더라구요. 그래서 3660를 돌렸는데 그 상태로 남아 있어요.
(실제로 제가 작업할땐 다른 API를 호출하는데 약 15~20만건의 데이터를 돌리고 있어요)




이미지처럼 날짜값을 갖고 오고, 기준이 되는 Lambda에서 호출해서 받아온뒤 ( , ) 를 기준으로 잘라서 사용합니다. 
아래 이미지가 바로 기준이 되는 Lambda예요.


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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#-*- coding:utf-8 -*-
 
import json
import zeep
import urllib3
import xml.etree.ElementTree as ET
import time
import ast
import boto3
import requests
import os
import re
 
from urllib.request import urlopen
from requests.auth import HTTPBasicAuth
from requests import Session
from zeep import Client
from zeep.transports import Transport
from bs4 import BeautifulSoup
 
def errorCheck(msg) :
    print(msg)
 
def get_unipass_data(list):
 
    """
    # get_unipass_data
    # (list)  
    """
    
    print('# [get_unipass_data] Count : 'len(list))
    # print(list)
    print(os.environ['ARN_SCRAPING'])
    try:
 
        print('# [SNS 전송 시작]')
        client = boto3.client('sns')
        response = client.publish(
            TargetArn = os.environ['ARN_SCRAPING'],
            Message = json.dumps({'default': json.dumps(list)}),
            Subject = 'PY36_MASOCON_DEMO_UNIPASS_URL',
            MessageStructure='json'
        )
        print('# [SNS 전송 끝]')
 
 
    except Exception as e:
        print('# [SNS 전송 오류]')
        print(e)
 
        return errorCheck(e,'')
    
    return 'OK'
 
 
def url_list():
    try:
        
        headers = {
            'x-api-key': os.environ['xapikey'],
            'Content-type':'application/json;charset=utf-8',
            'Accept':'*/*'
        }
        
        data = {}
        resp = requests.post(os.environ['api_url'], headers=headers, data=json.dumps(data))
        dict = resp.text.split(',')
        url_list = []
        
        if len(dict) > 0 :
            for i in dict: 
                url_list.append(os.environ['unipass_url'+ i.replace("\"",""))
                
        print('# 총 건수 : 'len(url_list))
        data = []
        if len(url_list) > 0 :
            count = 0
            total_group_count = 0
            for i in url_list: 
                data.append(url_list[count])
                count = count + 1
                if (len(data)/36== 1 :
                    get_unipass_data(data)
                    total_group_count = total_group_count + 1 
                    data.clear()
                    #break
            if len(data) > 0 :
                total_group_count = total_group_count + 1 
                get_unipass_data(data)
                data.clear()
 
            print('# 36개씩 나눈 작업 개수 : ', total_group_count)
        return url_list 
        
    except Exception as e:
        print(e)
        return errorCheck(e)
 
def lambda_handler(event, context):
    url_list()
 
# if __name__ == '__main__':
#     lambda_handler('','')
    
cs




소스는 API Gateway 를 호출하고, 받아온 Text 값을 ( , ) 를 기준으로 split을 하고 dict에 넣습니다.
그런데 보시면 os.environ['변수명'] 이 보이실꺼예요. 이것은 Lambda에서 제공해주는 환경 변수를 이용했어요. 
(boto3를 이용해서 인코딩/디코딩을 해서 사용해도 좋습니다.)
위치는 Lambda Console화면에서 '함수코드' 밑에 '환경변수'가 있습니다. 
저는 key를 4개 사용했습니다. 



반복문을 이용하여 36개씩 나누어 get_unipass_data를 호출해요. 
get_unipass_data는 Amazon SNS 에 던지는 역할입니다.
데모에서 에러처리에 대해서는 별도로 구성하지는 않았어요.
(실제로 구현할때는 에러처리도 Amazon SNS에 에러내용을 전달하여 Lambda를 통해서 RDBMS에 넣었습니다.)

여기까지가 아래 구조도의 내용이예요.



그럼 Amazon SNS를 통해 전달받은 Lambda를 보여드릴게요. 



SNS가 연결되어 있는것을 볼 수 있습니다. 활성화도 되어 있구요. 


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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#-*- coding:utf-8 -*-
######################
############## lib 
######################  
 
import json
import zeep
import urllib3
import xml.etree.ElementTree as ET
import time
import ast
import boto3
from urllib.request import urlopen
from requests.auth import HTTPBasicAuth
from requests import Session
from zeep import Client
from zeep.transports import Transport
from bs4 import BeautifulSoup
from multiprocessing import Process
 
def dynamo_insert(list):
 
    """
    # get_unipass_data
    # (list)  
    """
    
    print('# [DynamoDB] Count : 'len(list))
 
    try:
 
        print('# [SNS 전송 시작]')
        client = boto3.client('sns')
        response = client.publish(
            TargetArn = 'ARN값을 넣습니다...',
            Message = json.dumps({'default': json.dumps(list)}),
            Subject = 'PY36_MASOCON_DEMO_UNIPASS_SCRAPING',
            MessageStructure='json'
        )
        print('# [SNS 전송 끝]')
 
 
    except Exception as e:
        print('# [SNS 전송 오류]')
        print(e)
 
        return errorCheck(e,'')
    
    return 'OK'
 
 
def errorCheck(msg) :
    print(msg)
    
def change_date_format(content):
    if content != None:
        return content[0:4]+'-'+ content[4:6+ '-' + content[6:8
 
def Unipass_scraping(list):
 
    count = 0
    
    print('# [Unipass_scraping] Count : 'len(list))
    err_url = ''
 
    try:
        if len(list) > 0 :
            for url in list: 
 
                err_url = url
                count = count + 1
 
                tree = ET.ElementTree(file=urlopen(url))
 
                tCnt = 0
                tCnt = int(tree.find('tCnt').text)
                
                print(tCnt)
                list_trifFxrtInfoQryRsltVo = []
                        
                if tCnt > 0:
                    for item in tree.findall('trifFxrtInfoQryRsltVo'):
                        if item.find('cntySgn').text == "KR" : 
                            trifFxrtInfoQryRsltVo = {
                                'cntySgn' : item.find('cntySgn').text if item.find('cntySgn').text != None else None,
                                'mtryUtNm' : item.find('mtryUtNm').text if item.find('mtryUtNm').text != None else None,
                                'fxrt' :item.find('fxrt').text if item.find('fxrt').text != None else None,
                                'aplyBgnDt' : change_date_format(item.find('aplyBgnDt').text) if item.find('aplyBgnDt').text != None else None,
                                'currSgn':item.find('currSgn').text if item.find('currSgn').text != None else None,
                                'imexTp' : 2
                            }
 
                    dynamo_insert(trifFxrtInfoQryRsltVo)
 
        err_url = ''
        
        print('success')
 
    except Exception as e:
        print('# [Unipass_scraping] Error : ', e)
        print('# [Unipass_scraping] err_url : ', err_url)
        # pass
        return errorCheck(e,err_url)
        
        
        
def lambda_handler(event, context):
    
    if 'API' in event :
 
        print('# 작업명 (Event == API)')
 
        job_type = event['API'][0]['Type']
        message = json.dumps(event['API'][0]['Data'])
        messageList = ast.literal_eval(message)
        
        Unipass_scraping(messageList)
        
        return job_type
 
    elif 'Records' in event : 
 
        print('# 작업명 (Event == Records)')
 
        job_type = event['Records'][0]['Sns']['Subject']
        message = event['Records'][0]['Sns']['Message']
        messageList = ast.literal_eval(message)
        
        Unipass_scraping(messageList)
        
        return job_type
 
    else : 
        return 'not working'
        
cs





핸들러는 이벤트 값을 받고, 이벤트 값에 제가 API 인지 Records인지 구분을 합니다. 

발표내용을 보면 'API Gateway를 통해서 직접 실행할수 있게 구현했다.' 라는 내용이 있는데요. 그 내용입니다.

간단하게 구분값을 API / Records 로 했어요. 그리고 Subject에 타입을 넣어서 던졌어요. 

실제 구현한 소스에는 Subject를 기준으로 분기처리도 했었어요. 

message에는 데이터를 담았어요. 그래서 message 를 list로 만들어서 Unipass_scraping으로 던집니다. 


처음에 언급한바와 같이 관세청 API는 1:N 이예요. 1개씩 던져서 여러행을 받습니다.

list 를 반복하여 관세청 API를 통신하고, 결과 값을 받아서 DynamoDB에 만든 TEST테이블에 Insert합니다. 

(저는 리턴받은 데이터중 KR만 뽑아서 담았어요) 

DynamoDB를 Insert하는 Lambda에 SNS를 이용해서 던집니다. 

DynamoDB에서 테이블은 간단하게 1개의 키로만 구성했어요. (DynamoDB는 NoSQL입니다.)







DynamoDB에 Insert하는 Lambda의 소스입니다.


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
import json
import ast
import boto3
 
def dynamoDB_INSERT(data):
    dynamodb = boto3.resource('dynamodb', region_name='ap-northeast-2')
    dynamodb.Table('MASOCON_DEMO').put_item(
        Item={
            'DATA': data
        }
    )
    
    return 'success'
 
def lambda_handler(event, context):
    
    if 'API' in event :
 
        print('# 작업명 (Event == API)')
 
        job_type = event['API'][0]['Type']
        message = json.dumps(event['API'][0]['Data'])
        messageList = ast.literal_eval(message)
        dynamoDB_INSERT(message)
        return 'success'
 
    elif 'Records' in event : 
 
        print('# 작업명 (Event == Records)')
 
        job_type = event['Records'][0]['Sns']['Subject']
        message = event['Records'][0]['Sns']['Message']
        messageList = ast.literal_eval(message)
        print(message)
        dynamoDB_INSERT(message)
        return 'success'
 
    else : 
            
        # data = 'aaaa'
        # dynamoDB_INSERT(data)
        
        return 'not working'
        
cs





Amazon SNS를 통해서 받아서 넣는건데요, 이전에 봤던 Lambda와 다른점은 DynamoDB에 Insert를 하는것 말고는 크게 다른것이 없습니다.

결과를 보여드리겠습니다.


실행 전 





실행 후 



참고로 호출하는 관세환율에 대한 정보는 7일을 기준으로 바뀌는 데이터였어요. 
즉, 7번의 중복되는 데이터를 제가 갖고오는거죠. 그렇지만 DynamoDB의 특성상 키값을 기준으로 동일한 값이 들어가면 UPDATE처리가 된다고해요.
(사실... 중복제거하고 DynamoDB에 넣는게 맞는것인데.. 일단 저는 이렇게 데모를 준비했네요ㅎㅎ) 
실행 후 테이블에 몇백개의 데이터가 들어가있는것을 확인해볼 수 있습니다.

데모를 준비하면서 IAM을 잡는 부분이 생각보다 어려웠어요. 
실무에서 구현할때는 사내에 있는 클라우드팀의 도움을 받았으나, 데모는 하나하나 제가 설정을 잡은거였거든요.

상세하게 서비스별로 설명드리기는 어렵고, 기회가 되면 IAM 설정을 포함한...
사용한 서비스들에 대해서 하나씩 글을 남겨보겠습니다.
(이글은 데모에 대한 내용일뿐이예요...)

마지막으로 다시 구조도를 보여드리겠습니다.







+ Recent posts