Post

5일차 대시보드 API, UI 구현

5일차 대시보드 API, UI 구현

🎯 오늘의 목표

실시간 모니터링용 대시보드 화면 완성

  • 총 4개의 주요 지표 API 개발
  • 차트 시각화 구현 (Chart.js + Vue 3)
  • 더미 데이터 생성 및 테스트 연동

✅ 구현한 대시보드 항목

1. 설비 상태 비율 (Equipment Status Ratio)

  • API: /api/dashboard/equipment-status
  • 데이터 내용: 각 설비의 상태별 개수 (가동중, 점검중 등)
  • 쿼리 요약:
    1
    2
    3
    
    SELECT status, COUNT(*) 
    FROM equipment 
    GROUP BY status;
    

2. 제품별 작업지시 건수 (Work Order Count By Product)

  • API: /api/dashboard/work-order-count
  • 데이터 내용: 제품(productName)별로 등록된 작업지시 수
  • 쿼리 요약:
    1
    2
    3
    4
    
    SELECT p.name AS productName, COUNT(*) AS count 
    FROM work_order w 
    JOIN product p ON w.product_id = p.id 
    GROUP BY p.name;
    

3. 최근 7일간 생산 실적 (Production Trend)

  • API: /api/dashboard/production-trend
  • 데이터 내용: 최근 7일간의 일자별 생산 수량 추이
  • 쿼리 요약:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    SELECT
      DATE_FORMAT(start_time, '%Y-%m-%d') AS date,
      SUM(produced_qty) AS quantity
    FROM
      production_result
    WHERE
      start_time >= CURDATE() - INTERVAL 7 DAY
    GROUP BY
      DATE_FORMAT(start_time, '%Y-%m-%d');
    

4. 최근 7일간 불량률 (Defect Rate Trend)

  • API: /api/dashboard/defect-trend
  • 데이터 내용: 일자별 (불량 수량 / 생산 수량) * 100
  • 쿼리 요약:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    SELECT
      DATE_FORMAT(start_time, '%Y-%m-%d') AS date,
      ROUND(SUM(defective_qty) / SUM(produced_qty) * 100, 2) AS defectRate
    FROM
      production_result
    WHERE
      start_time >= CURDATE() - INTERVAL 7 DAY
    GROUP BY
      DATE_FORMAT(start_time, '%Y-%m-%d');
    


🧪 더미 데이터 생성

  • 테스트를 위해 대시보드에 사용될 데이터는 미리 production_result 테이블에 100건 이상의 더미 데이터를 삽입.
  • 생산 수량, 불량 수량, 작업 시작/종료 시점을 무작위로 설정

  • **프로시저 생성 (insert_dummy_data) ** ``` MYSQL CREATE DEFINER=root@localhost PROCEDURE insert_dummy_data() BEGIN DECLARE i INT DEFAULT 1;

    – products WHILE i <= 100 DO INSERT INTO product (name, code, spec) VALUES ( CONCAT(‘제품-‘, i), CONCAT(‘P’, LPAD(i, 4, ‘0’)), IF(i % 2 = 0, ‘완제품’, ‘반제품’) ); SET i = i + 1; END WHILE;

    SET i = 1;

    – equipments WHILE i <= 100 DO INSERT INTO equipment (name, location, status) VALUES ( CONCAT(‘설비-‘, i), CONCAT(‘E’, LPAD(i, 4, ‘0’)), IF(i % 2 = 0, ‘사용’, ‘미사용’) ); SET i = i + 1; END WHILE;

    SET i = 1;

    – work_orders WHILE i <= 100 DO INSERT INTO work_order (product_id, quantity, due_date, status) VALUES ( MOD(i, 100) + 1, FLOOR(RAND() * 100) + 1, DATE_ADD(CURDATE(), INTERVAL i DAY), IF(i % 2 = 0, ‘사용’, ‘미사용’) ); SET i = i + 1; END WHILE;

    SET i = 1;

    – production_results WHILE i <= 100 DO INSERT INTO production_result (work_order_id, equipment_id, produced_qty, defective_qty) VALUES ( MOD(i, 100) + 1, MOD(i, 100) + 1, FLOOR(RAND() * 100) + 1, FLOOR(RAND() * 100) + 1 ); SET i = i + 1; END WHILE;

END

1
2
3
4
5
6
---

## 🛠️ 트러블슈팅

### 1. DTO 매핑 오류
- 오류:  

Cannot instantiate class ‘ProductionTrendDto’ it has no constructor with signature… ```

  • 원인:
    @Query에서 new dto(...) JPQL 구문 사용 시, DTO 클래스에 정확한 생성자가 없거나 필드명이 일치하지 않으면 발생.

  • 해결:

    • DTO에 명확한 생성자 추가
    • native query + @SqlResultSetMapping 방식 사용 전환

2. Chart.js에서 그래프가 그려지지 않음

  • 원인:
    • 데이터 응답은 왔으나 data.map 에러 발생 → API 응답이 배열이 아닌 경우
  • 해결:
    • 서버에서 리턴값이 List<T> 형태가 되도록 JPA 쿼리 수정
    • Vue에서는 fetch().then(res => res.json()) 후 데이터 구조 점검

3. 불량률 계산 오류

  • 문제:
    • defective_qty만 합산하고, produced_qty와 나누는 계산이 누락된 채로 화면에 출력됨.
  • 해결:
    • DB 쿼리에서 SUM(defective_qty) / SUM(produced_qty) * 100 으로 불량률 계산 추가
    • 소수점 2자리 반올림 처리

🔚 마무리

오늘은 초기 설계했던 대시보드 구현까지 초기버전을 완성했다. 더미 데이터를 만들어서 직접 API에서 활용할 쿼리를 만들고, 프론트 Vue.js와 연동하는 것이 새롭고 재밌었다. 트러블슈팅 과정이 많았지만, 그만큼 SQL → DTO 매핑, API 응답 구조, Chart.js 렌더링 등 전반적인 데이터 흐름을 제대로 이해할 수 있었다.


Frontend Repository : GitHub

Backend Repository : GitHub

This post is licensed under CC BY 4.0 by the author.