본문 바로가기

삶/프로젝트 회고록

Close To You (시각장애인을 위한 AIoT 옷장과 의류 관리 PWA 애플리케이션)

나의 첫 번째 프로젝트 회고록 대상으로 당첨된 🎉공통 PJT 🎉 의 회고록을 써보려고 한다.

삼성 청년 소프트웨어 아카데미(이하 싸피)라는 곳에서 진행한 프로젝트인데,

간략하게 싸피에 대해서 이야기하자면 1학기엔 교육, 2학기엔 3번의 자기 주도형 프로젝트를 진행한다.

3번의 프로젝트에는 공통, 특화, 자율이라는 이름이 붙여져 있고, 오늘 쓸 프로젝트는 이 중 첫 번째 프로젝트인 공통 프로젝트이다.

 

싸피에 대해 더 자세히 알고 싶다면

https://sh-tg.tistory.com/1

 

싸피(SSAFY) 11기 합격(최초합) 후기

사실 이 글은 합격 소식을 접한 직후부터 쓰기 시작한 글인데 시간이 없어서 매번 제대로 완성을 하지 못했다.최대한 자세하게 작성하고 싶었지만, 기억이 희미해져서 작성하지 못한 내용도 있

sh-tg.tistory.com

https://sh-tg.tistory.com/14

 

[SSAFY 11기] 1년 동안 대전에서 싸피 해본 후기

이 글은 싸피의 입과를 앞두고 있는 사람(특히 대전 캠퍼스)에게 유용할 수 있는 정보 전달의 목적도 있지만,80% 이상 개인적인 감상과 느낌을 포함한 나만의 기록이 될 것 같다는 것을 먼저 이야

sh-tg.tistory.com

두 포스팅을 참고하길!

 

이 프로젝트를 시작으로 학부 때 했던 프로젝트, 싸피의 나머지 프로젝트 특화, 자율 프로젝트 회고록도 쓸 예정이다.


프로젝트 개요

내 포트폴리오에 있는 프로젝트 표지

위 사진에 나와있듯, 

 

시각장애인의 옷 관리와 착용의 어려움 해결하기 위한 MaskRCNN 모델을 활용한 온디바이스 AI 옷장과
리액트 기반 PWA 애플리케이션을 개발한 프로젝트이다.

 

프로젝트 이름은 "당신에게 가까이"라는 의미로 Close To You라고 지었다.

시각장애인을 위한 프로젝트를 진행하다 보니 시각장애인 분들을 꽤 만나게 되었는데

의식주 중 하나이자 그들의 삶에 가까이 닿아있는 "옷"을 다루는 프로젝트이기 때문에 이렇게 짓게 되었다.

 

기간: 2024.07.01 - 08.16
참여 인원: 6명 (프론트 2, 프론트 + AI 1, 백엔드 + IoT 2, 백엔드 1)
맡은 역할: 팀장, 프론트엔드, AI
기술 스택: React, Javascript, Zustand, Vite, Emotion, Prettier, Eslint

 

 

 

팀 빌딩

공통 프로젝트의 팀 빌딩은 배정된 반 안에서 할 수 있기 때문에 모두 자기소개를 한 후에 컨택해서 6명씩 팀을 만든다.

하지만 자기소개 이전에 1학기 때 알던 인맥으로 미리 팀을 구하는 일이 많다.

나 역시 1학기 때 같은 반이었던 3명의 사람들과 같이 팀을 하자고 했고,

백엔드 2명, 프론트 백엔드 고민 중인 친구 1명, 프론트인 나 1명이 팀이 되었다.

전공자 중에서도 다들 열심히 하고, 잘하는 친구들이었기 때문에 나머지 2명 구하는 일이야 누워서 떡 먹기 일 줄 알았다.

 

MM(싸피 메신저)에 자신만만하게 올렸던 구인글

 

감사하게도 한 분이 연락을 주셔서 합류하게 되었고, 나머지 1명은 구하지 못한 채 자기소개 시간이 되었다.

 

나의 자기소개 장표

 

