진행하고 있는 장고 프로젝트에 cron 작업을 추가하는 경험을 정리해본다.


환경 및 선수조건

  • Django
  • crontab의 개념
  • (선택) pyenv와 virtualenv를 이용한 가상환경(가상환경에서도 잘 돌아가고 경로 설정을 자동으로 해줍니다.)


crontab 사용 이유

문제

  • 기존 API를 호출하면 페이지를 크롤링을 하고 그에 대한 결과를 응답하는데 시간이 3초 이상걸린다.

해결

  • 크롤링하고자하는 페이지를 주기적으로 크롤링해서 결과를 DB에 저장해두고 API는 DB에 저장된 값들만 가져온다.


설정

pip를 통한 설치

pip install django-crontab


settings.py에 django_crontab를 추가

settings.py

...
INSTALLED_APPS = (
    'django_crontab',
    ...
)
...


app/cron.py의 파일을 생성 및 함수 만들기

  • 해당 장고프로젝트의 app(본인의 경우에는 main이라는 앱명을 지었습니다.)폴더 안에 cron.py 파일을 생성하고 함수를 만듭니다.
  • 사실 함수를 불러올 수 있는 경로이면 상관 없습니다. 즉, 따로 cron.py를 만들지 않고 경로만 잘 잡아주면 됩니다.

app/cron.py

def my_cron_job():
    pass


settings.py에 있는 CRONJOBS에 작업 추가하기

  • 기본 Linux crontab과 형식이 같습니다.(참고)
  • 기본 구조: * * * * * 수행할 명령어
  • 순서대로 분(0 - 59) 시(0 - 23) 일(1 - 31) 월(1 - 12) 요일(0 - 6) (0:일요일, 1:월요일, 2:화요일, …, 6:토요일)
  • 예제: ('*/5 * * * *', 'app.cron.my_cron_job') -> 매 5분마다 app/cron.py에 있는 my_cron_job()을 실행합니다.

settings.py

...
CRONJOBS = [
    ('*/5 * * * *', 'app.cron.my_cron_job')
]
...


적용

등록된 job들을 모두 실행

python manage.py crontab add

등록된 job들을 모두 제거

python manage.py crontab remove

등록된 job들을 모두 보기

  • django-crontab을 통해서 등록한 job들이 보여집니다.
python manage.py crontab show


확인

  • 위에 나와있는 명령어로 확인이 가능하지만 django-crontab의 경우에는 등록을 하면 Linux crontab에 등록이 된다.
  • crontab -e의 명령어를 통해서 확인이 가능하다.


실수

  • django-crontab을 이용하는 경우에 실제 리눅스에 등록된 crontab이 작동하는거기 때문에 파일의 경로에 신경을 써줘야합니다.
  • 예를 들어서, 위에 cron.py에서 파일을 새로 생성했다면 프로젝트의 앱 폴더(app/)가 아닌! 리눅스 유저 기본 디렉토리(~)에 위치합니다!


참고자료

OS를 공부할 때 나오는 개념인 멀티프로그래밍, 멀티프로세싱, 멀티스레딩, 멀티태스킹에 대해 알아보자


환경 및 선수조건

  • OS에 대한 아주 간략한 이해(OS가 무엇이다 정도)
  • 싱글코어 멀티코어
  • 프로그램, 프로세스 그리고 스레드의 개념


싱글코어와 멀티코어

  • Core: CPU안에서 기초적인 연산을 처리하고 담당하는 부분을 말한다. 사람의 뇌로 생각을 하면 대뇌와 비슷하다.
  • Multi Core: 하나의 CPU안에 여러개의 코어를 구현해 놓은 아키텍처를 멀티코어라고 한다.
  • Hyper-Threading: 인텔에서 개발한 기술로 하나의 코어에 논리적으로 두개 이상의 코어처럼 동작하도록 설계한 기술을 의미한다.


프로그램, 프로세스 그리고 스레드

Program

  • Program: 저장소에 존재하는 코드의 뭉치로 실행상태가 아닌 실행하기 전에 저장소에 저장된 코드들이다. 우리가 흔히 실행한다는 게임이나 도구(Word, Excel등등)들이 해당된다.

