💡 AI 인사이트

🤖 AI가 여기에 결과를 출력합니다...

댓글 커뮤니티

쿠팡이벤트

이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.

검색

    [코담] 웹개발·실전 프로젝트·AI까지, 파이썬·장고의 모든것을 담아낸 강의와 개발 노트

    영업 분석 대시보드용 API 만들기 | ✅저자: 이유정(박사)

    배경
    당신은 한 온라인 쇼핑몰의 백엔드 개발자입니다.
    마케팅팀이 다음과 같은 요청을 해왔습니다:

    ✅ "월별 매출 추이"와 ✅ "카테고리별 매출 합계"를 대시보드에 표시해 주세요.

    실제로는 이런 데이터를 CSV나 JSON 파일로 받아와 저장하고,
    이를 Django API로 제공하면 됩니다.

    제공된 JSON 원시 데이터 (sales_data.json)

    // sales_data.json
    [
      { "order_id": "A001", "category": "의류",     "price": 30000,  "quantity": 2, "order_date": "2024-05-10" },
      { "order_id": "A002", "category": "전자제품", "price": 150000, "quantity": 1, "order_date": "2024-05-11" },
      { "order_id": "A003", "category": "의류",     "price": 45000,  "quantity": 1, "order_date": "2024-06-01" }
    ]
    

    문제: sales/utils.py – JSON 로드 함수 완성

    import os
    import json
    from django.conf import settings
    
    def load_sales_data():
        """프로젝트 루트의 sales_data.json 파일을 읽어와 Python 객체로 반환"""
        path = os.path.join(settings.______, 'sales_data.json')
        with open(path, encoding='utf-8') as f:
            data = json.______(f)
        return data
    
    • settings.______
    • json.______

    sales/views.py – 두 개의 API 뷰 완성

    from django.http import JsonResponse
    from .utils import load_sales_data
    
    def monthly_sales(request):
        """
        월별 매출 추이 집계
        결과 예시: [
          { "month": "2024-05", "total": 210000 },
          { "month": "2024-06", "total":  45000 }
        ]
        """
        data = load_sales_data()
        result = {}   # {"2024-05": 0, "2024-06": 0, …}
    
        for item in data:
            # 1) order_date에서 앞 7글자(YYYY-MM)만 잘라 key로 사용
            month = item["____"][:7]
    
            # 2) 매출 = price * quantity
            sales = item["____"] * item["____"]
    
            # 3) 누적 계산
            if month in result:
                result[month] += sales
            else:
                result[month] = sales
    
        # 4) 최종 리스트로 변환
        response = []
        for m, total in sorted(result.items()):
            response.append({"month": m, "total": total})
    
        return JsonResponse(response, safe=____)
    
    
    def category_sales(request):
        """
        카테고리별 매출 합계 집계
        결과 예시: [
          { "category": "의류",     "total": 105000 },
          { "category": "전자제품", "total": 150000 }
        ]
        """
        data = load_sales_data()
        result = {}   # {"의류": 0, "전자제품": 0, …}
    
        for item in data:
            # 1) category
            cat = item["____"]
    
            # 2) 매출 = price * quantity
            sales = item["____"] * item["____"]
    
            # 3) 누적 계산
            if cat in result:
                result[cat] += sales
            else:
                result[cat] = sales
    
        # 4) 최종 리스트로 변환
        response = []
        for c, total in sorted(result.items()):
            response.append({"category": c, "total": total})
    
        return JsonResponse(response, safe=____)
    

    URL 연결

    from django.urls import path
    from . import views
    
    urlpatterns = [
        path('sales/monthly/',  views.monthly_sales),
        path('sales/category/', views.category_sales),
    ]
    
    • config/urls.pypath('api/', include('sales.urls')) 설정을 추가하세요.

    ✅ 정답 코드:

    # sales/utils.py
    import os
    import json
    from django.conf import settings
    
    def load_sales_data():
        """프로젝트 루트의 sales_data.json 파일을 읽어와 Python 객체로 반환"""
        path = os.path.join(settings.BASE_DIR, 'sales_data.json')
        with open(path, encoding='utf-8') as f:
            data = json.load(f)
        return data
    

    ✔️ 의사코드:

    함수 load_sales_data():
        1. 설정 객체(settings)에서 프로젝트 루트 디렉터리(BASE_DIR) 경로를 가져온다.
        2. 파일 이름 'sales_data.json'을 프로젝트 루트 경로와 결합하여 전체 파일 경로(path)를 생성한다.
        3. 해당 파일 경로(path)에 있는 파일을 UTF-8 인코딩으로 연다.
        4. 열린 파일 객체(f)를 json.load() 함수에 전달하여 JSON 문자열을 Python 객체(data)로 파싱한다.
        5. 파싱된 Python 객체(data)를 호출자에게 반환(return)한다.
    
    
    # sales/views.py
    from django.http import JsonResponse
    from .utils import load_sales_data
    
    def monthly_sales(request):
        """
        월별 매출 추이 집계
        결과 예시: [
          { "month": "2024-05", "total": 210000 },
          { "month": "2024-06", "total":  45000 }
        ]
        """
        data = load_sales_data()
        result = {}   # {"2024-05": 0, "2024-06": 0, …}
    
        for item in data:
            # 1) order_date에서 앞 7글자(YYYY-MM)만 잘라 key로 사용
            month = item["order_date"][:7]
    
            # 2) 매출 = price * quantity
            sales = item["price"] * item["quantity"]
    
            # 3) 누적 계산
            if month in result:
                result[month] += sales
            else:
                result[month] = sales
    
        # 4) 최종 리스트로 변환
        response = []
        for m, total in sorted(result.items()):
            response.append({"month": m, "total": total})
    
        return JsonResponse(response, safe=False)
    
    
    def category_sales(request):
        """
        카테고리별 매출 합계 집계
        결과 예시: [
          { "category": "의류",     "total": 105000 },
          { "category": "전자제품", "total": 150000 }
        ]
        """
        data = load_sales_data()
        result = {}   # {"의류": 0, "전자제품": 0, …}
    
        for item in data:
            # 1) category
            cat = item["category"]
    
            # 2) 매출 = price * quantity
            sales = item["price"] * item["quantity"]
    
            # 3) 누적 계산
            if cat in result:
                result[cat] += sales
            else:
                result[cat] = sales
    
        # 4) 최종 리스트로 변환
        response = []
        for c, total in sorted(result.items()):
            response.append({"category": c, "total": total})
    
        return JsonResponse(response, safe=False)
    

    ✔️의사코드:

    # monthly_sales 함수 의사코드 (문장 설명)
    
    1. 브라우저에서 요청이 들어오면, load_sales_data() 함수를 호출하여 sales_data.json 파일의 모든 주문 데이터를 Python 리스트 형태로 불러옵니다.
        
    2. 월별 매출을 저장할 빈 딕셔너리 result 를 만듭니다.
        
    3. 불러온 데이터 리스트를 하나씩 순회(for item in data:)하면서:
        
        - order_date 문자열에서 앞의 7글자(`YYYY-MM`)를 잘라 month 변수에 담습니다.
            
        - price 값에 quantity 값을 곱해 이 주문의 매출액(sales)을 계산합니다.
            
        - 만약 month 키가 이미 result 딕셔너리에 있으면, 그 값에 방금 계산한 sales 를 더해주고,  
            그렇지 않으면 month 키를 새로 만들어 sales 를 할당합니다.
            
    4. 월별로 누적된 매출이 담긴 result 딕셔너리를 키(월) 순서대로 정렬하여,
        
        - 빈 리스트 response 에 각 (month, total) 쌍을 { "month": month, "total": total } 형태의 딕셔너리로 하나씩 추가합니다.
            
    5. 완성된 response 리스트를 JsonResponse 에 담아 safe=False 옵션과 함께 반환합니다.
        
    ---
    # category_sales 함수 의사코드 (문장 설명)
    
    1. 요청이 들어오면 역시 load_sales_data() 함수를 통해 모든 주문 데이터를 불러옵니다.
        
    2. 상품별 매출을 저장할 빈 딕셔너리 result 를 만듭니다.
        
    3. 주문 하나하나를 순회하면서:
        
        - category 값을 꺼내 cat 변수에 저장합니다.
            
        - price * quantity 연산으로 해당 주문의 매출액 sales 를 계산합니다.
            
        - cat 키가 이미 result 에 있으면 그 값에 sales 를 더하고,  
            없으면 cat 키를 새로 만들어 sales 값을 할당합니다.
            
    4. 상품명 순으로 정렬된 result 아이템을 순회하며,
        
        - 빈 리스트 response 에 { "category": c, "total": total } 형태로 하나씩 추가합니다.
            
    5. 완성된 response 리스트를 JsonResponse(response, safe=False) 로 반환합니다.
    
    # sales/urls.py
    from django.urls import path
    from . import views
    
    urlpatterns = [
        path('sales/monthly/',  views.monthly_sales),
        path('sales/category/', views.category_sales),
    ]
    

    config/urls.py (프로젝트 최상위)

    from django.contrib import admin
    from django.urls import path, include
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('api/', include('sales.urls')),
    ]
    

    Insomnia 테스트

    GET http://127.0.0.1:8000/api/sales/monthly/
    GET http://127.0.0.1:8000/api/sales/category/
    

    ✅ 응답 월별 매출

    [
      {
        "month": "2024-05-01",
        "total_sales": 210000
      },
      {
        "month": "2024-06-01",
        "total_sales": 45000
      }
    ]
    

    ✅ 응답 카테고리별 매출

    [
      {
        "category": "의류",
        "total_sales": 105000
      },
      {
        "category": "전자제품",
        "total_sales": 150000
      }
    ]
    
    TOP
    preload preload