나는 이렇게 할 수 있는 기술, 어떤 사람인지 등으로 자기소개를 구성했고 당시에 있었던 포트폴리오(노션)를 QR 코드로 볼 수 있게 했다.

 

열심히 어필했지만..ㅜ 싸피에선 프론트가 귀한 편이라 아무도 연락이 없었다.

급하게 모든 프론트 분들에게 연락을 돌렸지만 모두 팀 빌딩이 되어 있었고, 결국 원래 있던 전공자 중 백엔드 하기로 한 친구가 프론트를 하고, 백엔드를 구하려고 하던 찰나..!

 

우리 프로젝트가 AIoT가 된 이유

 

한 프론트 분께서 팀 빌딩이 되었지만 AIoT에 대한 미련을 놓지 못하고 AIoT 팀을 구하고 있는 것을 보았고,

우리 팀이 AIoT를 하자!라고 결정한 뒤 컨택해서 한 팀이 되었다.

 

그렇게 조금은 소란스러웠던 팀 빌딩이 끝나고 대전 유일의 AIoT 팀이 되어서 아이디에이션을 시작하게 되었다.

 

 

 

아이디에이션 + 기획

우리 팀은 아이디어가 넘치는 팀이었다.

처음에는 AIoT라는 주제와 온디바이스라는 분야가 생소해서 감이 안 잡혔는데

한 두 개씩 이야기하다 보니까 정말 샘이 솟듯이 퐁퐁 아이디어가 쏟아져 나왔다.

하루에 하나씩 6명이 생각해 오면 6개가 되는데 각자 2-3개씩 생각해 와서 아이디어가 10개, 20개가 넘어갔다.

매 팀 미팅마다 최소 10개 이상의 아이디어를 나열해서 가져갔더니 컨설턴트님과 코치님들도 놀라셨던 기억이 있다.

 

 

이것 말고도 더 있음... 쓰레기통에 들어간 아이디어들도 많이 있음...

 

하지만 이 수많은 아이디어들도 이런저런 이유 때문에 반려되고 쓰레기통으로 들어가고를 반복했다.

아이디어를 짜내고 짜내다가 더 이상 생각이 나지 않았던 나는 사회 공헌과 관련된 주제를 하고 싶다는 생각에

시각장애인 유튜버 한솔씨의 영상을 정주행 하게 되었다.

딴짓하고 싶었던 것 아님.. 

 

https://www.youtube.com/watch?v=7cmVEEWcaTM

 

바로 이 영상!!

 

영상을 보고 'open cv로 옷의 색을 검출할 수 있을 것 같고, AI로 옷 종류를 분류할 수 있을 것 같은데?'라는 생각이 들어서 "시각장애인을 위한 옷 구별 서비스"라는 아이디어를 내게 되었다.

 

초기 아이디어 기획

 

팀미팅 때 바로 컨설턴트님께 "오 좋은 것 같은데요? 정말 필요해 보여요!"라는 말로 컨펌을 받고 프로젝트를 시작하게 되었다.

 

이렇게 아이디어는 선정이 되었고, 기획을 시작했다.

하지만 우리의 이 프로젝트가 타겟층인 시각장애인 분들께 정말로 필요한가?라는 의문이 들었고,

시각 장애를 가지고 있는 분들이 겪는 어려움을 정확하게 알지 못하기 때문에 어떤 것이 불편하고,

그 불편함을 해결하기 위해 어떤 기능을 포함시켜야 할지 고민이 들었다.

그래서 여러 명의 시각장애인 또는 협회에 인터뷰를 요청하기로 했다.

 

인터뷰 질문을 정리하고 32번의 인터뷰 요청 끝에 총 10번의 인터뷰를 하게 되었다.

전화로 Zoom(온라인)으로, 수원까지 직접 방문해서 대면으로 인터뷰를 하면서 우리 프로젝트의 콘셉트와 기능의 윤곽이 잡히기 시작했다.

 

중간 발표 PPT 중 일부, 이때는 8번이었지만 추가로 2개의 인터뷰를 더 했다.

 

 

