Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,5 @@ yarn-error.log
.pnp.js
# Yarn Integrity file
.yarn-integrity

*venv*
138 changes: 138 additions & 0 deletions content/blog/개발/5분만에_알아보는_AWS_Lambda.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
---
title: 5분 만에 알아보는 AWS Lambda
date: "2020-04-26T23:50:00+09"
description: 예제와 함께하는 AWS Lambda with Python
draft: false
---

> 클라우드 서비스 덕에 서버가 없어도, 서버 관리자가 없어도 소수의 인원이 웹서비스를 만들고 운용할 수 있는 시대가 도래하였습니다. 그것이 가능한 이유 중 하나인 Serverless를 AWS Lambda 예제를 이용하여 알아보겠습니다.

## 서버리스란

서버리스는 운용하는 입장에서 서버에 대한 관리가 필요하지 않은 서비스입니다. 서버는 클라우드 서비스에서 관리해 주고, 사용자는 실행에 필요한 함수에 대해서만 관리를 하면 됩니다. 사용하지 않더라도 서버를 켜 놓은 시간에 대해서 비용이 발생하는 가상서버와는 달리, 서버리스는 함수를 실행시키는 데에 필요한 리소스에 대한 비용만을 지불하면 됩니다. 대표적인 서버리스 서비스는 AWS Lambda, GCP Functions, Azure functions가 있습니다.

서버리스를 이용하면 API를 손쉽게 만들 수 있을 뿐만 아니라, 다른 클라우드 서비스와 트리거를 설정해 놓으면, 실시간 파일 처리 등의 서비스를 구현 할 수 있습니다.

이번 포스트에서는 AWS Lambda와 파이썬을 이용하여 간단한 API를 만들어보겠습니다.

## 서버리스 프레임워크

