본문 바로가기
정보공유

2017 Pycon KR - Django/AWS 를 이용한 쇼핑몰 서비스 구축

by 날고싶은커피향 2018. 11. 28.

2017 Pycon KR - Django/AWS 를 이용한 쇼핑몰 서비스 구축




2017 Pycon KR - Django/AWS 를 이용한 쇼핑몰 서비스 구축
1. PYCON KR 2017 Youngil Cho 인테이크 주식회사
2. 조영일 / http://www.choyoungil.com / jeffrey@intakefoods.kr 현재 • 식품 스타트업 ‘인테이크’ 창업(2012~) : http://www.intakefoods.kr • CTO : 서비스 기획/개발/운영 과거 • 모바일 게임 개발사 ‘어썸피스’ : 동기/비동기 게임 서버 개발(Python, Java) • GIS SW 개발사 ‘자올소프트’ : 브라우저 기반 웹 지도 엔진 개발(Javascript) 기술 • Languages : Python, Java, Javascript • Framework/Library : Django, Flask, Celery, Node.js • Cloud : AWS / AWS Solutions Architect Associate 취득 • 기타 : Google Analytics / GAIQ 취득
3. https://www.shopintake.com
4. • ‘인테이크’ 라는 자사 브랜드 온라인 쇼핑몰 • 2014년 8월 런칭 • 누적 주문 수 7만+ • 누적 회원 수 5만+ • 월간 주문 수 5000+ • 월간 PV 30만+
5. • 쇼핑몰, 직접 구축 할 것인가? • 쇼핑몰 개발 • 제품 • 장바구니 • 결제연동 • 관리자 페이지 • 매출 통계 • 비동기 작업/작업 스케쥴링 • AWS를 통한 서비스 • ElasticBeanstalk • S3/CloudFront • Appendix. • 메일링 • 버그트레킹 • 측정 및 분석
6. Pros • 차별화된 UI/UX 제공 가능 • 자유도 높은 프로모션/이벤트 진행 가능 • 방문 고객에 대한 세밀한 분석 • 나는 PHP 가 싫다. Cons • Why reinvent the wheel? • 지속되는 유지보수 이슈
7. 제품 장바구니 결제 고객 관리자 페이지 매출 통계 비동기 작업 관리자 메일링/메세징 운영/측정 및 분석
8. 이 많은걸 언제 다 개발하나? 믿을 건 Django 뿐… The web framework for Perfectionists with deadlines. = 패키지 자체에 웹 개발에 필요한 수 많은 요소들이 기본 탑재되어 있음. 사용하기 쉬운 ORM. 풍부한 Django 관련 Third-Party 생태계.
9. • 제품에 딸린 정보가 생각보다 많음 • 고객 side, 물류 side, 관리자 side에서 필요한 정보를 모두 합하면 30개 이상의 attribute 필요 • 하나의 Model에 모두 넣을 경우 유지보수 어려워 짐 • 모든 곳에서 공통적으로 참조할 만한 attribute만 핵심 Model로 남기고 Model을 분리하자.
10. • 핵심 모델의 예시 class Product(models.Model): management_code = models.CharField(max_length=10, blank=True, null=True, help_text=u"상품 관리용 코드") name = models.CharField(max_length=128, help_text=u"상품 이름") standard_price = models.IntegerField(default=0, help_text=u"정가") original_sell_price = models.IntegerField(default=0, help_text=u"기준 판매가") sell_price = models.IntegerField(default=0, help_text=u"현재 판매가") original_cost = models.IntegerField(default=0, help_text=u"기준 제조 원가/공급가액") cost = models.IntegerField(default=0, help_text=u"현재 제조 원가/공급가액") sales_count = models.IntegerField(default=0, help_text=u"총 판매 수량") current_stock = models.IntegerField(default=0, help_text=u"현재 재고 수준") safety_stock = models.IntegerField(default=30, help_text=u"안전 재고 수준") logistics_code = models.CharField(max_length=64, blank=True, null=True, help_text=u"물류센터 상품 관리 코드") is_soldout = models.IntegerField(default=SoldOutStatus.INSTOCK, choices=( (SoldOutStatus.INSTOCK, u"재고 있음"), (SoldOutStatus.TEMPORARY_SOLDOUT, u"일시 품절"), (SoldOutStatus.PERMANENT_SOLDOUT, u"영구 품절"), ), help_text=u"품절 상태")
11. • 기타 모델의 예시 • ShopProduct(고객에게 표시될 상품 상세페이지, 상품 표기 사항 등) • ShopProductThumbnail(제품 썸네일 이미지) • ShopProductReview(고객 상품 후기) • ProductStockTransaction(제품 재고 변화 기록 모델) • … • 기능적 구분에 따라 추가적인 정보를 저장하는 Model을 추가 • 각 Model은 핵심 Model(Product)를 Foreign Key로 참조
12. • 대부분의 쇼핑몰에서 카테고리 기능은 필수 • 1-depth 혹은 2-depth 정도의 복잡하지 않은 카테고리 구조를 가지는 쇼핑몰이라면 : 카테고리 정보를 일반적인 Model로 구성하고 Product 모델이 ManyToMany를 이용하여 카테고리를 참조하도록 개발 class Category(models.Model): name = models.CharField(max_length=32, help_text=u"식품 유형별 카테고리 이름") index = models.IntegerField(default=0, help_text=u"카테고리 표시 순서(모바일), 적을 수록 먼저 표시됨") class SubCategory(models.Model): category = models.ForeignKey(Category) name = models.CharField(max_length=32, help_text=u"서브 카테고리 이름") index = models.IntegerField(default=0, help_text=u"서브 카테고리 표시 순서, 적을 수록 먼저 표시됨") class ShopProduct(models.Model): categories = models.ManyToManyField(Category) sub_categories = models.ManyToManyField(SubCategory)
13. • 카테고리가 3-depth 이상 복잡한 구조를 가지는 경우 • Foreign Key로 구현하면.. : Foreign Key Hell • Django-mptt : Django ORM을 확장하여 RDBMS 상에서 계층적(Hierarchical)인 데이터를 처리 할 수 있도록 해주는 라이브러리, Django Manager를 확장하여 트리 탐색을 도와주는 Method를 제공
14. • 상품 주문을 위한 시작점 • 필요 기능 : 상품 담기, 수량 변경, 삭제, 가격 계산 기능 • Django-carton : Django 기반의 장바구니 라이브러리. Django에서 사 용자가 설계한 제품 Model을 장바구니에서 바로 사용 가능하며, 위의 기초 적인 장바구니 기능들을 지원. • Session 을 기반으로 장바구니 내용 저장
15. 추가적인 요구 사항 • 주문 총액, 장바구니 내에 담긴 상품 종류에 따른 배송비 처리 기능 구현 • 로그인 한 유저에 대해, 장바구니 내용 보존을 위해 장바구니 내용을 JSON으로 serialize 하여 DB에 저장 => 주문 완료되지 않은 장바구니 내용의 경우 서로 다른 종류의 브라우저/Device에서 로그인 했을 경우에도 내역 보존 => 고객이 장바구니에 담은 내역을 실시간으로 분석 가능 (eg. 어떤 상품을 주로 장바구니에 많이 담나?, 어떤 상품을 장바구니에 담았다가 결제하지 않나?)
16. • 개발 초기에는… PG사에서 Python SDK를 지원하지 않는 관계로… PHP SDK 코드를 보면서 1:1 Python 버전으로 포팅하여 사용 • 하지만, 우리나라 PG사 결제 연동을 직접 하는 것은..지옥의 시작 • Python SDK 지원 X, 난해한 개발 매뉴얼, 결제 서비스 특성 상 테스트 하기 어려운 환경, 카카오페이/페이코 등의 간편결제로 인한 복수의 PG 연동 필요성 등.. PG 직접 연동은 제가 해봐서 알아요… 하지마세요…
17. • 결제 기능을 개발해야 한다면… ‘아임포트’를 쓰세요. • 읽기 쉬운 API 문서 • 복수 PG사 연동 가능 • 복수의 PG사를 연동하는 경우에도 single code base로 구현 가능 • API를 통한 주문 상태 조회 / 결제 취소 가능 • Python rest client 도 있음
18. • 관리자 페이지 UI 100% 직접 구현은 힘들다. • 하지만 Django admin은 일반적으로 사용하기에는 불편함. • 목적 및 사용 대상에 따라 Django admin과 직접 제작한 UI로 이분하여 사용 • Django admin • Model의 내용을 새로 등록 하거나 검색, 수정하는 작업 • 컨텐츠 등록 작업, low-level CRUD 작업 등 • 사용 대상 : 개발자, 쇼핑몰 최종관리자[MD] 등 • 직접 제작 UI • Model 내용을 등록/수정을 빈번하게 하지는 않지만 복잡한 View logic을 가진 작업 • 사용성이 중요한 작업 • 매출 통계, 주문/배송 조회, 고객센터 문의 관리 등 • 사용 대상 : 모든 멤버
19. • Django admin • Django-grappelli : Django 기본 Admin 부족한 부분을 보완 • 좀 더 미려한 UI • 향상된 Filter 기능 • jQuery 기반의 Date Picker 등 편리한 Widget 탑재 • Foreign key 자동완성 기능
20. • Django admin • Django-summernote : Summernote의 Django Add-on • 이벤트, 공지사항, 제품 상세페이지 등 쇼핑몰 많은 부분에 HTML 편집이 필요 => 하지만 쇼핑몰 관리 담당자는 HTML을 사용하지 못함 • WYSIWYG : What You See Is What You Get • WYSIWYG 에디터인 Summernote를 Django Admin 에 손쉽게 통합 가능
21. • Django admin • Django Form Assets • 사용자 정의 CSS/JS 파일을 Admin Form 에 삽입 하는 기능 • 일부 UI 개선 • Javascript 를 이용한 추가 기능 삽입 class MainCategoryBestProductForm(forms.ModelForm): class Meta: model = MainCategoryBestProduct fields = ('__all__') class Media: css = { 'all': ('css/admin.css',) }
22. • 직접 제작 UI • AdminLTE • Bootstrap 기반 관리자 페이지용 무료 템플릿 • Bootstrap 마크업을 그대로 사용 해도 예쁜 관리자 페이지를 제작 할 수 있습니다. • Chart, Date Picker, Slider 등 관리자 페이지에 필요한 요소들을 기본 탑재
23. • Django Aggregation • .annotate(), .extra(), .aggregate() 등을 조합하여 사용하면 꽤 복잡한 SQL 구문도 Django ORM을 통해 개발 가능 함. • ORM으로 구현하기에 너무 복잡한 일부 join 구문에 대해서는 .raw() method를 사용하여 직접 raw SQL을 실행하도록 함.
24. • Django-cacheops • Django Queryset에 대한 실행 결과를 Redis에 쉽게 caching 할 수 있는 라이브러리 • 변할 여지가 적고, 자주 통계 기능에서 Access 되는 Queryset들을 Caching. if "cacheops" in settings.INSTALLED_APPS: monthly_sales_aggregation = orders.values('month').annotate(Sum('order_sum'), Count('id')).order_by('month').cache(timeout=60*60) else: monthly_sales_aggregation = orders.values('month').annotate(Sum('order_sum'), Count('id')).order_by('month')
25. • Google Chart • HTML/SVG 기반의 차트를 표시하는 라이브러리 • 폭넓은 차트 종류 지원 • 커스텀 가능한 다양한 옵션 지원 • 매출 담당자의 요구에 따라서 다양한 형태의 그래프로 출력
26. • 쇼핑몰에서 왜 비동기 작업이 필요할까? • 고객의 액션(주문완료 등)과 함께 작업이 실행되어야 하나 그 작업이 사용자 경험에 해로운 Blocking을 유발할 우 려가 있는 작업들 (eg. 외부 API와의 I/O 작업이 필요한 Email/SMS/카카오톡 발송) • 실행 시간이 긴 작업 (eg. 회원 대상 대량 SMS 발송, 넓은 기간 범위에 대한 관리자의 매출 통계 조회) • 쇼핑몰에서 왜 작업 스케쥴링이 필요 할까? • 일정 주기마다 자동으로 실행되어야 하는 작업들 (eg. 매일 자정 멤버 대상 매출 통계 메일 발송, 물류 센터 API로 부터 운송장 가져오기, 회원 휴면 계정 처리, 회원 등급 평가)
27. • Celery • Python에서 가장 유명한 분산형 비동기 작업 Worker 패키지 • Celery가 제공하는 decorator 기능을 사용하면 Django 코드와 유연하게 통합 가능 • Task 부하가 늘어 날 경우 Worker를 손쉽게 확장 가능
28. • Celery • Decorator를 이용한 task 등록 예시 • Celery에 등록된 task를 비동기로 실행하는 예시 from celery import Celery app = Celery('intake-async') app.config_from_object('django.conf:settings') app.autodiscover_tasks(lambda: settings.INSTALLED_APPS) @app.task def expire_coupon(): """ 관리자가 요청 할 경우 사용기간이 지난 쿠폰을 만료 처리함 “”” for c in CouponModel.objects.filter(status=COUPON_STATUS.ISSUED, expiration_date__isnull=False): c.expire_coupon() from async.celery import expire_coupon expire_coupon.delay()
29. • Celerybeat : Celery에 내장된 작업 스케쥴러 • 다양한 방식으로 schedule을 지정 가능 • 설정 예시(Django settings.py 에 통합 ) CELERYBEAT_SCHEDULE = { # 매일 밤 11시 55분 매출 통계 메일링 발송 'daily_sales_stats': { 'task': 'emailer.celery.sales_stat', 'schedule': crontab(minute=55, hour=23) }, # 매주 수요일 마다 장바구니에 담기만 하고 구매하지 않은 고객에게 프로모션 메일 발송 'cart_promotion': { 'task': 'emailer.celery.send_cart_email', 'schedule': crontab(minute=5, hour=15, day_of_week='wednesday') }, }
30. • Celery Flower • 비동기/분산형으로 동작하는 Celery의 특성 상 모니터링의 어려움 발생 • Celery Monitoring Tool • Celery Task의 실행 결과와 Celery Worker를 Web UI를 통해서 모니터링 가능
31. • 서비스 초창기에는 국내 호스팅/IDC를 사용 하였습니다만… • 점점 더 늘어만 가는 서버 유지보수 부담 • 소규모 개발팀을 위한 DevOps에 있어서 클라우드는 필수적인 선택
32. • 난 그냥 Django 서비스를 올리고 싶을 뿐인데.. AWS가 너무 어렵다면…. • 개발된 코드를 업로드 하기만 하면 아래와 같은 AWS상의 리소스를 자동으로 생성하고 서비스 가능한 상태 로 서로 연결 시켜줌. • AWS EC2 : 서버 인스턴스 • AWS ELB : 로드밸런서 • AWS VPC/Security Group : Private Cloud 네트워크 및 보안 방화벽 설정 • Autoscaling Group : 서비스 부하에 따른 자동화된 Autoscaling • AWS RDS : Managed RDBMS(MySQL/PostgreSQL) • AWS Cloud Watch/SNS : 인프라 관련 지표/알림 서비스
33. • 개발언어/버전에 따라 일종의 Template을 제공 • Nginx, Apache / Gunicorn, uWSGI 등 Python/Django 서비스를 위한 서비스 스택을 자동으로 구성 • requirements.txt 에 따른 project dependency 자동 설치 • GUI 기반의 다양한 설정 기능 : Auto-Scaling, Load Balancing 등.
34. • 간편한 배포/무중단 배포 기능 • 압축파일 업로드를 통한 배포 • git push 혹은 CLI 를 통한 배포
35. Apache / Nginx Django App WSGI / uWSGI Static File Directory (img, js, css…) • 일반적인 Django App 서비스 Stack • Collect static을 하는 이유 : 일반적으로 static file의 경우 Apache/Nginx 등의 웹서버가 제공하는 것이 더 좋은 퍼포먼스를 보장함.
36. • 쇼핑몰은 특히 용량이 크고 많은 이미지 파일을 사용하기 때문에 Static File에 많은 신경을 써야 합니다. (상품 썸네일, 긴 상품 상세페이지 등) • AWS S3 : AWS에서 제공하는 내구도 높은 Static file 저장 서비스 • Static file 제공 기능을 웹 서버에서 완전히 분리하여 더욱 빠르고 내구도 높은 AWS S3가 Static file을 Serving 하도록 변경 • Django-storages : Django의 Static/Media 파일을 AWS S3상에 저장 할 수 있도록 해주는 Django Storage Backed 라이브러리(Azure, Google Cloud 등도 가능)
37. Apache / Nginx Django App WSGI / uWSGI AWS S3 (img, js, css…) • Django-storage를 이용한 AWS S3 사용 • Apache/Nginx 대신 AWS S3가 Static File Serving • collectstatic 을 할 경우 static file이 AWS S3 bucket으로 저장됨
38. • Static File - 더 빠르고, 더 안정적으로 제공하고 싶다면.. • AWS CloudFront : AWS에서 제공하는 CDN 서비스 • 48개 도시/79개 Location을 통한 지리적 Caching • S3만으로 서비스하는 것보다 많은 경우에 비용 효율적 • 무료 HTTPS 인증서 적용, 커스텀 도메인 적용 가능 • 다양한 Caching 정책을 활용하여 Django가 생성하는 컨텐츠 일부에 대해서도 Caching 가능 (eg. 브랜드 소개페이지 등 장시간 변화가 없는 페이지)
39. Apache / Nginx Django App WSGI / uWSGI AWS S3 (img, js, css…) • AWS S3+CloudFront 사용 AWS Cloud Front • Django에 의해 동적으로 생성되어야 하는 리소스(eg. 로그인, 세션 데이터 등)를 제외하고 웹페이지와 S3상의 Static File을 모두 CloudFront에 캐싱
40. • MailChimp • Email 발송 기능의 경우 직접 개발 시 생각보다 많은 난관이 존재 합니다. (Email Blacklist/Whitelist 처리 등) • 전 세계적으로 가장 성공적인 이메일 마케팅 서비스 • Webhook, REST API, Python SDK 지원 • 전자 상거래 통합 기능으로 고객의 장바구니/구매내역에 기반한 상세한 고객 타게팅 메일링 가능
41. • Sentry • 실시간 버그 트레킹 도구 • 오류 발생 시 Stacktrace 를 포함한 상세한 버그 레포팅을 제공 • 자체 서버 구축(무료)/호스팅 서비스(유료) • Django logger에 손쉽게 통합됨 • 이메일, 슬랙 등을 통한 알림 기능
42. • Google Analytics • 방문자 유입 경로, 행동 분석 도구 • Google Analytics Ecommerce Plugin : 쇼핑몰에 반드시 적용 해야함! • 제품별 매출 실적 • 쇼핑 행동 분석 • 결제 단계별 이탈률 분석 (제품 상세페이지 -> 장바구니 -> 결제 시작 -> 결제 완료)


반응형