Process

  • Process: 저장소에 존재하는 프로그램이 컴퓨터가 실행해서 CPU가 처리할 수 있게 메인 메모리에 올라온 상태이다.

Thread

  • Thread: 프로세스 안에 있는 작은 실행단위로 프로세스와 Data영역과 Code영역은 공유하고 스레드 각자의 스택과 레지스터를 갖는다.


멀티프로그래밍, 멀티프로세싱, 멀티스레딩, 멀티태스킹

멀티프로그래밍

  • 초창기 싱글코어 싱글 스레드 컴퓨터에서는 프로그램이 메모리에 하나만 올라가고 해당하는 프로그램만 CPU가 처리를 진행할 수 있었다. 이런 과정에서 프로그램이 파일 입출력을하게 되면 중간에 idle(정지)상태가 되는데 이 때 다른 프로세스의 일부를 실행시키는걸 의미한다.

멀티프로세싱

  • 하나의 컴퓨터에 여러개의 CPU를 장착하고(CPU속에 멀티코어로 생각해도 무방합니다.) 하나 이상의 프로세스들을 동시에 처리하는걸 의미한다.
  • 더 넓은 범위로 해석하면 하나 또은 그 이상의 프로세스를 여러 장치에서 병렬로 처리하는 것을 의미한다.

멀티스레딩

  • 말 그대로 프로세스내에서 하나의 스레드가 아닌 여러개의 스레드를 형성하여 명령어들을 처리하는걸 의미한다.

멀티태스킹

  • 테스크란 OS에서 처리하는 작업단위를 의미하는데 그 여러 작업 단위가 빠르게 처리되어 동시에 처리되는것처럼 보이는 것을 의미하며 Concurrent라는 특징을 생각하면 된다.
  • 여기서 말하는 여러 작업 단위란 처리해야하는 여러 프로세스들의 명령어들을 쪼갠거라 생각하면 된다.


참고자료

Git에서 작업중인 현재 branch에 있는 commit 내역들을 수정해보자


환경 및 선수조건

  • Git


문제 상황 및 목적

  • 새로운 branch를 만들어서 commit을 2번 하였는데 그 2번의 commit에 다 오타가 있어서 수정하고 싶은 상황


방법

  • rebase를 통해서 수정이 가능하다.
  • git rebase -i HEAD~~: HEAD를 포함해서 2번째 부모 커밋 전까지의 내역을 rebase를 통해서 수정하겠다.


HEAD와 인덱싱을 통해 찾기

  • HEAD: git에서 현재 작업중인 곳을 가리키는 포인터
  • HEAD~ or HEAD~1: HEAD로부터 첫번째 부모 커밋. 즉, 현재의 이전 커밋
  • HEAD~~ or HEAD2: HEAD로부터 두번째 부모 커밋. 즉, 현재의 이전 이전 커밋


실제 적용 사례

rebase 명령어 사용

  • 현재 작업내용을 포함해서 이전 커밋까지 수정한는거니까 아래와 같다.
$ git rebase -i HEAD~~


pick을 edit으로 변경

  • 아래처럼 화면이 뜨면 vim의 방식을 이용해서 pick -> edit으로 변경해준다.
  • i를 눌러서 변경하고 ESC를 누른 다음에 :를 누르고 wq를 누르면 저장된다.
...

pick 6a2298f add main.js to staticd folders
pick 7911e2d 코드에 있는 indentation tab(4spaces)로 수정

...
...

edit 6a2298f add main.js to staticd folders
edit 7911e2d 코드에 있는 indentation tab(4spaces)로 수정

...


중간 확인

  • 그러면 아래처럼 화면에 수정할 수 있도록 명령어를 치라는 화면에 쉘에 나와야 한다.
  • git commit --amend로 수정 한번하고 git rebase --continue를 통해서 다음 수정으로 넘어가는 방식
...

You can amend the commit now, with

  git commit --amend

Once you are satisfied with your changes, run

  git rebase --continue