요구사항 명세서 중 일부

 

옷장과 웹 서비스(PWA 애플리케이션)를 개발하기로 했기 때문에 옷장과 웹 서비스 각각 요구사항 명세서와 기능 명세서를 작성했다.

기능명세서

 

동시에 백엔드는 ERD, 프론트엔드는 화면 설계(와이어프레임)를 구성했다.

 

와이어프레임

 

와이어프레임을 구성하면서 중요하게 생각한 것은 최대한 사용하기 쉽게! 글씨도 크게! 였다.

시각장애인이라는 사용자 특성상 그에 맞는 화면을 만들어야 한다고 생각해서 관련된 포스팅도 참고하면서 화면을 설계했다.

 

https://blog.toss.im/article/tinyquestions-disability-5

 

[사소한 질문들] 토스가 '모바일 접근성' 에 진심인 이유는? - 금융이 알고 싶을 때, 토스피드

토스는 ‘금융을 모든 사람에게 편하게 제공하겠다’는 목표를 가지고 있습니다. 때문에 접근성까지도 신경 써야 한다는 공감대는 팀 내에 어렵지 않게 형성되었습니다. 아니, 오히려 꼭 해야

blog.toss.im

 

 

 

개발

개발을 시작하면서 굉장히 바빠졌는데 그 이유는 내가 팀장 + 프론트엔드 + AI를 동시에 맡았기 때문이다.

왜 이런 짓을...

 

프론트엔드 개발 과정을 이야기하자면, 나를 제외한 두 팀원이 모두 React가 처음이었기 때문에 학습과 동시에 프로젝트를 진행했다.

프로젝트 세팅이나 기술 스택에 대해서 정할 때 나를 중심으로 정하게 됐는데 다른 팀에서 프론트엔드 프로젝트를 시작하는 법에 대해서 물어봐서 "React로 프로젝트를 시작할 때"라는 제목으로 포스팅하게 됐다.

 

https://sh-tg.tistory.com/11

 

React로 프로젝트를 시작 할 때

1. 프로젝트 구조먼저, 프로젝트의 구조부터 살펴 보겠습니다.아래의 레포지토리는 지인이 공유해준 React 프로젝트 템플릿인데, 지인에게 미리 사용, 공유해도 된다는 허락을 받았다!https://github.

sh-tg.tistory.com

 

 

이 포스팅과 내가 가지고 있는 노션 자료들로 대략적인 폴더 구조 세팅, 기술 스택 선정 등에 대해 설명해 주고 우리 프로젝트에도 적용했다.

 

결과적으로 React, Javascript, Emotion, Zustand, Vite를 사용하게 됐다.

 

React: 프론트엔드 직무에서 많이 쓰는 프레임워크이고 Next.js를 쓰기 전에 React를 먼저 써봐야 한다고 생각

Javascript: Typescript를 써보고 싶었지만 빠르게 개발하기 위해서 먼저 Javascript를 선택했다.

Emotion: 주로 tailwindCSS를 썼었지만 한 번쯤 styled-in-js 라이브러리로 스타일링을 하고 싶었다.

Zustand: Redux 보다는 가볍지만 효율적인 상태관리가 가능하다고 생각했다.

Vite: 웹팩보다 빠르고 효율적인 번들러라고 생각해서 채택했다. 웹팩 vs Vite도 곧 포스팅할 예정

 

프로젝트 세팅은 내가 했지만 아래와 같이 노션에 문서화해서 모두가 볼 수 있게 했다.

 

https://classic-molecule-29c.notion.site/2c2f61d124d34743b5ae987864fb4e05?pvs=4

 

프로젝트 세팅 | Notion

1. Vite로 React PWA 시작하기

classic-molecule-29c.notion.site

 

피그마로 와이어프레임이 아닌 본격적인 디자인을 한 후에 공통 컴포넌트 ➡ 페이지 개발 ➡ 하면서 필요한 컴포넌트 개발 ➡ API 연동 및 상태 관리 적용 순으로 개발했다.

