토이프로젝트를 마치며
🎯 프로젝트 개요
- 프로젝트명 : MES (Manufacturing Execution System) 관리 시스템
- 개발 기간 : 총 10일
- 목표
- 백엔드(Spring Boot + JPA)와 프론트엔드(Vue 3)를 연계한 풀스택 개발 경험
- 개발 목적
- 실무 개발에 가까운 구조를 스스로 설계하고 구현하며 전반적인 시스템 아키텍처 이해도 향상
- API 설계, JWT 인증, Front-end 상태 관리, DB 설계, 데이터 시각화 등을 종합적으로 학습
- 도메인 선택 이유
- 개인적으로 제조업 도메인에 대한 실무 경험이 없어서, MES 시스템을 직접 구현하면서 구조와 흐름을 익히고자 선택 (설비, 제품, 작업지시, 생산실적)
📌 사용 기술 스택
| 영역 | 기술 |
|---|---|
| Frontend | Vue 3.2.13, Vue Router, Axios, Chart.js, Pinia |
| Backend | Java 17, Spring Boot 3.2.3, Spring Security, JPA, JWT |
| Database | MySQL 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 # 루트 컴포넌트
- Frontend: mes-view
📁 백엔드 디렉토리 구성 (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 설정
- Backend: mes-backend
🔐 인증 및 보안 (JWT)
- 사용자가 로그인하면, Spring Security에서 JWT 토큰을 발급
- 발급된 토큰은 Vue의 Pinia 상태(
userStore.token)에 저장- Axios 인터셉터를 통해 모든 API 요청에 Authorization : Bearer <토큰> 자동 포함토큰>
- 백엔드에서는 JwtAuthenticationFilter를 통해 토큰을 검증하고, SecurityContext에 사용자 인증 정보 저장
📊 ERD 및 데이터 흐름
📁 주요 테이블 목록
| 테이블명 | 설명 |
|---|---|
products | 제품 정보 |
equipments | 설비 정보 |
work_orders | 작업지시 정보 |
production_results | 생산 실적 |
users | 로그인 사용자 계정 |
📁 테이블 관계
product (제품) ⤷ 하나의 제품은 여러
work_order (작업지시)에 연결됨
(product_id→work_order의 외래키)equipment (설비)
⤷ 하나의 설비는 여러production_result (생산실적)에 연결됨
(equipment_id→production_result의 외래키)work_order (작업지시)
⤷ 하나의 작업지시는 하나의product에 대응
⤷ 또한, 하나의 작업지시는 여러production_result에 대응 가능
(work_order_id→production_result의 외래키)production_result (생산실적)
⤷work_order,equipment와 각각 N:1 관계
⤷ 어떤 설비에서 어떤 작업지시로 생산했는지를 기록함users (사용자)
⤷ 사용자 관리용 테이블
🔄 데이터 흐름
- 관리자는 제품과 설비를 등록함
- 등록된 정보를 기반으로 작업지시를 생성함
- 작업이 완료되면, 생산 실적을 등록함
- 대시보드는 이 데이터를 종합해 시각화함
✅ 주요 기능 및 개발 성과
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 undefined | filteredResults 초기값이 undefined | filteredResults = []로 초기값 배열 보장 |
DateTimeParseException | datetime-local 포맷과 Java LocalDateTime 불일치 | @JsonFormat 적용 + Vue input 형식 맞춤 |
400 Bad Request | DTO 필드 이름 또는 타입 불일치 | DTO 필드명/타입을 프론트와 일치시킴 |
LazyInitializationException | 엔티티 직접 반환으로 Lazy 로딩 실패 | DTO로 변환하여 응답 |
JWT 로그인 후 Header 반영 안 됨 | localStorage는 Vue 반응형 시스템 밖에 있음 | Pinia 상태관리 도입 + computed 활용 |
Token 매칭 실패 (403 Forbidden) | 비밀번호 비교 시 평문 vs 암호화 mismatch | BCrypt 기반 비밀번호 검증 적용 |
getActivePinia() was called... | createPinia()를 등록하지 않고 store 사용 | app.use(createPinia())로 정확히 등록 |
useUserStore is not a function | useUserStore를 함수처럼 호출하지 않음 | useUserStore()로 호출 방식 수정 |
Component name "Header" | ESLint 규칙 위반: 단일 단어 컴포넌트명 사용 | MainHeader로 이름 변경 |
Axios Authorization 누락 | 요청 시 토큰이 자동 헤더에 추가되지 않음 | Axios 요청 인터셉터에서 토큰 자동 주입 설정 |
🔚 마무리
이번 토이프로젝트는 Spring Boot 기반의 백엔드와 Vue 3 기반의 프론트엔드 구조를 처음부터 스스로 설계하며 개발 환경과 특성을 이해하는데 큰 도움이 되었다.
특히 보안 인증 흐름(JWT)과 상태관리(Pinia)를 직접 구현하면서 실무에서 흔히 접하는 보안 및 반응형 처리 이슈를 경험하고 해결할 수 있었다.
또한, 실시간 대시보드 구성은 처음이라 Chart.js와의 연동에서 데이터 연결이나 디자인 수정에 어려움이 있었지만, 흐름을 학습하는 좋은 계기가 되었다.
만약, 다음에 개선하게 된다면, 사용자별 권한 설정(조회만 가능, 등록/조회 가능)이나 오류를 핸들링할 수 있는 기능을 추가하고 싶다.