...


수정하기

  • 명령어 실행 및 vim 방식을 통해서 메시지 수정
$ git commit --amend
  • 다음 수정으로 넘어가기
$ git rebase --continue


완료

  • 마지막으로 아래 명령어를 수행하면 성공이라고 뜬다. 뒤에 브랜치 명은 사용한 브랜치에 따라서 다르다.
$ git rebase --continue
Successfully rebased and updated refs/heads/feature/merge-all-js-codes-to-js-file.


참고자료

업데이트(2019.09.08): 조건문 사용법 업데이트

Linux 기반 운영체제에서 스크립트를 사용할 때 조건문을 어떻게 사용하는지 알아보자.


환경 및 선수조건

  • Linux
  • Mac OS
  • Bash shell(/bin/bash)


스크립트에서 조건문 사용하기

기본 구조

#!/bin/bash

if [ 조건 ] # 조건 양 옆에 '['와 ']' 사이에 공백을 꼭 있어야합니다!
then
    명령어
elif [ 조건 ]
then
    명령어
else
    명령어
fi

# 또는

if (( 조건(arithmetic operation) )); then
	명령어
elif (( 조건(arithmetic operation) )); then
	명령어
else
	명령어
fi


예제

example.sh

#!/bin/bash

# test_num = 0 이렇게 입력하면 syntax 에러가 발생합니다 꼭 붙여서 써주세요.

# Numeric if statement
test_num=5

if [ "${test_num}" -eq 2 ]; then
	echo "number is 2"
elif [ "${test_num}" -eq 3 ]; then
	echo "number is 3"
else
	echo "number is not 2 or 3"
fi

# 위와 같은 비교문이지만 (())를 사용하면
# <, >와 같은 산술 연산자를 사용할 수 있습니다.

# Numeric if statement
test_num=5

if (( ${test_num} > 3 )); then
	echo "number is greater than 3"
else
	echo "number is not greater than 3"
fi

# String if statement
test_str="test"

if [ "${test_str}" = "test" ]; then
	echo "test_str is test"
else
	echo "test_str is not test"
fi
$ ./example.sh
number is not 2 or 3
number is greater than 3
test_str is test


참고자료

Python에서 Requests모듈을 통해서 json 데이터를 요청하고 받아와서 파싱해보자.


환경 및 선수조건

  • Python(3.X)
  • requests 모듈, json 모듈


Requests?

  • HTTP 통신을 위한 파이썬 라이브러리로 urllib.request처럼 with문 사용없이 직관적으로 사용이 가능합니다.


Requests 기본 사용법

기본 예제

  • 홈페이지에 있는 내용을 그대로 가져왔습니다.
>>> import requests
>>> r = requests.get('https://api.github.com/user', auth=('user', 'pass'))
>>> r.status_code
200
>>> r.headers['content-type']
'application/json; charset=utf8'
>>> r.encoding
'utf-8'
>>> r.text
u'{"type":"User"...'
>>> r.json()
{u'private_gists': 419, u'total_private_repos': 77, ...}

다른 Method를 사용할 때

  • GET, POST, PUT, DELETE, HEAD, OPTIONS가 다 가능합니다.
>>> import requests
>>> r = requests.get('https://api.github.com/events')
>>> r = requests.post('http://httpbin.org/post', data = {'key':'value'})
>>> r = requests.put('http://httpbin.org/put', data = {'key':'value'})
>>> r = requests.delete('http://httpbin.org/delete')
>>> r = requests.head('http://httpbin.org/get')
>>> r = requests.options('http://httpbin.org/get')


json요청하고 파싱하기

  • 올린 json파일을 HTTP 요청을 통해서 받아오고 그걸 python에서 사용할 수 있는 dictionary형태로 파싱을 하는 코드입니다.

import requests
url = 'https://gist.githubusercontent.com/TWpower/771f9dfc8d9e1ddc0ecbdaea5b2e379e/raw/2c7785b4835138255bdadb71bd83702e53ac2677/test-example.json'

data = requests.get(url).json()


참고자료