강대성
daesung7.kang@gmail.com
PHP에서 Django로 갈아타기
Session 공유를 통한 WebFramework간 이동
소개
현재
2년차 아빠, 5년차 남편, 2년차 CTO
피플펀드컴퍼니 2015.09 ~ 현재 - CTO ( IT의 모든 일 )
아재
과거
록앤올(김기사) 2년 - 교통정보 분석, 미래 속도 예측
금융회사 6년 - 해외선물, FX거래 시스템
통신회사 2년 - 인사 관리 시스템
게임회사 3년 - MMORPG 서버 개발
10살때부터 컴퓨터와 금융을 좋아했음.
이 이야기는 서로 다른 Web Framework간
점진적으로 갈아타는 기본 지식과 성공 사례입니다.
2015년 9월
저는 피플펀드컴퍼니에
1호 엔지니어로 조인했습니다.
디자이너가 PM이고
외주로 만들어진 홈페이지가 있었습니다.
PHP
PHP가 나쁘지 않으나,
PHP로
계속 서비스하고 싶진 않았습니다.
금융을 PHP로 만들다가,
나중에 어려워 질 것 같았죠.
내일 당장 오픈할지 모르는데,
어떻게 하면 PHP에서 벗어날 수 있을까?
PHP을 한번에 없애고
새로운 것으로 바꾸면
버그가 발생할 확률이 높으니
점진적으로 옮기기로 합니다.
점진적으로 옮기기!
“Back to the Basic”
기본부터 다시 봅시다.
PHP, Django
HTTP, Session, Cookie
HA(High Availability)
PHP
PHP(Hypertext Preprocessor)는 프로그래밍 언어의 일종이다. 원
래는 동적 웹 페이지를 만들기 위해 설계되었으며 이를 구현하기 위
해 PHP로 작성된 코드를 HTML 소스 문서 안에 넣으면 PHP 처리
기능이 있는 웹 서버에서 해당 코드를 인식하여 작성자가 원하는 웹
페이지를 생성한다. 근래에는 PHP 코드와 HTML을 별도 파일로 분
리하여 작성하는 경우가 일반적이며, PHP 또한 웹서버가 아닌
php-fpm(PHP FastCGI Process Manager)을 통해 실행하는 경우
가 늘어나고 있다.
https://ko.wikipedia.org/wiki/PHP
<html>
<body>
1~10까지 나오는 예제입니다. 여기는 HTML 부분입니다.<br>
<?php
for( $i = 1 ; $i <= 10 ; $i++ )
{
echo $i;
echo “<br>”;
}?>
여기도 HTML 부분입니다.<br>
</body>
</html>
Django
장고(Django)는 파이썬으로 작성된 오픈 소스 웹 애플리케이션 프레임워크로, 모델-뷰-
컨트롤러 패턴을 느슨하게 적용한다. 2005년 7월에 BSD 사용 허가서로 공개되었다.



이 웹 애플리케이션 프레임워크는 집시 재즈 기타리스트인 장고 라인하르트의 이름을 따
명명되었다.



고도의 데이터베이스 기반 웹사이트를 작성하는 데 있어서 수고를 더는 것이 장고의 주
된 목표이다. 장고는 콤포넌트의 재사용성(reusability)과 플러그인화 가능성
(pluggability), 빠른 개발 등을 강조하고 있다. 또한, "DRY(Don't repeat yourself: 중
복배제)" 원리를 따랐다. 설정 파일 일서부터 데이터 모델에까지 파이썬 언어가 구석구석
에 쓰였다.
https://ko.wikipedia.org/wiki/%EC%9E%A5%EA%B3%A0_(%EC%9B%B9_%ED%94%84%EB
%A0%88%EC%9E%84%EC%9B%8C%ED%81%AC)
HTTP
HTTP
HyperText Transfer Protocol
해석 : HyperText(참조를 통해 한 문서에서 다른 문서로 이동할 수 있는 텍스
트)의 전송 규약
다른 프로토콜 )
SSH : Secure Shell
SMTP : Simple Mail Transfer Protocol
FTP : File Transfer Protocol
HyperText
<html>
<body>
이것은 하이퍼 텍스트의 예제입니다.
<a href=”/example.html”>다른 예제로 이동</a>
</body>
</html>
HTTP
접속, 요청, 응답, 끊기
접속, 요청, 응답, 끊기
접속, 요청, 응답, 끊기
* KeepAlive도 있긴함
접속
요청
GET / HTTP/1.1

Host: www.peoplefund.co.kr

(생략)
응답
HTTP/1.1 200 OK

Content-Type: text/html; charset=utf-8

(Header 생략)
<html>
<head>
(Content 생략)
끊기
다음 접속 시작
요청
GET /example.html HTTP/1.1

Host: www.peoplefund.co.kr

(생략)
응답
HTTP/1.1 200 OK

Content-Type: text/html; charset=utf-8

(Header 생략)
<html>
<head>
(Content 생략)
끊기
첫번째 접속,
두번째 접속이
같은 웹브라우저인가?
같은 브라우저임을
어떻게 증명할 것인가?
Session Token
A session token is a unique identifier that is generated and
sent from a server to a client to identify the current
interaction session. The client usually stores and sends the
token as an HTTP cookie and/or sends it as a parameter in
GET or POST queries.
https://en.wikipedia.org/wiki/Session_(computer_science)
쿠키(Cookie)
쿠키(cookie)란 하이퍼 텍스트의 기록서(HTTP)의 일종으로서 인터넷 사용자가
어떠한 웹사이트를 방문할 경우 그 사이트가 사용하고 있는 서버를 통해 인터넷
사용자의 컴퓨터에 설치되는 작은 기록 정보 파일을 일컫는다. HTTP 쿠키, 웹 쿠
키, 브라우저 쿠키라고도 한다. 이 기록 파일에 담긴 정보는 인터넷 사용자가 같
은 웹사이트를 방문할 때마다 읽히고 수시로 새로운 정보로 바뀐다. 이 수단은
넷스케이프의 프로그램 개발자였던 루 몬툴리(Lou Montulli)가 고안한 뒤로 오
늘날 많은 서버 및 웹사이트들이 브라우저의 신속성을 위해 즐겨 쓰고 있다.
쿠키는 소프트웨어가 아니다. 쿠키는 컴퓨터내에서 프로그램처럼 실행될 수 없
으며 바이러스를 옮길 수도, 악성코드를 설치할 수도 없다. 하지만 스파이웨어를
통해 유저의 브라우징 행동을 추적하는데에 사용될 수 있고, 누군가의 쿠키를 훔
쳐서 해당 사용자의 웹 계정 접근권한을 획득할 수도 있다.
https://ko.wikipedia.org/wiki/HTTP_%EC%BF%A0%ED%82%A4
Session Token w/Cookie
서버에서 생성하여 클라이언트에 보냄,
클라이언트가 매번 서버로 보냄
ex) 5hbbad4p5jf8la3m66rn3a7ff5
Session Token
HTTP/1.1 200 OK
Set-Cookie: SESSID=5hbbad4p5jf8la3m66rn3a7ff5; path=/;
GET / HTTP/1.1
Cookie: SESSID=5hbbad4p5jf8la3m66rn3a7ff5
29
30
Server/Client는
Session Token을 공유하고
Server에 Token기반으로
정보 저장
여러분의 서비스는 안 죽을 수 있나요?
HA(High Availability)
한대가 죽어도 살아남을 수 있게.
Active-Active
Active-Standby
웹서버는
보통 Active-Active
이제 본격적인 이야기를 해보겠습니다.
어떻게 점진적으로 Django로
갈아탈 수 있을까?
내부 로직만 API로 만들어보자
HTTP
DB
Connection
DB
ConnectionRESTHTTP
Django에서 API를 만들고
PHP는 API를 호출
API 만들기 : Django REST Framework
uwsgi의 설정
# the socket (use the full path to be safe
socket = /tmp/inapi.sock
API를 위한 Nginx설정
upstream myapi {
server unix:///tmp/api.sock;
}
server {
listen 7001;
access_log /var/log/nginx/access-api.log;
location / {
uwsgi_pass myapi;
include /etc/nginx/uwsgi_params;
}
}
방화벽으로 조정하거
나, localhost만 listen
PHP
$curl = new Curl();
$curl->setHeader("Content-Type", “application/json");
$this->result = $curl->get(“127.0.0.1:7001” . “/niceapiexample”);
// Do Something with $this->result
PHP에서 DB에 접근하지 않을 수 있고,
Django를 통해 금융 서비스 개발
이제 Front-End도
Django로 만들어볼까?
#1. 동일한 HTTP연결인데,
URL별로 PHP or Django 서비스
#2. Access Log는
같이 남길까 따로 남길까?
#1. URL에 따라 Django or PHP 로 서비스
https://example.com/django-pages/*
https://example.com/php-pages/*
Web Server
HTTP
NGINX 로 Routing 필요.
upstream django_peoplefund {
server unix:///tmp/peoplefund-web.sock;
}
server {
listen 80;
location /django-pages/ {
uwsgi_pass django_peoplefund;
include /etc/nginx/uwsgi_params;
access_log /var/log/nginx/access-django.log;
}
location /php-pages/ {
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
include /etc/nginx/fastcgi_params;
access_log /var/log/nginx/access-php.log;
}
}
PHP에서 로그인 했는데,
Django에서 회원 정보를
어떻게 인식해야하는지?
Web Server
HTTP
PHP에서 생성된 Session Token,
Client는 매번 Session Token을 보냄,
Django에도 같은 Session Token으로 요청됨
Django에서
PHP에서 생성된 Session만
읽어오면 되겠다
PHP는 Session을 파일 기반으로 처리
Local File에 저장
/var/lib/php5/sess_[sessionkey]
PHP설정을 다음과 같이 바꾸면
Session을 읽기 쉽게 저장됨
/var/lib/php5/sess_5hbbad4p5jf8la3m66rn3a7ff5
파일 내용
a:1:{s:7:"user_id";i:12345678}
Session Token :
5hbbad4p5jf8la3m66rn3a7ff5
Session File :
/var/lib/php5/sess_5hbbad4p5jf8la3m66rn3a7ff5
File Contents :
a:1:{s:7:”user_id";i:12345678}
파일의 위치와 내용은 알았고,
파일 내용만 Django에서 잘 읽어내면 되겠다.
비슷한 고민을 했던 분들이 있었다.
import phpserialize

with open("/var/lib/php5/sess_"+session_key, mode='rb') as fp_session:

session_contents = fp_session.read()

session_dict = phpserialize.loads(session_contents)

/var/lib/php5/sess_(session_key)를 읽어와서 session_dict에 집어 넣기
Session FileSession File
서버 한대가 죽는다면?
여기에 있는
정보는?
죽은 서버에 접속된 유저들의
Session File에 접근할 수 없으니
전부 로그아웃 됨
한대가 죽어도
(한대를 죽여도)
사용자는 아무 영향 없어야 함
Session DB
PHP에서 Session을 File이 아닌 DB로,
Django에서 DB에서 Session정보를
얻어오게 변경
DynamoDB
쉽고 저렴해서 선택
PHP
use AwsDynamoDbDynamoDbClient;
use AwsDynamoDbSessionHandler;
$dynamodbclient = new DynamoDbClient(
[ 'region' => $DYNAMO_REGION,
'version' => 'latest',
'credentials' => ['key' => $DYNAMO_KEY, 'secret' => $DYNAMO_SECRET]]
);
$sessionHandler = SessionHandler::fromClient($dynamodbclient,
[
'table_name' => $DYNAMO_TABLE,
'session_lifetime' => 3600,
'locking_strategy' => 'pessimistic'
]
);
$sessionHandler->register();
Django
awssession = boto3.session.Session(ACCESSKEY, SECRETKEY, region_name=REGION)

dynamodb = awssession.client('dynamodb')

res = dynamodb.get_item( TableName =DYNAMODB_TABLE,
Key = { 'id':{'S':'SESSID_'+session_key}})

session_contents = res[‘Item']['data']['S'].encode(
settings.DEFAULT_ENCODING_PHP_SESSION_FILE) # bytes 형으로 변환
session_dict = phpserialize.loads(session_contents) # bytes 형으로 받음
Session DB
정리
1단계 : API형식으로
PHP(Front-End) - Django(Back-End)로 구성
2단계 : 세션 공유와 Nginx를 이용해
PHP와 Django를 하나의 도메인으로 운영 가능
3단계 : 외부 DB에 Session을 보관함으로 HA구성 가능
감사합니다

Py con2017 ph_ptodjango