이 개발 순서는 공통 이후로 특화, 자율 때도 동일하게 진행했다.

공통 컴포넌트를 먼저 개발하면 활용도가 높아져서 좋고, 페이지 개발을 먼저 하고 API 연동을 하면 프론트도 비교적 쉬운 화면 개발을 먼저 해서 마음이 편하고 백엔드와 속도도 맞아져서 좋았다.

 

Git 컨벤션의 경우 팀 전체에서 커밋 컨벤션을 정했고, 프론트에서는 이슈 작성 ➡ 개발 ➡ MR 작성 순으로 진행하도록 했다.

이렇게 하면 이슈를 작성하면서 개발할 내용을 파악할 수 있고, MR에서 코드 리뷰를 할 수 있어서 좋았다.

추후에 나오겠지만 이 방식도 특화, 자율 때 동일하게 적용됐고 브랜치 이름에 이슈 번호를 넣는 등 좀 더 구체적으로 진화했다.

 

노션에 작성한 담당

 

 

AI의 경우엔 AIhub에 있는 의류 데이터를 활용했다.

 

https://www.aihub.or.kr/aihubdata/data/view.do?currMenu=&topMenu=&aihubDataSe=data&dataSetSn=71501

 

AI-Hub

설명서 및 활용가이드 다운로드 데이터 설명서 다운로드 구축활용가이드 다운로드 {    "dataset": {         "dataset.id": 4168,         "dataset.name": "01_sou_000834_004168_wear_02top_04shirt_woman",       

www.aihub.or.kr

https://www.aihub.or.kr/aihubdata/data/view.do?currMenu=&topMenu=&aihubDataSe=data&dataSetSn=71445

 

AI-Hub

샘플 데이터 ? ※샘플데이터는 데이터의 이해를 돕기 위해 별도로 가공하여 제공하는 정보로써 원본 데이터와 차이가 있을 수 있으며, 데이터에 따라서 민감한 정보는 일부 마스킹(*) 처리가 되

www.aihub.or.kr

 

AIhub 사이트에서 MaskRCNN 모델을 사용했다고 해서 그대로 활용했으나 동일한 방식은 아니었고 별도의 오픈 소스를 사용했다.

 

https://mmdetection.readthedocs.io/en/latest/overview.html

 

MMdetection이라는 오픈 소스였는데 MaskRCNN을 포함해 object detection, instance segmentation, panoptic segmentation method를 사용할 수 있는 toolbox였다.

 

아쉽게도 논문을 읽고 리뷰할 시간은 없었는데 아래 블로그에서 잘 설명해 줘서 도움이 됐다.

 

https://herbwood.tistory.com/20

 

Mask R-CNN 논문(Mask R-CNN) 리뷰

이번 포스팅에서는 Mask R-CNN 논문(Mask R-CNN)을 읽고 리뷰해보도록 하겠습니다. Mask R-CNN은 일반적으로detection task보다는 instance segmentation task에서 주로 사용됩니다. Segmentation 논문을 읽어본 경험이

herbwood.tistory.com

 

 

AI는 나의 담당이었지만 혼자 담당하니까 혹시 나에게 불의의 사고가 생겨서 싸피를 못 나오게 되면 어쩌지?!라는 걱정이 들어서 노션에 방법, 순서, 코드 등 최대한 꼼꼼하게 작성했다.

확신의 N의 망상... 바람이었을지도...

 

한 단계 할 때마다 공용 노션에 기록함

 

뒤에 이야기하겠지만 실제로 프로젝트 끝물에 나의 망상이 실제로 일어날 뻔 한적 있다.

 

 

문제 발생 🚨🚨

 

열심히 그리고 정신없이 프론트, AI 개발을 동시에 하고 있는데 이놈의 모델 훈련이 너무 오래 걸리는 것이 아닌가..?!

AIhub에서 다운로드한 데이터는 무려  옷 종류 10만 개, 옷 패턴 7만 개 총 17만 개 (과정 중간에 파일 이름이 이상하거나 내용이 누락된 파일 등을 제외하고 약 13만 개)가 되었기 때문에 학습 시간이 오래 걸렸다. 

이대로라면 프로젝트가 끝날 때까지 학습만 시켜야 할 것 같다는 생각이 들었는데...............................

 

결국 10만 개가 넘는 데이터를 학습시키겠다는 나의 욕심은 조금 내려놓고 코치님의 조언을 받아서 옷 종류 1.3만 개, 옷 패턴 8천 개로 최적화된 데이터 셋으로 진행했다.

하나의 클래스당 천 개씩 선정했는데 성능이 잘 안 나오면 100개씩 늘려갈 계획이었다.

AIhub 데이터 셋을 열어보니 다양한 각도로 촬영된 옷 사진과 모델이 착용한 옷 사진이 있었는데 보통 뒷모습이 잘 안 보여서 뒷모습 촬영 데이터는 제외하는 등 다시 한번 데이터를 정제하는 과정을 거쳤다.

그리고 다시 학습 데이터셋을 마련하고, 모델 학습을 시작했는데 이번에는 epoch 한 번 돌아가는데 2시간 정도? 걸렸다.

 

그리고 마주한 두 번째 문제.

학습이 잘 되고 있는 줄 알았는데 나중에 보니

loss 값이 nan으로 찍히고 있다.

Loss값이 측정되지 않고 있었다.

 

mmdetection github issue tab

 

내가 사용한 오픈 소스인 mmdetection 이슈 탭에서 검색해 보니 동일한 문제를 겪는 사람이 많았고, 댓글을 모두 참고해서 여러 가지 방법을 시도했다.

 

해결 방법은 굉장히 간단했는데 learning rate를 0.02에서 0.01로 조정했더니 해결되었다.

* 이유: loss function의 최솟값(minimum value)을 찾아가는 과정에서 진동(oscillate)하거나 오버슈트(overshoot)가 발생하고 이로 인해 backpropagation 과정에서 weight 값이 크게 변하면서 발산하게 되고, 그에 따라 loss 값도 함께 커지면서 발산하게 된다. 그래서 learning rate를 낮추면 모델이 더 안정적으로 수렴하게 되면서 해결된 것.

 

짜잔..
예쁜 loss 값 그래프

 

셔츠(종류) / 도트(패턴) / 점프수트(종류) 잘 검출 되는 것 확인

 

최종적으로 옷 종류는 94.05%, 옷 패턴 검출은 93.1%의 정확도를 달성했다.

추가적인 성능 지표는 다음과 같다. (Precision, Recall, F1 Score)

 

옷 종류 구분

       
Class  Precision  Recall  F1 Score
blouse 0.5046 0.5062 0.5054
cardigan 0.4875 0.5552 0.5192
coat 0.6194 0.5756 0.5967
jacket 0.5213 0.5777 0.5481
jumper 0.5392 0.4907 0.5138
shirt 0.6164 0.6294 0.6228
sweater 0.5525 0.4766 0.5118
t-shirt 0.4970 0.5158 0.5062
vest 0.7743 0.8257 0.7992
pants 0.8156 0.9087 0.8596
skirt 0.7860 0.8304 0.8076
dress 0.6586 0.6083 0.6324
jumpsuite 0.7708 0.6964 0.7317

 

옷 패턴 구분

       
Class  Precision  Recall F1 Score
check 0.9511 0.9262 0.9385
dot 0.9455 0.9366 0.9410
stripe 0.9060 0.8896 0.8977
plants 0.7681 0.7257 0.7463
etc 0.6406 0.7059 0.6716

 


 

그러나 또 다른 문제는 (ㅋㅋㅋㅋ...)

 

내가 이렇게 정신없이 모델 훈련을 시키는 동안 프론트엔드 개발이 너무 늦춰진 것이다.

그리고 곧 최종 발표였다는 것이다😱

그리고 최종 발표를 맡은 내가 코로나에 걸린 것이다 😱 😱

 

다들 열심히 개발 중이었다

 

이 3가지 일이 연속적으로 이뤄졌는데 그 과정은 다음과 같다.

 

1. 프론트엔드 개발이 늦어져서 최종 발표를 일주일 앞두고 밤을 새워서라도 다 구현해야겠다고 다짐을 하며 밤새워 개발했다.

2. 최종 발표를 내가 맡게 되었는데 그 이후부터 목이 살살 아픈 게 감기인가? 발표를 하려면 빨리 나아야겠다라고 생각했다.

하지만 남은 기능이 너무 많아서 쉬지 못하고 또 밤을 새웠다.

3. 다음 날 몸이 심상치 않았지만 여전히 기능이 남아있었고 다른 팀원들도 밤늦게까지 개발하고 있는 상황이었다.

4. 몸이 너무 안 좋아서 3일 밤새기는 무리다 하고 잠시 잠이 들었는데 다음 날 아침 불덩이로 눈을 뜨게 되었다.

5. 병원에 가서 "감기 때문에 왔어요."라고 말하는 순간 내가 코로나라는 것을 나도 간호사 선생님도 직감했다. (ㅠㅠ)

팀원들한테 비타민 주사라도 맞고 가겠다고 했는데 코로나 양성 확인서를 들고 다시 집으로 돌아가게 되었다.

 

최종 발표는 금요일이었고 (인생에서 3번째) 코로나는 수요일에 확진됐다.

너무 미안했지만 발표도 다른 팀원에게 넘기고 IoT를 만들던 전공자 친구가 프론트엔드 개발을 도와주게 되었다.

재택근무로 맡고 있던 프론트엔드 개발이랑 AI  코드 수정 (학습은 완료됐지만 IoT에 맞춰서 코드를 수정해야 할 부분이 있었다)을 하게 됐다.

 

발표 당일 새벽 5시까지 개발과 PPT 제작, UCC 제작에 힘쓴 결과 겨우 마무리하고 최종 발표를 시작하게 되었다.

에어컨도 안 나오는 자취방에서 UCC 찍느라 고생한 팀원들... 미친 듯이 기능 찍어내느라 고생한 팀원들... 정말 고생했다. 팀원들이 고생하는 걸 보면서 나도 코로나에 걸려서 몸이 너무 아팠는데 MM이 울릴까 봐 노트북을 안고 잤다 깨다를 반복했다. 새벽 5시쯤 MM이 멈췄다...

 

최종 발표

발표날 다 같이 점심도 먹지 못하고 준비했다. 

IoT 팀이고 부피가 큰 옷장을 준비했기 때문에 미리 세팅을 하고 리허설을 하기 위해서였다.

다른 팀들이 배려해 줘서 점심시간 이후 첫 팀으로 순서를 배정받았다.

 

실제 옷장 사진

 

케이틀린의 공들여 만든 PPT와 비욘세(닉네임)의 멋진 발표가 있었지만 실제 시연에서 기대에 미치지 못하는 모습을 보였다.

나중에 다른 팀의 후기를 들었는데 기대에 했던 것에 비해 쏘쏘 했다는 평을 들었다..

 

그 이유는 옷장에 부착된 마이크가 주변 소음에 예상보다 민감했고, 명령어 인식이 잘 안 됐다.

몇 번의 시도 끝에 인식을 하고 옷 종류와 패턴을 잘 검출하고 옷장에서의 위치도 잘 기억했지만 버벅거리는 모습이 좋아 보이지는 않았던 것 같다.

 

멋있는 PPT 두둥

 

 

 


마무리

우여곡절도 있었고 고생했지만 우리 팀원들과 함께 할 수 있어서 좋았다.

우리도 다른 팀들도 컨설턴트님도 코치님도 기대했던 프로젝트였는데 수상을 하지 못해서 아쉬웠다.

2학기 첫 프로젝트였던 만큼 공을 많이 들이고 열정도 많이 쏟았다!

마지막에 옷장 분해 할 때 거의 눈물 날 뻔...

 

코로나 +1, 팀장 +1이라는 성과를 얻었던 공통 PJT, 오늘도 결론은

고생했다 나 자신~! (팀원들도..)

 

마무리는 회식 사진