⭐️ SEMES 기업 연계 프로젝트
⭐️ SSAFY 자율 프로젝트 2위 수상(148개 팀 中)
SEMAI
는 크게 네 가지 주요 기능을 탑재한 프로그램이다.- 이미지 기반 OHT 휠(wheel) 볼트 이상 진단 기능
- 전이학습 기능
- 레포트 기능
- AI 분석 기능
- OHT란?
- Overhead Hoist Transport의 약자로, 반도체 공장에서 천장 레일을 통해 반도체 소재를 옮기는 장비이다.
- 삼성전자 P1라인에만 1850대의 OHT가 가동되고 있다(관련 기사).
- OHT와 OHT 휠
* 보안 문제로 README에서 실제 휠 및 볼트 사진은 사용이 불가.
- SEMAI의 필요성
- OHT 휠에 대한 정확하고 효율적인 점검을 위해 데이터 기반 OHT 휠 볼트 사전 이상 예방 시스템의 필요성이 대두되었다.
* 각 기능의 개발 상세 내용은 ai, backend, frontend 폴더 내에서 확인 가능.
-
휠 이미지가 input으로 들어오면 휠 내 볼트를 탐지하여 볼트 이미지를 추출하고, 추출된 이미지들을 분류 모델에 넣어 정상/유실/파단/풀림을 분류한다.
-
볼트 이상 진단 시스템 구성도
① 휠 이미지가 촬영되면 해당 이미지가 Spring Boot로 전달된다.
② Spring Boot에서 Fast API로 해당 이미지에 대한 볼트 이상 진단 요청을 보낸다.
③ 볼트 이상 진단 결과를 응답한다.
④ 대시보드에 업데이트 될 데이터를 전송한다.
⑤ 최근 진단 내역을 대시보드에 업데이트한다.
⑥ 최근 진단 내역을 사용자가 확인한다.
- SEMAI가 동작하며 쌓이는 클래스별(정상/유실/파단/풀림) 볼트 데이터를 가지고 전이학습을 수행하는 기능이다.
- 전이학습 시스템 구성도
① 전이학습 페이지로 이동한다.
② 전이학습에 사용할 이미지 선택 및 학습 하이퍼파라미터를 설정한다.
③ 전이학습을 요청한다.
④ 전이학습을 진행시킨다.
⑤ 전이학습 완료 후 결과를 반환한다.
⑥ 전이학습 결과를 반환한다.
⑦ 전이학습 결과 알림을 띄운다.
⑧ 전이학습 결과 알림을 확인한다.
- 볼트 이상 진단 기록을 자세히 확인할 수 있다.
- 검사 기간 설정, 정렬 등으로 원하는 기록만 추출할 수 있고, CSV 파일로 기록을 다운로드 할 수 있다.
- 레포트 시스템 구성도
① 레포트 페이지로 이동한다.
② 볼트 이상 진단 결과 데이터를 조회한다.
③ 볼트 이상 진단 결과 데이터를 요청한다.
④ 볼트 이상 진단 결과 데이터를 반환한다.
⑤ 사용자가 조회한 내역을 보여준다.
⑥ 사용자가 조회한 내역을 확인한다.
- 당원 누적 이상 볼트 개수가 정상 범주를 벗어난 이상(anomaly) 휠의 리스트를 확인할 수 있다.
- 최근 52주 불량 볼트 데이터를 바탕으로 예측된 차주 교체 예상 휠 개수를 확인할 수 있다.
- AI 분석 시스템 구성도
① AI 분석 페이지로 이동한다.
② 이상 위험 휠, 차주 교체 예상 휠 데이터를 요청한다.
③ 이상 위험 휠, 차주 교체 예상 휠 데이터를 반환한다.
④ 이상 위험 휠 및 차주 교체 예상 휠 개수, 이상 위험 휠 표 및 이상 볼트 개수 3차원 그래프를 보여준다.
⑤ AI 분석 결과를 확인한다.
📌 커밋 메시지 컨벤션
🐛 [BE] 레포트 디테일 데이터 수정 S08P31A301-652 깃모지 - [파트] - 내용 - 이슈 번호
- 팀원과의 소통
- 편리하게 과거 추적 가능
- 나중에 실무에서 익숙해지기 위해
- 추적 가능하게 유지해주기
- 너무 많은 문제를 한 커밋에 담으면 추적하기 어렵다.
- 쌍따옴표를 닫지 말고 개행하며 작성 → 다 작성한 후에 쌍따옴표를 닫으면 작성 완료
git commit -m "FEAT: 회원가입 기능 추가
- 회원가입 기능 추가"
-
커밋 유형은 깃모지로 대체
커밋 타입 의미 ✨ 새로운 기능에 대한 커밋 🐛 버그 수정에 대한 커밋 💄 CSS 등 사용자 UI 디자인 변경 ♻️ 코드 리팩토링에 대한 커밋 🎨 스타일 (코드 형식 변경: 비즈니스 로직에 변경 없음) 📝 문서 추가, 수정에 대한 커밋 🔨 빌드 관련 파일 수정에 대한 커밋 🚚 파일 혹은 폴더명을 수정하거나 옮기는 작업만인 경우 🔥 파일을 삭제하는 작업만 수행한 경우 🚀 CI 관련 설정, 수정에 대한 커밋 💬 필요한 주석 추가 및 변경 🔀 브랜치 합병
- 커밋 유형 이후 제목과 본문은 한글로 작성하여 내용이 잘 전달될 수 있도록 할 것
- 본문에는 변경한 내용과 이유 설명 (어떻게 보다는 무엇 & 왜를 설명)
📌 git flow
작업하는 동안 default branch는 develop.
✅ pr 날릴 때 어디로 날리는 건지 꼭 체크하기!
main은 모든 작업이 끝난 후 develop에서 merge 시킨다. —————————————————————————
- main - 초기 세팅 존재
- develop - local 작업 완료 후 merge 브랜치
- feature지라 이슈 번호 - 작업 브렌치
- local/feature-지라 이슈 번호 - 각자의 기능 추가 브랜치 → ex) feature-S08P31A301-652
—————————————————————————
local - feature
에서 각자 기능 작업- 작업 완료 후
remote - develop
에 PR - 코드 리뷰 후 Confirm 받고 Merge
- remote - develop 에 Merge 될 때 마다 모든 팀원 remote - develop pull 받아 최신 상태 유지
main → develop → feature/내용, fix/내용, refactor/내용
📌 FrontEnd
- components 이름은 Pascal Case로 작성한다.
- Non-components 이름은 Camel Case로 작성한다.
- null 또는 undefined일 수 있는 값은 optional chaining 연산자 (?.)를 사용한다.
- 유틸리티 파일을 만들어 중복된 코드를 피한다.
- Presentational 컴포넌트와 Container 컴포넌트를 분리하여 사용한다.
- 고차 컴포넌트(Higher Order Components, HOC)는 적절하게 사용한다.
- JS, test, css로 파일을 분리한다.
- 불필요한 주석을 사용하지 않는다.
- 현재 화면보다 긴 코드는 더 작은 단위의 코드로 리팩토링 한다.
- 주석 처리된 코드는 커밋하지 말고 삭제한다.
- class component가 아닌 function component를 사용한다.
- JSX 문법을 사용한다.
- spread 연산자를 사용한다.
- 구조 분해 할당을 사용한다. let과 const만 사용한다. (var 사용금지)
- 되도록 화살표 함수를 사용한다.
- 직접 null을 체크하기 보다 optional chaining 연산자 (?.)를 사용한다.
- 테스트를 작성한다.
- 적정 수준의 테스트 커버리지를 유지한다.
- 하나의 테스트 파일에서 하나만 테스트 한다.
- 테스트 코드안에서 로직을 사용하지 않는다.
- 테스트 클래스는 하나의 클래스만 테스트 한다.
- 네트워크, 데이터 베이스와 직접 통신하지말고 가짜 함수를 사용한다.
- inline css를 사용하지 않는다.
- 명명 규칙을 지킨다.
📌 BackEnd
문자열을 처리할 때는 쌍따옴표를 사용하도록 합니다.
문장이 종료될 때는 세미콜론을 붙여줍니다.
🐫 함수명, 변수명은 카멜케이스로 작성합니다.
🥙 URL, 파일명은 케밥케이스로 작성합니다.
☝ 가독성을 위해 한 줄에 하나의 문장만 작성합니다.
주석은 설명하려는 구문에 맞춰 들여쓰기 합니다.
// Good
function someFunction() {
...
// statement에 관한 주석
statements
}
연산자 사이에는 공백을 추가하여 가독성을 높입니다
a+b+c+d // bad
a + b + c + d // good
☝ 콤마 다음에 값이 올 경우 공백을 추가하여 가독성을 높입니다.
var arr = [1,2,3,4]; //bad
var arr = [1, 2, 3, 4]; //good
🔠 생성자 함수명의 맨 앞글자는 대문자로 합니다.
function Person(){}
🔠 ENUM이나 상수는 대문자로 합니다.
NORMAL_STATUS = 10;
🔠 함수명은 소문자로 시작하고 동사로 합니다.
function getUserId(){}
- 패키지는 목적별로 묶는다.
- common(공통기능 관련 패키지), user(User 관련 패키지), coupon(쿠폰 관련 패키지)
- Controller에서는 최대한 어떤 Service를 호출할지 결정하는 역할과 Exception처리만을 담당하자.
- Controller 단에서 로직을 구현하는 것을 지양한다.
- 하나의 메소드와 클래스는 하나의 목적을 두게 만든다.
- 하나의 메소드 안에서 한가지 일만 해야한다.
- 하나의 클래스 안에서는 같은 목적을 둔 코드들의 집합이여야한다.
- 메소드와 클래스는 최대한 작게 만든다.
- 메소드와 클래스가 커진다면 하나의 클래스나 메소드 안에서 여러 동작을 하고 있을 확률이 크다.
- 수많은 책임을 떠안은 클래스를 피한다. 큰 클래스 몇 개가 아니라 작은 클래스 여럿으로 이뤄진 시스템이 더욱 바람직하다.
- 클래스 나누는 것을 두려워하지 말자.
- 도메인 서비스를 만들어지는 것을 피하자.
- User라는 도메인이 있을 때, UserService로 만드는 것을 피한다.
- 이렇게 도메인 네이밍을 딴 서비스가 만들어지면 자연스레 수많은 책임을 떠안은 큰 클래스로 발전될 가능성이 높다.
- 기능 별로 세분화해서 만들어보자. (UserRegisterService, UserEmailService 등...)
- 에러 검출(try - catch)
- 최상단에서 에러 검출 하기
- ex) 컨트롤러 서비스 DAO가 있으면 컨트롤러에서 try -catch문 작성
-
컨트롤러 클래스 안에서 메서드 명을 작성 할 때는 아래와 같은 접미사를 붙인다.
메서드명 의미 orderList() 목록 조회 유형의 서비스 orderDetails() 단 건 상세 조회 유형의 controller 메서드 orderSave() 등록/수정/삭제 가 동시에 일어나는 유형의 controller 메서드 orderAdd() 등록만 하는 유형의 controller 메서드 orderModify() 수정만 하는 유형의 controller 메서드 orderRemove() 삭제만 하는 유형의 controller 메서드
-
서비스 클래스 안에서 메서드 명을 작성 할 때는 아래와 같은 접두사를 붙인다.
메서드명 의미 findOrder() 조회 유형의 service 메서드 addOrder() 등록 유형의 service 메서드 modifyOrder() 변경 유형의 service 메서드 removeOrder() 삭제 유형의 service 메서드 saveOrder() 등록/수정/삭제 가 동시에 일어나는 유형의 service 메서드
-
Mapper 클래스 안에서 메서드 명을 작성 할 때는 아래와 같은 접두사를 붙인다.
메서드명 의미 selectOrder() 조회 유형의 mapper 메서드 insertOrder() 등록 유형의 mapper 메서드 updateOrder() 변경 유형의 mapper 메서드 deleteOrder() 삭제 유형의 mapper 메서드
📌 DB 컨벤션
ex.)
- 두 개 이상의 단어를 조합해서 쓸 때는 카멜케이스로 쓴다.
- 한 단어일때는 소문자로 적는다.
1. idx
idx는 테이블명_idx로 하도록 한다.
2. 예약어는 칼럼명으로 사용하지 않는다.
ex) 난이도 테이블의 값 : value = X
3.이분법으로 나눠지는 값은 is‘_‘사용
📌 명명 규칙의 중요성
데이터 구조는 어플리케이션 코드보다 훨씬 지속력이 높다. 잘 정의된 데이터 구조와 테이블 레이아웃은 어떠한 어플리케이션에서도 사용되어질 수 있다. 즉, 데이터 구조는 한번 잘 짜 놓든 아니든 영향력이 오래간다.
한번 컬럼이나 테이블 이름을 정해 놓으면 어플리케이션에서는 그 이름을 코딩으로 사용한다. 만약 컬럼과 테이블의 이름이 변경된다면 의존하고 있던 어플리케이션에서도 수정이 일어나야 한다.
이름이 잘 정의된 테이블, 뷰, 컬럼이 있다면 본인 뿐만 아니라 다른 개발자들도 데이터베이스의 구조를 이해하는데 짧은 시간이 소모될 것이다.