Post

7일차 전체 화면 완성, 공통 UI 리팩토링

7일차 전체 화면 완성, 공통 UI 리팩토링

🎯 오늘의 목표

설비관리, 작업지시, 생산실적 화면을 동일한 구조로 통일하고, 기능 완성하기


📁 공통 UI 리팩토링

✅ 적용 대상

  • 제품관리
  • 설비관리
  • 작업지시
  • 생산실적

✅ 공통 레이아웃 구조

  • 왼쪽: 데이터 목록
  • 오른쪽: 등록 폼

✅ 공통 기능 적용(검색, 페이징)

  • 검색 필터링 적용
  • 검색어 입력 후 filterResults() 실행 시 filteredResults 업데이트 ```js data() { return { results: [], filteredResults: [], searchProduct: ‘’, searchEquipment: ‘’ }; }, methods: { filterResults() { this.filteredResults = this.results.filter((item) => { return item.productName.includes(this.searchProduct) && item.equipmentName.includes(this.searchEquipment); }); this.currentPage = 0; // 첫 페이지로 이동 }, resetSearch() { this.searchProduct = ‘’; this.searchEquipment = ‘’; this.filteredResults = this.results; this.currentPage = 0; } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
- 페이지당 15개 항목 기준으로 페이징 처리
```js
data() {
  return {
    currentPage: 0,
    perPage: 15
  };
},
computed: {
  totalPages() {
    return Math.ceil(this.filteredResults.length / this.perPage);
  },
  paginatedData() {
    const start = this.currentPage * this.perPage;
    return this.filteredResults.slice(start, start + this.perPage);
  }
}
  • mounted시 데이터 fetch후 초기 세팅 ```js async mounted() { const res = await fetch(‘http://localhost:8080/results’); const data = await res.json(); this.results = data; this.filteredResults = data; }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

### ✅ 공통 디자인 및 스타일링
- 공통 CSS 클래스 적용
  ```css
  .form-group {
      margin-bottom: 1rem;
  }
  .btn {
      padding: 6px 12px;
      background-color: #333;
      color: white;
      border: none;
      border-radius: 4px;
      cursor: pointer;
  }
  .data-table {
      width: 100%;
      border-collapse: collapse;
  }
  .data-table th,
  .data-table td {
      border: 1px solid #ccc;
      padding: 8px;
      text-align: center;
  }
  • 날짜 출력 형식 개선 (toLocaleString()으로 시/분/초까지 출력)
  • 버튼 디자인 통일

🧩 설비관리 화면 개선

  • 설비 등록/조회 UI 공통 디자인 적용
  • equipment 테이블 설비코드(code) 컬럼 추가
    1
    
    ALTER TABLE equipment ADD COLUMN code VARCHAR(50);
    
  • Vue 등록 폼에 설비코드 입력란 추가
  • 설비명 기준 검색 기능 추가

📄 작업지시 화면 개선

✅ 기능 정리

  • 작업지시 등록/조회 UI 공통 디자인 적용
  • dueDate 필드 시간 포함 (datetime-local 입력)
  • DTO 적용 및 백엔드 연동 구조 개선

✅ 주요 이슈 해결

  • NullPointerException: JSON 필드명 불일치 (dueDate → 일치하도록 수정)
  • 시간 미포함 문제 → datetime-local 사용
1
2
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm")
private LocalDateTime dueDate;

📊 생산실적 기능 개발

✅ 실적 등록

  • 제품, 설비, 수량, 시작/종료시간 등 입력 받아 등록
  • Vue datetime-local을 사용하여 시간까지 포함된 날짜 전송
  • 연관 엔티티 조회 후 ProductionResult 저장
    1
    2
    3
    4
    5
    6
    7
    
    async submitForm() {
    await fetch('http://localhost:8080/results', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(this.form)
    });
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    
    public ProductionResult createResult(ProductionResultRequest dto) {
      WorkOrder workOrder = workOrderRepository.findById(dto.getWorkOrderId())
          .orElseThrow(() -> new IllegalArgumentException("작업지시 없음"));
      Equipment equipment = equipmentRepository.findById(dto.getEquipmentId())
          .orElseThrow(() -> new IllegalArgumentException("설비 없음"));
    
      ProductionResult result = new ProductionResult();
      result.setWorkOrder(workOrder);
      result.setEquipment(equipment);
      result.setProducedQty(dto.getQuantity());
      result.setDefectiveQty(dto.getDefectCount());
      result.setStartTime(dto.getStartTime());
      result.setEndTime(dto.getEndTime());
    
      return resultRepository.save(result);
    }
    

✅ 등록 폼 기능

1
2
<input v-model="form.startTime" type="datetime-local" required />
<input v-model="form.endTime" type="datetime-local" required />
1
2
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm")
private LocalDateTime startTime;

✅ 실적 목록 조회

  • 제품명 / 설비명으로 검색 기능 추가
  • Vue computed 속성으로 페이징 처리
  • slice 에러 해결: filteredResults 초기값 배열 보장
1
2
3
4
5
filterResults() {
  this.filteredResults = this.results.filter((item) => {
    return item.productName.includes(this.searchProduct) && item.equipmentName.includes(this.searchEquipment);
  });
}

🛠️ 트러블슈팅 기록

문제원인해결
NullPointerExceptionJSON 필드명 오타필드명 일치시키고 DTO 정비
DateTimeParseException시간 형식 누락datetime-local로 수정
Hibernate Lazy 로딩 에러Entity 직접 반환 → 프록시 직렬화 실패DTO로 응답 구조 변경
filteredResults.slice 오류초기값이 null이거나 객체배열로 초기화
400 Bad RequestDTO 매핑 불일치DTO 필드 점검 및 매핑 포맷 수정
제품명/설비명 출력 안됨Entity 자체를 반환한 응답 구조DTO에 문자열 필드로 반환 처리


🧠 오늘의 작업 결과

  • 전체 페이지 기능, 디자인 완성

제품관리

설비관리

작업지시

생산실적등록


🔚 마무리

오늘 초기에 설계한 것들이 개발을 하다 보니 추가되야하는 것들이나 수정되어야 하는 부분들이 많이 보였다. 잘 모르는 상태에서 설계를 하다 보니 확실히 초기 프로토타입의 완성도가 좋지 않았던 것 같다. 기술적으로 많은 고민을 할 수 있는 경험이 되어 뿌듯하다.

API 구조나 UI 구조나 공통 컴포넌트는 분리해서 재사용하는 방향으로 개발을 했으면 좋았을텐데, 공부를 하면서 동시에 토이 프로젝트를 진행하다보니 부족한 부분이 많은 것 같다.

오늘도 좋은 깨달음을 얻을 수 있었다,,

Frontend Repository : GitHub

Backend Repository : GitHub

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