[서버리스 프레임워크](https://serverless.com/)는 서버리스 서비스를 더욱 간편하게 이용 할 수 있게 해주는 오픈소스 프레임워크입니다. 서버리스 프레임워크를 이용하면, 서버리스에 사용될 함수의 개발, 테스트, 배포 단계를 편리하게 하실 수 있습니다.

### Node.js 설치

서버리스 프레임워크는 [Node.js](https://nodejs.org/ko/)가 설치되어있어야 하는데, 맥에서 [nvm](https://github.com/nvm-sh/nvm)을 통해 Node.js를 설치하기 위해서는 아래 명령어를 이용하면 됩니다.

```shell
# nvm 설치
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bash

# Node.js LTS 버전 설치
nvm install --lts
```

### 서버리스 프레임워크 설치

서버리스 프레임워크는 아래의 명령어로 간편하게 설치하실 수 있습니다.

```shell
npm install -g serverless
```

### AWS 계정설정

서버리스 프레임워크에서 AWS 계정에 접근하기 위해서는 환경변수에 AWS credentials를 등록해야 합니다. 아래 명령어로 환경변수에 AWS credentials를 일회성으로 등록 할 수 있고, 쉘 실행 시에 자동으로 등록해주기 위해서는 아래 명령어를 ~/.bashrc 나 ~/.zshrc 파일에 넣어주면 됩니다.

```shell
export AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE
export AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
export AWS_DEFAULT_REGION=us-west-2
```

## AWS Lambda와 파이썬으로 API 만들기


### 서버리스 프레임워크 템플릿
서버리스 프레임워크의 큰 장점은 템플릿이 많이 존재한다는 것입니다. 어떤 템플릿들이 존재하는지 궁금하시면 아래 명령어를 입력하시면 됩니다.

```shell
serverless create -t
```

![서버리스 템플릿](serverless_templates.png)

서버리스 프레임워크는 여러 가지 클라우드 서비스와 여러 가지 언어의 조합으로 템플릿을 제공하는데, 우리는 AWS Lambda를 python3로 이용하는 aws-python3 템플릿을 사용하여 프로젝트를 만들겠습니다.

```shell
serverless create -t aws-python3
```

![서버리스 aws-python3](serverless_aws-python3.png)

만들어진 프로젝트에는 handler.py와 serverless.yml, 그리고 .gitignore, 모두 세 개의 파일이 존재합니다. \
handler.py는 우리가 클라우드 서비스에서 실행시킬 함수가 들어있고, serverless.yml에는 서버리스 프레임워크의 설정값이 들어있습니다.

### serverless.yml 수정

serverless.yml의 기본값에는 API 관련 내용과 AWS region 설정이 빠져있습니다. 따라서 해당 내용을 추가하여 아래와 같이 수정해줍니다.

```yaml
service: serverless

provider:
name: aws
runtime: python3.8
# region 추가
region: ap-northeast-2

functions:
hello:
handler: handler.hello
# API 설정 추가
events:
- http:
method: get
path: test
cors: true
```

### hello.py 수정

hello.py를 조금 수정해서 API get method를 이용해 파라미터를 받아오는 예제를 만들어 보겠습니다.

hello.py를 아래와 같이 수정합니다.
```python
import json

def hello(event, context):
body = {
"message": "Go Serverless v1.0! Your function executed successfully!",
# event 내용 중 API에서 넘겨주는 queryStringParameters 출력
"input": event['queryStringParameters']
}

response = {
"statusCode": 200,
"body": json.dumps(body)
}

return response
```

### API 배포

서버리스 프레임워크의 아래 명령어로 API를 배포 할 수 있습니다.

```shell
serverless deploy
```

배포 완료 후, endpoint에 API 주소가 나타납니다. 그 주소 제일 뒤에 ?age=100을 추가하여 API를 테스트해 보겠습니다. 아래와 같은 출력이 나온다면 성공입니다. 웹브라우저나 curl을 이용하여 테스트해 보시면 됩니다.
![서버리스 결과](serverless_result.png)


축하드립니다! 서버리스를 이용하여 API를 완성하셨습니다!

## 마지막으로

서버에 대한 고민 없이, 서버리스 프레임워크의 설정값과 함수만을 이용하여 API를 만들어보았습니다. 서버리스 프레임워크를 활용하면, CPU를 이용하는 간단한 딥러닝 모델도 API 형태로 서빙을 할 수 있습니다. 다음번에는 서버리스를 이용하여 딥러닝 모델을 배포하는 방법에 대해 살펴보겠습니다.
126 changes: 126 additions & 0 deletions content/blog/개발/5분만에_알아보는_웹스크래핑.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
---
title: 5분 만에 알아보는 파이썬 웹 스크래핑
date: "2020-03-29T17:48:00+09"
description: 예제와 함께하는 파이썬 웹 스크래핑
---

> 구슬이 서 말이어도 꿰어야 보배다.\
요즘엔 데이터가 재산이라는 말이 있습니다. 그럼 세상에서 가장 많은 데이터는 누가 가지고 있을까요? 세상에서 가장 많은 데이터는 웹상에 공개된 형태로 존재하고 있습니다. 하지만 이 데이터를 가지고 있는다고 해서 바로 부자가 되지는 않습니다. 구글이 데이터를 잘 정리해서 검색하기 쉽게 만들어 준 것처럼 데이터를 잘 꿰어야지만 비로소 보배가 되는 것이지요.\
웹 상의 데이터를 꿰는 과정인 웹 스크래핑의 세계에 처음으로 발을 들이고 싶으신 분들을 위해 간략한 가이드를 작성해 보았습니다.

## 웹 크롤링? 웹 스크래핑?

먼저 용어 정리를 하고 가겠습니다. 웹 크롤링과 스크래핑은 저를 포함해서 많은 분들이 용어를 섞어서 사용하고 있는데, 제가 이해하고 있는 정의는 다음과 같습니다.

**웹 크롤링** : 웹을 여기저기 돌아다니는 행위\
**웹 스크래핑** : 웹 원하는 자료를 추출 해내는 행위

웹에서 원하는 데이터를 모으려면 보통 웹을 돌아다니는 행위와 각 페이지에서 원하는 자료를 추출 해 내는 행위가 함께 이루어지므로, 두 용어는 구분해서 쓰지 않습니다. 하지만 이번 포스트에서는 하나의 페이지에서 자료를 추출 해 내는 것에 대해서만 다룰 예정이므로 웹 스크래핑이라는 용어를 사용하겠습니다.

## 실습을 위해 필요한 환경

이번 포스트에서는 파이썬을 이용한 웹 스크래핑을 해 볼 예정입니다. 이번 포스트에서 나오는 예제를 실행시켜보기 위해서 필요한 환경은 다음과 같습니다.

```shell
python3
bs4 # pip install bs4
requests # pip install requests
```

## 웹 스크래핑

먼저 우리가 웹브라우저를 이용해 페이지에 접근을 하는 과정을 간단하게 표현하면 다음과 같습니다.

```text
1. 웹브라우저에서 서버에 페이지를 요청 (request)
2. 서버에서 웹브라우저에 페이지를 보내줌 (response)
3. 웹 브라우저에서 페이지를 이쁘게 보여줌 (render)
```

웹 스크래핑 하는 과정도 우리가 웹브라우저를 사용하는 과정과 크게 다르지 않습니다.

```text
1. 파이썬에서 서버에 페이지를 요청 (request)
2. 서버에서 파이썬에 페이지를 보내줌 (response)
3. 페이지에서 원하는 데이터를 추출 (parsing)
```

웹브라우징과 웹스크래핑은 페이지를 요청하고 받는 1번, 2번 과정은 동일하고, 3번과정에서 페이지를 보여주느냐, 페이지에서 데이터를 추출하느냐만 다르다고 생각하시면 됩니다.

위의 예제는 가장 단순한 상황에서의 웹브라우징, 스크래핑을 설명 한 것이고, 만약에 로그인같은 좀 더 복잡한 과정을 거쳐서 페이지를 요청해야 하거나, 서버에서 보내준 페이지를 단순히 보여주는 형태가 아닌, 동적으로 브라우저에서 페이지를 만드는 형태라면 웹스크래핑 과정도 그에 맞게 바뀌어야 합니다. 이런 경우에는 [selenium](https://www.selenium.dev/) 이라는 패키지를 이용해서 대응 할 수 있습니다.

## 예제: 네이버 뉴스 헤드라인 가져오기

이제부터 네이버 헤드라인 뉴스의 제목을 가지고 오는 예제를 살펴보겠습니다.
먼저 파이썬에서 웹페이지 요청을 하고, 그 다음에는 웹페이지를 파싱해서 원하는 정보를 추출 해 내는 순서로 설명드리겠습니다.

### 1. 파이썬에서 웹페이지 요청하고 받기

```python
# 웹페이지 요청을 위한 패키지
import requests

# 네이버 뉴스 페이지 url
url = 'https://news.naver.com/'
# 네이버 뉴스 페이지 요청, 응답 저장
response = requests.get(url)

print(response) # 응답 형식은 <Response [200]>
print(response.status_code) # 응답 코드는 200 (정상 응답)
print(response.text) # 응답 내용 출력 (html, 엄청 긺)
```

코드는 엄청 간단합니다. 원하는 url을 requests.get 함수의 인자로 넣어주고, 함수를 호출하면 서버에 웹페이지를 요청하고, 응답결과를 반환합니다. 응답결과는 Response 객체로 되어 있는데, 자세한 사항은 [Requests 문서](https://2.python-requests.org/en/master/user/advanced/#id2)를 보시면 도움이 됩니다.

현재 Response 객체에서 우리가 필요한 내용은 두 가지입니다. response.status_code를 확인해서 서버로부터 정상 응답(200)이 왔는지, 정상응답이 왔다면 response.text로부터 해당 페이지의 내용을 가져오는 것입니다.

response.text의 내용을 보면, 긴 text 형식의 html 파일입니다. 여기에서 우리가 원하는 헤드라인 뉴스의 제목을 추출 해 내기 위해서는 html을 파싱하는 작업이 필요합니다.

### 2. 웹페이지에서 원하는 데이터 추출하기

```python
# 웹페이지 파싱을 위한 패키지
from bs4 import BeautifulSoup

# response로 부터 html 가져오기
html = response.text

# BeautifulSoup 으로 html 파싱
soup = BeautifulSoup(html, 'html.parser')

# CSS Selector 로 헤드라인 뉴스가 있는 항목 선택
hdline_titles = soup.select('#today_main_news > div.hdline_news > ul > li > div.hdline_article_tit > a')

# 헤드라인 뉴스가 있는 a 태그에서 텍스트만 추출
for title in hdline_titles:
print(title.get_text(strip=True)) # 결과 출력

```

BeautifulSoup은 html을 파싱해주는, 말 그대로 아름다운 패키지 입니다.

html을 파싱 한 후 가장 중요한 것은 우리가 원하는 정보가 있는 곳을 찾는 작업입니다. 개인적으로는 이 작업이 웹 스크래핑에서 가장 시간이 오래 걸리는 부분으로 생각됩니다.

html에서 원하는 정보가 있는 곳을 선택하는 방법으로는 CSS Selector, XPath 등이 있는데, 여기서는 CSS Selector를 이용했습니다. 두 작업 모두 CSS에서 원하는 정보가 있는 곳의 태그, 클래스 이름, 아이디를 찾아내는 작업이 필요합니다. 크롬 개발자도구를 이용하면 보다 편리하게 CSS Selector를 찾아 낼 수 있습니다.

![크롬 개발자도구를 이용한 CSS Selector 찾기](find_css_selector.gif)

크롬 개발자도구를 이용해 찾아낸 CSS Selector는 아래와 같습니다.

```css
#today_main_news > div.hdline_news > ul > li:nth-child(1) > div.hdline_article_tit > a
```

이 셀렉터는 하나의 제목을 가져오는 것이므로, 제목을 모두 가져오기 위해서는 li 태그의 모든 항목을 가져오는 것이 필요합니다. 따라서 이 글에서는 CSS Selector를 아래와 같이 변경 한 후, 코드에 적용하였습니다.

```css
#today_main_news > div.hdline_news > ul > li > div.hdline_article_tit > a
```

보다 자세한 [CSS Selector](https://www.w3schools.com/cssref/css_selectors.asp) 문법은 다음에 다루도록 하겠습니다.

## 마지막으로

이 글에서는 웹페이지로부터 원하는 정보를 추출 해내는 스크래핑의 간단한 예제를 살펴보았습니다. 여기서 원하는 url을 순차적으로 탐색하는 크롤링 기능만 넣으면 쓸만한 웹 크롤러를 만들 수 있습니다. 웹 크롤링에서 가장 중요한 것은 대상이 되는 서버에 많은 부담을 주지 않는 것과, 해당 웹사이트에서 크롤링을 원하지 않는 자료는 크롤링 하지 않는 것입니다. 서버에 부담을 주지 않는 것은 크롤러에 일정 딜레이를 주어서 해결 할 수 있고, 해당 웹사이트에서 크롤링에 대해 어떤 정책을 가지고 있는지는 웹사이트의 robot.txt를 참고하면 알 수 있습니다.

웹 크롤링을 보다 쉽게 만들어주는 [Scrapy](https://scrapy.org/) 프레임워크 사용 방법에 대해서도 추후에 다루도록 하겠습니다.
14 changes: 14 additions & 0 deletions content/blog/개발/Gatsby로_블로그_만들기.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
title: Gatsby로 블로그 만들기
date: "2020-04-10T17:48:00+09"
description: Gatsby로 쉽게 만드는 Github Page
draft: true
---

> 블로그를 시작하기로 마음을 먹은 뒤에 가장 먼저 한 일은 어떤 플랫폼을 쓸 것인가였다. IT라면 역시 깃허브지! 라는 마음으로 깃허브 페이지를 만들어보았는데, ruby를 전혀 모르는 입장에서 Jekyll은 쉬운듯 어려웠다. 최근에 자바스크립트와 리액트를 입문정도 수준으로 공부했는데, 마침 리액트를 기반으로한 Gatsby라는 프레임워크를 알게되어서 깃허브 페이지를 만들어 보았다.

## 왜 Jekyll이나 Gatsby를 사용할까?

Github page에서는 공식적으로 Jekyll을 권장하고 있는데, Jekyll이나 Gatsby를 사용하면, github page에 쉽게 블로그를 만들 수 있다. 더 중요한 것은 마크다운으로 글을 작성하면 웹페이지 형태로 변환을 해 줘서, HTML이 아닌 익숙한 형식으로 쉽게 글을 작성 할 수 있다. 물론 네이버나 티스토리, 미디엄등의 블로그 서비스를 이용하는 것 보다는 조금 더 복잡하지만, 한 번 익숙해지면 글을 작성하는 난이도는 블로그 서비스를 이용하는 것과 크게 다름이 없다. 그리고 멋진 github.io 도메인은 덤이다.

## Gatsby는 무엇인가
Binary file added content/blog/개발/catalina_versions.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added content/blog/개발/find_css_selector.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added content/blog/개발/python_venv.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added content/blog/개발/serverless_aws-python3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added content/blog/개발/serverless_result.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added content/blog/개발/serverless_templates.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added content/blog/개발/shell-command.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading