서버 개발 후기 Joyfl 설진석
Who? 연세대학교 수학과 SW Maestro 2기 스타트업 Joyfl Cofounder 웹 & 서버 개발자
[email protected] fb.me/theeluwin
@theeluwin
요리한거 자랑하고 싶은데 딱히 올릴 곳이 없었음
남의 요리를 fork 떠서 내 방식대로 재창작
이 피피티는 초보자가 서비스를 런칭하기까지 겪었던 우여곡절입니다
여튼 서버를 맡게 되었음 근데 난 웹 전문
심지어 전공은 수학
예전에 학교에서 알고리즘 경시대회를 열었던 적이 있음
그때 쟝고 처음 사용
코드 복붙할 생각으로 쟝고를 선택
는 서버쪽 지식이 null이라서 서버 키는데 한달 걸림ㅋ
쟝고 튜토리얼도 안읽고 코딩 시작
User 모델링을 했음 근데 난 쟝고에 User가 원래 있는지 몰랐음 걍 쌩으로 만듦
로그인이 필요함 근데 난 쟝고에 authenticate이
원래 있는지 몰랐음 걍 쌩으로 만듦
그 땐 OAuth 같은게 뭔지 몰랐음 사실 로그인의 원리를 몰랐음 그래서 대충 상상을 해봄
서버
공개키
비밀키 RSA
우선 서버가 RSA로 공개키랑 비밀키를 만듦
클라 hash(“비밀이라능” + random)
email, password
서버
공개키
클라는 로그인시 “비밀이라능” 에 소금을 친 후 공개키로 암호화해서 같이 보냄
이건 일종의 OTP가 됨
서버
OTP 비밀키
서버는 받은 OTP를 까서 “비밀이라능”이 맞는지 확인하고
OTP를 NoSQL에 저장
REDIS
서버
“비밀이라능”이 맞았으므로 access token을 발급
클라 access token
SSL을 생활화합시다
장점 이 앱에서만 로그인 가능 replay attack 방지
단점 웹에선 쓸 수 없는 모델
로그인 외엔 replay attack 됨
매 요청마다 OTP를 거는건? 부하가 너무 클듯
애초에 replay attack이나 decompile을 걱정할만한 앱이었으면 좋겠음... 또르르
보안 설계는 대충 이정도로 하고
restful은 코드도 이뻐야댐
당시엔 django-rest나 tastypie를 익힐 능력이 안되었음
서버도 못키던 자연대생...
각 url을 method별로 함수로 구분 각 함수를 구현
/dish/:id urlDishId로 보냄
다시 getDishId, postDishId 등등으로 보냄
url(r'^dish/(?P<id>\d+)/?$', 'urlDishId’)
@method('GET', 'PUT', 'DELETE') def urlDishId(request, id):
method = request.method if method == 'GET': return getDishId(request, id) elif method == 'PUT': return putDishId(request, id) elif method == 'DELETE': return deleteDishId(request, id)
@authenticate(authorize = 'dish') def putDishId(request, id):
user_id = request.META['user_id'] ...
def getDishId(request, id): ...
@method('GET', 'PUT', 'DELETE') def urlDishId(request, id):
method = request.method if method == 'GET': return getDishId(request, id) elif method == 'PUT': return putDishId(request, id) elif method == 'DELETE': return deleteDishId(request, id)
method decorator는 내가 만든거 PUT, DELETE를 유효화해주고
올바르지 않은 method는 에러처리
https://gist.github.com/theeluwin/5955244
@authenticate(authorize = 'dish') def putDishId(request, id):
user_id = request.META['user_id'] ...
authenticate decorator도 내가 만든거 access token이나 “비밀이라능”을 검사해줌 쟝고 User를 쓰지 않아서 user 받아올때
저렇게 이상하게 했음
장점 코드가 이쁨
함수명이 직관적
여튼 pure rest를 이쁘고 빠르게 개발 가능
페북 연동은 https://github.com/pythonforfacebook/facebook-‐sdk
을 사용했음
근데 얘가 인코딩 버그가 있음!
왜 쟝고용 페북 SDK를 안썼냐?
애초에 나에게 쟝고는 ORM + http + template
나도 쟝고를 왜 쓰는지 모르겠음ㄷㄷ
랄것도 없었음... 대형 서비스가 아니니까
nginx
memcached
url cache
uwsgi
django
MySQL
pypy
REDIS
Java Push
RMQ
unix socket
SSL
staJc files
향후 계획? DB를 R/W 분리시키기 NoSQL 활용도 높이기
물론 서비스가 잘된다면야...ㅠㅠ 여기 링크 있어여
https://dishby.me 다운 후 별 5개 ㄱㄱ
유동성은 AWS가 진리임을 부정할 수 없음
cafe24 기가 호스팅을 알아봄
6마넌! AWS랑 큰 차이가 없긴 한데
여튼 나쁘지 않아 보임 일단 국내 서버고
근데 당시에 팀원 돈을 다 모아도 6만원이 없었음ㅋㅋㅋㅋ
(\w)모 사장님께서 도움을 주심! EC2 6만/달 급의 IDC 2개를 받음
(정말 감사드립니다)
“젊은이들이 하는건 묻따 ㄴㄴ하고 도와줘야함”
fit crop hash size 동시에 만족하는 library가 없더라
CharField 기반으로 wand 써서 만듦
(네 우리가 모두 잘 알고 있는 그분)
기술적인 문제 ㄴㄴ 구현하기 나름인데
실제 필드엔 해쉬값 “해쉬라능” 을 저장
실제로 생성되는 파일은 “해쉬라능.large.jpg”
“해쉬라능.640x480.crop.jpg” 뭐 이런식으로
https://dishby.me/media/dish/165faf317f65d56b37f63505cc3733dcaa767b01.large.jpeg
서버가 생기기 전에 cafe24 5,500원짜리 쓰고 있었음
근데 발코딩해서 그런지 메모리가 부족해서 서버가 쥬금
쿼리 튜닝의 필요성을 알게됨... 그 전까진 get하고 pk하나 반환하는
일이 허다했음
쿼리 튜닝 팁을 구글링해서 읽음
여전히 부족함을 느낌 결국 쟝고 문서 정독을 시작
쟝고 튜토리얼도 스킵했던 이유가 파이썬도 잘 몰라서 어쩔수 없었는데 쟝고를 써보고 튜토리얼을 보니
쟝고 문서 ㄷㄷ해
다들 알죠? 문제 발생 – 구글에 검색
최근에 봤던 쟝고 doc이 뜸 전엔 분명히 없었는데 이제 보니 써있음
는 구글링 하면 좋은거 많이 나옴..
개인적으론 manager나 F & Q의 활용이 도움 많이 됨
쿼리 수 vs join 수 정규화 vs 비정규화
팁을 쓸 만큼 경험이 많은건 아니지만 결국 unit test로 profiling하는게
답인듯. 빠른걸 선택
save & delete signal vs override
하려는거에 따라 되는게 있고 안되는게 있음 결국 둘다 씀...
celery 같은거 몰랐음 쌩 스레드 짜서 구현해봤음
SNS 특성상 스레드가 너무 많음 MQ로 커넥션 유지하는 프로세스한테 넘김 얘는 자바로 짬
글고 admin은 역시... 쟝고의 꽃
난 이걸로 외주도 해봤음 4시간 일하고 뱅마넌*_*
여튼 여차저차해서 library 거의 안쓴
심지어 쟝고 원래 기능도 많이 안쓴 이상한 서버가 탄생!
현재 에러 한번 없이 잘 돌아감!
이상 초보가 쟝고로 서비스 런칭하기까지 트러블 & 해결했던 이야기였슴다
https://dishby.me 다운로드 & 별 5개 ㄱㄱ