Post

토이프로젝트를 마치며

토이프로젝트를 마치며

🎯 프로젝트 개요

  • 프로젝트명 : MES (Manufacturing Execution System) 관리 시스템
  • 개발 기간 : 총 10일
  • 목표
    • 백엔드(Spring Boot + JPA)와 프론트엔드(Vue 3)를 연계한 풀스택 개발 경험
  • 개발 목적
    • 실무 개발에 가까운 구조를 스스로 설계하고 구현하며 전반적인 시스템 아키텍처 이해도 향상
    • API 설계, JWT 인증, Front-end 상태 관리, DB 설계, 데이터 시각화 등을 종합적으로 학습
  • 도메인 선택 이유
    • 개인적으로 제조업 도메인에 대한 실무 경험이 없어서, MES 시스템을 직접 구현하면서 구조와 흐름을 익히고자 선택 (설비, 제품, 작업지시, 생산실적)

📌 사용 기술 스택

영역기술
FrontendVue 3.2.13, Vue Router, Axios, Chart.js, Pinia
BackendJava 17, Spring Boot 3.2.3, Spring Security, JPA, JWT
DatabaseMySQL 8.0
버전관리GitHub (Frontend / Backend 분리)
런타임Node.js 18.16.0

📌 프로젝트 구조

📁 프론트엔드 디렉토리 구성 (mes-view)

1
2
3
4
5
6
7
src/
├── components/         # 공통 UI 컴포넌트 
├── pages/              # 각 메뉴 페이지 
├── router/             # Vue Router 설정
├── stores/             # Pinia 상태 관리 (user.js)
├── assets/             # 공통 CSS
└── App.vue             # 루트 컴포넌트

📁 백엔드 디렉토리 구성 (mes-backend)

1
2
3
4
5
6
7
8
src/
├── controller/         # REST API 컨트롤러
├── entity/             # JPA 엔티티
├── dto/                # 요청/응답 DTO
├── repository/         # JPA Repository 인터페이스
├── service/            # 비즈니스 로직
├── auth/               # JWT 인증 
└── config/             # Security 설정

🔐 인증 및 보안 (JWT)

  1. 사용자가 로그인하면, Spring Security에서 JWT 토큰을 발급
  2. 발급된 토큰은 Vue의 Pinia 상태(userStore.token)에 저장
  3. Axios 인터셉터를 통해 모든 API 요청에 Authorization : Bearer <토큰> 자동 포함
  4. 백엔드에서는 JwtAuthenticationFilter를 통해 토큰을 검증하고, SecurityContext에 사용자 인증 정보 저장

📊 ERD 및 데이터 흐름

📁 주요 테이블 목록

테이블명설명
products제품 정보
equipments설비 정보
work_orders작업지시 정보
production_results생산 실적
users로그인 사용자 계정

📁 테이블 관계

  • product (제품) ⤷ 하나의 제품은 여러 work_order (작업지시)에 연결됨
    (product_idwork_order의 외래키)

  • equipment (설비)
    ⤷ 하나의 설비는 여러 production_result (생산실적)에 연결됨
    (equipment_idproduction_result의 외래키)

  • work_order (작업지시)
    ⤷ 하나의 작업지시는 하나의 product에 대응
    ⤷ 또한, 하나의 작업지시는 여러 production_result에 대응 가능
    (work_order_idproduction_result의 외래키)

  • production_result (생산실적)
    work_order, equipment와 각각 N:1 관계
    ⤷ 어떤 설비에서 어떤 작업지시로 생산했는지를 기록함

  • users (사용자)
    ⤷ 사용자 관리용 테이블

🔄 데이터 흐름

  1. 관리자는 제품설비를 등록함
  2. 등록된 정보를 기반으로 작업지시를 생성함
  3. 작업이 완료되면, 생산 실적을 등록함
  4. 대시보드는 이 데이터를 종합해 시각화함

✅ 주요 기능 및 개발 성과

1. 제품/설비/작업지시/실적 CRUD API 설계 및 통합 구현

  • 각 도메인(Product, Equipment, WorkOrder, ProductionResult)에 대해 RESTful API 설계 및 개발
  • Spring Data JPA 기반으로 도메인별 등록 / 조회 / 수정 / 삭제 API 일괄 구현
  • 검색 조건 필터링, 페이징 처리, DTO 기반 응답 구조 정리 등 API 설계 일관성 유지
  • 공통 UI 스타일(CSS) 구성으로 전체 페이지 일관성 유지
  • 등록/조회/검색/페이징 기능 공통화

2. JWT 기반 인증 시스템 구축

  • Spring Security + JWT 토큰 기반 사용자 인증 구현
  • Vue에서는 Pinia 상태 관리와 Axios 인터셉터를 통해 토큰 자동 적용

3. 대시보드 시각화 구성 (Chart.js)

  • 제품별 작업지시 건수, 설비 상태 비율, 생산 실적 추이, 불량률 시각화 구현
  • Vue의 computed 속성으로 데이터 필터링 및 실시간 반응 처리

🛠️ 주요 트러블슈팅 정리

문제원인해결
TypeError: slice of undefinedfilteredResults 초기값이 undefinedfilteredResults = []로 초기값 배열 보장
DateTimeParseExceptiondatetime-local 포맷과 Java LocalDateTime 불일치@JsonFormat 적용 + Vue input 형식 맞춤
400 Bad RequestDTO 필드 이름 또는 타입 불일치DTO 필드명/타입을 프론트와 일치시킴
LazyInitializationException엔티티 직접 반환으로 Lazy 로딩 실패DTO로 변환하여 응답
JWT 로그인 후 Header 반영 안 됨localStorage는 Vue 반응형 시스템 밖에 있음Pinia 상태관리 도입 + computed 활용
Token 매칭 실패 (403 Forbidden)비밀번호 비교 시 평문 vs 암호화 mismatchBCrypt 기반 비밀번호 검증 적용
getActivePinia() was called...createPinia()를 등록하지 않고 store 사용app.use(createPinia())로 정확히 등록
useUserStore is not a functionuseUserStore를 함수처럼 호출하지 않음useUserStore()로 호출 방식 수정
Component name "Header"ESLint 규칙 위반: 단일 단어 컴포넌트명 사용MainHeader로 이름 변경
Axios Authorization 누락요청 시 토큰이 자동 헤더에 추가되지 않음Axios 요청 인터셉터에서 토큰 자동 주입 설정

🔚 마무리

이번 토이프로젝트는 Spring Boot 기반의 백엔드와 Vue 3 기반의 프론트엔드 구조를 처음부터 스스로 설계하며 개발 환경과 특성을 이해하는데 큰 도움이 되었다.

특히 보안 인증 흐름(JWT)과 상태관리(Pinia)를 직접 구현하면서 실무에서 흔히 접하는 보안 및 반응형 처리 이슈를 경험하고 해결할 수 있었다.

또한, 실시간 대시보드 구성은 처음이라 Chart.js와의 연동에서 데이터 연결이나 디자인 수정에 어려움이 있었지만, 흐름을 학습하는 좋은 계기가 되었다.

만약, 다음에 개선하게 된다면, 사용자별 권한 설정(조회만 가능, 등록/조회 가능)이나 오류를 핸들링할 수 있는 기능을 추가하고 싶다.

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