404

cdc wiki
이동: 둘러보기, 검색

목차

프로젝트 개요

기술개발 과제

국문 : AI 를 사용한 옷 검색 서비스

영문 : Clothing search service using AI

과제 팀명

404

지도교수

최혁 교수님

개발기간

2022년 9월 ~ 2022년 12월 (총 4개월)

구성원 소개

서울시립대학교 경제학부 | 컴퓨터과학부 20172800** 안*민 (팀장)

서울시립대학교 컴퓨터과학부 20179200** 이*영

서울시립대학교 컴퓨터과학부 20199200** 채*진

서론

개발 과제의 개요

개발 과제 요약

본 과제에선 사용자들이 보다 추상적으로, 또한 구체적으로 옷을 검색할 수 있는 서비스를 제공할 것입니다.

먼저 자신이 원하는 캐릭터가 그려진 옷이나 동식물이 표시된 옷 등 보다 구체적으로 옷을 검색하는 기능을 제공할 것입니다. 이를 통해 사용자가 자신이 원하는 옷을 정확하게 검색할 수 있도록 할 것이며, 또한 사람들이 일상생활에서 사용하는 문장으로 검색하도록 하여, 사용의 편의성을 높일 것입니다.

또한, 검색된 옷에 대해서 자연어로 피드백을 주어, 해당 피드백이 반영된 옷을 검색하는 기능을 제공할 것입니다. 이를 통해 사용자가 원하는 옷을 더 원활히 찾을 수 있도록 할 것입니다.

이러한 기능들을 이용해 기존 키워드로만 제한적으로 검색되던 쇼핑몰이 제공하지 못했던 검색의 편의성을 제공할 것이고, 결과적으로 사용자들이 옷을 더 편리하고 정확하게 검색할 수 있 도록 할 것입니다.

이를 통해 사용자들이 옷을 검색하고 스타일링하는 데 들이는 시간과 비용을 보다 줄일 수 있는 효용을 제공할 것입니다.

개발 과제 배경

1. 긍정적 패션 시장 전망

그림 1-1을 보면, 국내 패션 시장은 2022년 46조4천억 원에 이를 것으로 전망되며, 특히 2022년 세계 경제가 지속 성장이 예측되는 가운데 패션 시장 역시 완전히 회복될 것으로 예상합니다. 이는 코로나 19로 인한 보복 소비 증가와 패션기업의 온라인 채널 다각화 등에 따른 실적 상승이 원인이었습니다.

즉, 코로나 19가 점차 완화됨에 따라 의류 소비 역시 증가할 것이고, 패션 시장은 여전히 그 규모가 크면서 성장률 역시 높아질 것으로 보입니다. 결론적으로, 전체적으로 패션 관련 수요가 증가할 것으로 판단했습니다.

[그림 1-1]

Pic 1 1.png

[출처: 2022년 국내 패션 시장 6.2% 성장한 46조4천억 원 전망, https://m.fashionn.com/board/read.php?table=1004&number=39605]

2. 옷을 사고 스타일링하는 데 시간과 비용이 많이 듦


패션 관련 수요가 증가하지만, 여전히 소비자들은 옷을 구매하고 착용하면서 불편함을 겪고 있었습니다. 따라서 저희는 소비자들이 직면하고 있는 pain point를 조사했습니다. 여러 기사를 통해 저희 팀은, 자신의 취향에 맞는 옷을 찾는 데에도 많은 시간과 노력이 필요하며, 매일 옷을 코디하고 스타일링하는 데에도 어려움이 있다는 것을 확인하였습니다.

따라서 저희는 이 근원적 문제를 해결하기 위해선 사용자가 원하는 옷을 보다 추상적으로, 또는 구체적으로 옷을 검색하도록 하여, 자신이 정확히 원하는 옷을 찾을 수 있도록 하는 것이 필요하다고 생각했습니다.

3. 결론

따라서 저희 팀은 AI를 활용해 더욱더 편리하고 구체적으로 옷을 검색하는 서비스를 제공해 문제를 해결할 수 있다고 판단했고, 그러한 서비스를 만드는 것으로 주제로 선정했습니다.

◇ 개발 과제의 효과

  • 개강룩, 소개팅룩, 놀이동산룩 등 키워드를 기반으로 다양한 옷을 보다 편리하게 검색할 수 있습니다.이를 통해 고객이 원하는 옷을 찾는데 걸리는 시간과 노력을 크게 절약할 수 있습니다.
  • 미키마우스가 그려진 옷, 왕관이 들어간 옷 등 보다 추상적으로 옷을 검색함으로써, 자신이 원하는 옷을 더 상세하게 검색할 수 있습니다.
  • 검색된 옷에서 특정 요소가 추가되거나 수정, 제거된 옷을 다시 검색할 수 있는 기능을 통해, 더욱 명확하게 자신이 원하는 옷을 검색할 수 있습니다.

개발 과제의 목표 및 내용

◇ 목표 사용자층

  • 패션에 관심은 있지만, 어디서부터 시작해야 할지 모르는 사람들
  • 패션을 신경은 쓰지만, 귀찮아하는 사람들
  • 추상적으로 자신이 원하는 옷을 검색하고 싶은 사람들

◇ 개발 과제의 목표 및 세부 내용

1. 자동 키워드 추출

옷 이미지를 전달하면 해당 옷의 키워드를 자동으로 추출하는 AI 모델을 만들 것입니다.

이를 통해 옷의 키워드를 선정하는 작업을 자동화할 것이고, 추출된 키워드를 바탕으로 옷을 손쉽게 검색할 수 있는 서비스를 개발할 것입니다.

2. 텍스트 기반 옷 검색

미키마우스가 그려진 옷처럼 자신이 원하는 캐릭터가 그려진 옷을 검색하고 싶을 수 있습니다. 또한, 특정 동물이나 식물이 그려진 옷 등 구체적인 시각적 특성을 가지는 옷을 찾고 싶을 수도 있습니다. 이때 상품에 달린 설명과 검색어에 대한 관련성만을 이용하면 사용자가 원하는 검색어를 판매자가 관련 정보를 입력할 때 넣었어야 했다는 제한이 있습니다. 저희는 상품의 설명과 사용자의 검색어에 대한 관련성을 이용하는 대신 상품의 이미지가 검색어와 얼마나 관련성을 가지는지 직접 비교해서 "왕관을 쓴 미키마우스 티셔츠" 등 상품의 제목, 설명에 포함되어 있지 않을 가능성 큰 검색어에 대해서도 적절한 상품을 검색하는 기능을 제공할 것입니다.

이를 통해 사람들이 더욱 편리하게 자신이 원하는 옷을 검색할 수 있도록 할 것이며, 보다 구체적으로 원하는 옷을 찾을 수 있도록 도울 것입니다.

3. 다양한 쇼핑몰 상품 제공

다양한 쇼핑몰의 옷을 키워드로 편리하게 검색하는 기능을 제공할 것입니다.

이를 위해 여러 쇼핑몰의 데이터를 크롤링해서 데이터베이스를 구축할 것이며, 이를 통해 사용자들이 한눈에 손쉽게 다양한 쇼핑몰의 옷을 키워드 또는 추상적인 문장으로 검색할 수 있도록 할 것입니다.

4. 유저 피드백에 따른 상품 추천

사용자가 찾은 상품에서 부분적으로 추가되거나 수정하고 싶은 요소가 있으면, 자연어 피드백을 입력받아 새로운 상품을 제시하는 기능을 제공할 것입니다. 구체적인 예시로, 만일 사용자가 추천받은 옷에서 줄무늬를 추가하고 싶다면, "줄무늬가 있으면 좋겠어요" 등의 자연어 피드백을 입력받아 해당 상품에서 줄무늬가 추가된 옷을 새롭게 추천하도록 하는 기능을 구현할 것입니다.

이를 통해 사람들이 더욱 편리하게 자신이 원하는 옷을 검색할 수 있도록 할 것이며, 보다 구체적으로 원하는 옷을 찾을 수 있도록 도울 것입니다.

3. 다양한 쇼핑몰 상품 제공

다양한 쇼핑몰의 옷을 키워드로 편리하게 검색하는 기능을 제공할 것입니다.

이를 위해 여러 쇼핑몰의 데이터를 크롤링해서 데이터베이스를 구축할 것이며, 이를 통해 사용자들이 한눈에 손쉽게 다양한 쇼핑몰의 옷을 키워드 또는 추상적인 문장으로 검색할 수 있도록 할 것입니다.

4. 유저 피드백에 따른 상품 추천

사용자가 찾은 상품에서 부분적으로 추가되거나 수정하고 싶은 요소가 있으면, 자연어 피드백을 입력받아 새로운 상품을 제시하는 기능을 제공할 것입니다. 구체적인 예시로, 만일 사용자가 추천받은 옷에서 줄무늬를 추가하고 싶다면, "줄무늬가 있으면 좋겠어요" 등의 자연어 피드백을 입력받아 해당 상품에서 줄무늬가 추가된 옷을 새롭게 추천하도록 하는 기능을 구현할 것입니다.

관련 기술의 현황

관련 기술의 현황 및 분석 (State of the art)

◇ 키워드 추출 및 키워드 통한 이미지 검색

상품의 이미지와 해당 상품의 재질이 무엇인지 등의 레이블이 포함된 데이터셋은 데이터셋이 구축된 시간에 크게 의존하지 않습니다 [Liu+16, BBS10, Zou+19]. 면으로 된 티셔츠를 예를 들어 보면, 시간이 지남에 따라 다양한 스타일로 이루어진 면 티셔츠가 나오겠지만 면이라는 어느 정도 공통된 특성은 어느 정도 유지할 것이기 때문입니다.

하지만 시시각각 바뀌는 유행에 대응하는 키워드들에 대해 양질의 데이터셋을 구축하는 것은 다른 이야기입니다. 학습에 필요한 많은 양의 데이터에 레이블을 다는 중에도 유행은 계속 변할 것이고, 따라서 그 데이터셋을 이용해 학습된 모델의 효용이 오래 지속되지 않아 데이터 레이블링에 드는 비용이 실제 모델 학습에 장애물이 될 수 있습니다.

이렇게 패션에 대한 다양한 키워드에 따른 분류에는 적은 양의 데이터로도 학습할 수 있어야 한다는 요구사항을 갖습니다. 하지만 [Den+09]와 같이 개, 고양이 등의 고정된 레이블로 구성된 데이터셋에 대해 사전학습된 모델들은 다양하고 추상적인 패션 키워드들을 클래스로 포함하지 않아 적은 양의 데이터만 주어진 환경에서 사용하기에는 부족함이 있습니다. 이와 달리 [Rad+21, Jia+21]과 같이 다량의 이미지와 그에 대응하는 캡션에 대해 사전학습된 모델들은 “a photo of a dog”, “a photo of a cat” 등의 텍스트 프롬트를 적절히 구성하여 클래스 레이블에 대한 데이터가 따로 없는 zero-shot 설정에서도 사용할 수 있습니다.

[Rad+21]의 실험에서 알 수 있듯이 이미지나 그에 해당하는 프롬트가 사전학습 데이터와 다르면 다를수록 zero-shot 설정에서의 성능도 함께 떨어집니다. 따라서 “친구 결혼식에 입기 좋은 옷"과 같이 주로 추상적인 설명으로 구성되는 의류에 대한 키워드에는 일정량의 데이터가 있다고 가정되는 few-shot 설정이 적절할 것으로 생각할 수 있습니다. 가장 간단한 방법은 사전학습된 모델의 파라메터는 얼린 뒤 이미지 인코더의 최종 임베딩에 클래시피케이션 헤드를 붙여 이미지를 분류하거나, 모델의 파라메터 전체를 학습하는 방법이 있을 수 있습니다. 전자의 경우 텍스트 프롬트를 이용하지 않는 경우 이미지 클래스별 샘플 수가 적을 때 오히려 zero-shot보다 성능이 안 좋을 수 있다는 것이고 [Rad+21], 후자의 경우 [LAC21, LL21]에서 볼 수 있듯이 데이터셋 크기가 작은 경우 다양한 종류의 데이터에 대해 잘 사전학습된 모델의 파라메터를 헝클어뜨려 일반화에 악영향을 줄 수 있습니다. 게다가 전체 파라메터에 대해 모델을 여러 개 학습하는 경우 변경된 거대한 사전학습 모델을 각각 따로 서버에 올려 사용해야 한다는 단점이 있습니다.

이와 같은 문제를 완화하기 위해 CoOP [Zho+22a]은 NLP 분야의 [LAC21, LL21]과 같은 연속적인 프롬트를 모델 파라메터가 고정된 CLIP의 텍스트 인코더에 달아 이를 학습하는 방법을 제안합니다. 11개의 이미지 분류 데이터셋에서 소량의 샘플을 이용해 실험했을 때 사람이 직접 만든 프롬트들에 비해 높은 정확도를 보였습니다. 이와 비슷한 갈래의 방법인 ProDA [Lu+22a]는 하나의 프롬트를 학습하여 이용하는 CoOp과 달리 여러 프롬트 셋을 구성하고 텍스트 인코더의 임베딩 분포를 학습하도록 하여 CoOp에 비해 높은 정확도를 얻었습니다.

사용자는 실제로 모델을 사용할 때 학습 때 등장했던 클래스가 아닌 새로운 클래스에 대한 분류를 원할 수 있습니다. [Zho+22b]는 CoOp의 경우 프롬트에 붙는 클래 명을 바꾸어 학습 때 보지 않았던 클래스에 대한 분류를 하는 경우 그 정확도가 zero-shot CLIP에 비해 현저히 떨어짐을 보이고 이를 개선하기 위한 방법인 CoCoOp을 제안합니다. CoCoOp에서는 이미지 인코더에서 나오는 이미지 피쳐에 Meta-Net이라는 작은 모델을 붙여 이 모델에서 나온 “input conditional token”을 연속적인 프롬트에 더하여 학습합니다. 이렇게 학습했을 때 새로운 클래스에 대해서는 Zero-shot CLIP보다 낮은 정확도를 보이고, 이전에 보았던 클래스에 대해서는 CoOp보다 낮은 정확도를 보이지만 이전에 보았던 클래스, 이전에 보지 않았던 클래스에 대한 정확도의 하모닉 평균에서는 세 모델 중 가장 좋은 결과를 보였습니다.

◇ 텍스트 이용한 이미지 검색

BEIT-3 [Wan+22]는 masked data modeling이라 하여 이미지도 함께 NLP에서의 masked language model과 같이 마스킹해 텍스트와 함께 사전학습 한 모델입니다. 이때 Multiway Transformers [31]와 같이 self-attention 파라메터는 공유하지만 그 위에 존재하는 feed-forward network들은 이미지, 텍스트, 이미지-텍스트 세 종류의 입력 데이터 형식을 각각 담당할 수도 있도록 구성됩니다.

BEIT-3는 주어진 텍스트에 맞는 이미지를 가져오는 text-to-image retrieval 태스크에서 Flickr30k [You+14], MSCOCO [Lin+14] 데이터셋을 이용해 평가했을 때 zero-shot, fine-tuning 세팅에서 모두 이전의 모델들보다 좋은 결과를 내었습니다. 하지만 모델 파라메터가 적어도 아직은 공개되지 않은 데다가 1.9B이나 되는 파라메터 수는 이 모델을 저사양의 GPU에서 다루기 힘들게 합니다.

Text retrieval에서 이용하는 방법들도 text-to-image retrieval에 수직적으로 적용될 수 있습니다. 예를 들어 학습 중인 리트리버의 체크포인트를 이용해서 hard negative 샘플들을 구성해 성능을 개선한 [Xio+21]이나 ranker는 정답 패시지와 retriever가 가져온 패시지를 잘 구분하도록 학습하고, retriever는 ranker가 자신이 가져온 패시지와 정답 패시지를 구분하기 힘들도록 학습하는 방법을 제안한 [Zha+22]가 있습니다.

◇ 텍스트 형식의 유저 피드백 통한 상품 제안

이 태스크에서는 레퍼런스 이미지와 가져오고자 하는 이미지와 주어진 레퍼런스 이미지 간의 차이점이 기술된 텍스트가 주어졌을 때 이를 이용해서 적절한 타겟 이미지를 가져오도록 모델을 학습하는 것을 목표로 합니다. 관련 데이터셋으로는 패션 아이템 이미지들로 구성된 Fashion IQ [Wu+21], Challenging Fashion Queries [DCS22]와 일반적인 이미지들로 구성된 CIRR [Liu+21]가 있습니다.

FashionVLP [Goe+22]는 원래 이미지에 추가로 옷이 명확히 나오도록 확대된 이미지를 함께 넣고, 사전학습된 key point detection 모델 [Che+18], object detector 모델 [Ren+15] 그리고 이미지, 텍스트에 대해 사전학습된 모델 [Zha+21]을 활용하여 기존의 방법들에 비해 좋은 결과를 내었습니다.

[Bal+22a, Bal+22b]는 다양한 역할을 하는 모델들로 이루어진 FashionVLP와 달리 레퍼런스 이미지와 이와 함께 주어진 텍스트를 각각 CLIP [Rad+21]의 이미지, 텍스트 인코더를 이용해 임베딩을 추출한 뒤 이를 합쳐 최종 소스 임베딩을 만듭니다. 그리고 이 소스 임베딩이 타겟 이미지의 임베딩과 가까워지도록 학습하는 단순한 방식으로 이전의 방법들보다 좋은 결과를 낼 수 있음을 보입니다.

◇ AR 을 활용한 가상 피팅룸

영국 SPA 브랜드 탑샵의 경우, 2011년도 AR 과 키넥트(Kinect)를 사용해 가상피팅룸을 선보였습니다.

키넥트는 물리적인 작동기 없이 사용자의 신체를 이용하여 엔터테인먼트를 경험할 수 있는 엑스박스 360과 연결해서 사용하는 주변기기입니다.

이 키넥트의 모션 센서를 통해 사용자 동작을 인식하는데, 이 센서는 실시간으로 깊이 정보뿐만 아니라 RGB 영상과 관절 추적 정보를 제공합니다.

이를 통해 사용자의 신체 및 자세를 추정하는데 쉬운 데이터를 제공해주고, 이 데이터를 기반으로 옷을 덧입혀 마치 사용자가 옷을 착용한 것과 같은 이미지를 보여줍니다.

그러나 단순히 사용자의 모습에 옷을 덧입히는 방식이기 때문에, 다소 생동감이 떨어진다는 제한점이 있습니다.

◇ Virtual Try-On

모자 쇼핑몰 텐즈 스트릿 햇의 경우 모바일 기기 및 데스크탑을 통해 사용자가 모자를 착용한 모습을 볼 수 있는 기능을 제공하고 있습니다.

그러나 단순히 모자 이미지와 사용자 얼굴을 중첩하는 것이기 때문에, 생동감이 다소 떨어진다는 제한점이 있습니다.

또한, 아이웨어 쇼핑몰 글라스매치 역시 모바일 앱을 이용해 안경을 가상 착용할 수 있도록 하고 있습니다.

이때 가상 객체와 얼굴을 합성하는 방식을 사용하여, 다양한 각도에서도 안경을 착용한 모습을 볼 수 있도록 하여 생동감을 높였습니다.

기술 로드맵

◇ Virtual Try-On AR을 이용한 Virtual Try On에서는 실세계 대상의 좌표를 실시간으로 추적하는 것과 가상 객체를 증강하는 기술이 주가 됩니다.

1. 실시간 위치 추적

실시간 위치를 추적하는 방법으로는 관성추적, 자기추적 등의 방법이 있으며, 대표적으론 광학적 추적을 주로 사용합니다.

광학적 추적 방식의 경우 트랜스폰더-리시버 방식이 갖는 제약이 없으며, 높은 정확성을 가진다는 이점이 있습니다. 그러나 계산량이 많으므로 속도가 느려질 수 있다는 문제가 발생할 수 있습니다.

이때 두 방식을 혼합한 하이브리드 방식을 통해 성능을 개선할 수 있습니다. 그 예시로 관성 센서와 시각 기반 추적 방식을 함께 사용하면, 더욱 빠른 움직임에서는 관성 센서가 시각 기반 추적의 오차를 줄이고, 느린 움직임의 경우 시각 기반 추적을 통해 관성 센서의 관성에 의한 오차를 줄일 수 있습니다.

이를 통해 사용자에게 더 부드러운 AR 이미지를 제공할 수 있으며, 사용자는 자신의 움직임에 따라 옷이 같이 이동하며 마치 실제로 착용한 것과 같은 감각을 경험할 수 있습니다.

2. 가상 객체 증강

가상 객체를 증강하는 기술에서는 대표적으로 ARToolKit 가 있습니다.

ARToolKit 에서는 크기가 알려진 표시를 감지하기가 쉽도록 검정색 테두리로 둘러싼 표시를 이용하여, 그 사각형 안에 표시를 구분할 수 있는 패턴을 사용합니다. 이러한 표시 정보를 바탕으로 표시 위에 가상 객체를 증강할 순 있지만, 3차원 깊이 정보를 이용하지 않기 때문에 사용자의 시야 가림 문제를 해결할 수 없습니다.

이때 템플릿 매칭 기법을 이용할 수 있는데, 이를 사용해 다양한 시점으로부터 실세계에 존재하는 객체에 대한 템플릿 이미지를 얻고, 이를 실세계 객체를 위한 영상을 찾는데 사용할 수 있습니다. 이렇게 구한 영상에 대한 대략적인 CAD 모델과 수동적인 비전 기술만을 사용해, 사용자의 환경을 실시간으로 추적하여 효과적으로 가상 객체를 증강할 수 있습니다.

◇ AI 리뷰 요약

AI로 리뷰를 요약해 제공하는 기능은 사용자들이 리뷰를 더 편리하게 보게 할 수 있습니다. 네이버는 하이퍼클로바(HyperCLOVA)를 기반으로 제품의 특성을 한 줄의 문장으로 추출하고 있고, 여성복을 판매하는 오드에서는 리뷰를 소재 카테고리에 따라 분류하여 제공합니다. 또한, 자연어처리(NLP)기술 기반의 리뷰 분석 AI 서비스 기업인 빌리뷰는 신세계인터네셔날과 협업하여 그들에게 리뷰 분석 서비스를 제공합니다. AI 리뷰 요약 기능은 소비자들의 쇼핑 시간을 절감시키고 그들이 필요로 하는 정보만을 보여줄 수 있습니다. 또한, 이 요약 기술을 활용하여 여러 상품을 동시에 비교할 수 있는 기능을 만들어 소비자들에게 제공함으로써 그들은 그들만의 기준으로 상품을 비교해볼 수 있습니다.

특허조사

◇ 키워드 기반 검색

  • Natural language keyword tag extraction

◇ Text-to-image retrieval

  • System and methods of integrating visual features with textual features for image searching
  • Image search using text-based elements within the contents of images
  • System and method for multimedia ranking and multi-modal image retrieval using probabilistic semantic models and expectation-maximization (EM) learning

◇ 유저 피드백 통한 상품 제안

  • Search with more like this refinements

특허 전략 분석

유사도를 이용한 키워드 검색, text2image 검색, 스트링 매칭을 이용한 검색을 사용자가 이해하기 쉽게 화면에 표현하는 방법과 관련하여 특허 등록을 고려할 수 있습니다.

시장상황에 대한 분석

경쟁제품 조사 비교

◇ 전문 코디 추천

무신사, 셀렙샵의 경우 전문 스타일리스트 및 코디가 있어, 이들이 테마별 옷을 추천해주는 기능을 제공하고 있습니다. 이를 통해 사용자는 자신이 원하는 테마의 옷을 검색하고 추천받을 수 있습니다.

다만, 전문 스타일리스트가 직접 추천해주는 시스템이기 때문에, 서비스가 커지면 더 많은 소비자의 수요를 맞추지 못할 수 있다는 한계점이 있습니다.

[그림 2-1]

Musinsa.png

[출처: 무신사, https://www.musinsa.com/app/]

◇ 키워드 검색

키워드로 검색해도 검색결과가 나오는 서비스도 있었습니다.

브랜디의 경우, 판매자가 제목에 모든 키워드를 넣고, 제목을 기준으로 검색되었습니다. 그러나 이때 키워드 검색이 되려면 판매자가 제목에 모든 키워드를 넣어야 한다는 단점이 있었습니다.

한편 아뜨랑스의 경우, 옷에 대한 태그가 있어 이 태그를 기준으로 검색할 수 있었습니다.

[그림 2-2]

Pic 2 2.png

[출처: 브랜디(좌측), 아뜨랑스(우측)]

◇ 결론

대부분의 쇼핑몰의 경우 놀이동산룩, 개강룩 등 키워드로 검색할 수 있는 기능을 제공하고 있지 않았습니다. 또한, 제공하더라도 단일 키워드로 검색할 수 있으며, 사용자가 원하는 특정 옷을 보다 구체적인 문장으로 검색하는 기능은 제공하고 있지 않습니다.

그러나 옷을 고를 때 자신이 원하는 캐릭터가 그려진 옷이나 동식물이 있는 옷을 사고 싶을 수 있으며, 이런 소비자들의 Needs를 충족시키는 서비스는 존재하지 않습니다. 또한, 검색한 옷에서 단추가 있으면 좋겠다거나 후드 모자가 있으면 좋겠다는 등 특정 요소를 추가하거나 제거한 옷을 원할 수 있습니다. 이와 같은 방식으로 옷을 검색하는 서비스 역시 존재하지 않았습니다.

따라서 저희는 위와 같은 기능을 제공한다면 충분히 기존 서비스와 차별점이 생길 것으로 판단했습니다.

마케팅 전략 제시

◇ Strength

  • AI를 활용해 옷의 키워드를 분석하고 추출하는 작업을 자동화할 수 있다는 강점이 있습니다.이를 통해 다양한 쇼핑몰의 옷을 키워드로 손쉽게 검색할 수 있습니다.
  • 구체적인 문장을 통해 사용자가 원하는 옷을 검색할 수 있다는 강점이 있습니다.
  • 옷에 대해서 특정 요소를 추가 및 변경한 옷을 검색할 수 있다는 강점이 있습니다.

◇ Opportunity

  • 현재 패션 산업의 전망이 좋아지고 있으며, 온라인 쇼핑몰 산업 역시 규모가 크기 때문에, 패션 관련 서비스의 수요 역시 증가할 것으로 보입니다.
  • 또한, 여전히 소비자들은 옷을 고르고 스타일링하는 데 시간과 노력이 많이 든다는 pain point가 있기에, 이를 해결한 서비스에 대한 needs 가 존재합니다.

◇ SO 전략

종합적으로, 다양한 쇼핑몰의 옷을 키워드로 손쉽게 검색할 수 있으며, 구체적인 문장과 사용자 피드백으로 더욱 상세히 소비자가 원하는 옷을 검색할 수 있다는 강점이 있습니다.

이 강점을 살려 소비자들이 옷을 고르고 스타일링하는 데 들이는 시간과 노력을 줄인다면 기존 서비스와 차별되는 성공적인 서비스로 자리매김할 수 있을 것입니다.

개발과제의 기대효과

기술적 기대효과

◇ 다량의 이미지와 텍스트에 대해 학습된 모델을 효율적으로 재학습하여 적은 양의 데이터로도 키워드를 자동으로 부여할 수 있게 합니다.

◇ 검색어와 상품의 이미지에 대한 연관성을 직접 비교함으로써 판매자가 직접 작성한 상품에 대한 설명에 존재하지 않는 상품의 시각적 성질에 대해서 검색을 가능하게 합니다.

◇ 사용자 피드백에 기반을 둔 모델 추천에 사용되는 자연어 데이터는 제작에 비용이 많이 들어 다양한 유형의 상품에 대해 만들기에 어려움이 있습니다. 데이터셋에 주어진 도메인에서 타겟 도메인에 적응하는 방법을 통해 이러한 제약을 줄여 관련 방법의 사용을 용이하게 합니다.

경제적, 사회적 기대 및 파급효과

◇ 소비자들의 옷 선택 시간 및 쇼핑 시간을 단축할 수 있습니다.

◇ 현재, 오프라인 소매업의 몰락을 의미하는 ‘리테일 아포칼립스(Retail Apocalypse)’ 현상이 가속화되고 있습니다. 소비자들이 웹사이트에서 상황에 따른 옷을 파악할 수 있게 된다면 오프라인 매장에 가는 일이 더욱 줄어들 것입니다.

◇ 하나의 도매업체에서 같은 옷을 들여오지만 다른 가격에 파는 쇼핑몰들이 있습니다. 만약 한 페이지에 여러 쇼핑몰의 데이터를 크롤링하여 보여준다면 획일화된 제품들을 판매하는 쇼핑몰들을 확인할 수 있으며 그들에게 이 사이트는 긴장감을 부여할 것입니다. 이는 결국, 같은 옷의 가격 동결을 이뤄낼 것입니다.

기술개발 일정 및 추진체계

개발 일정

1. 월 단위 개발 일정 M plan.png

2. 주 단위 개발 일정

W plan 1.png W plan 2.png

3. 간트 차트

G chart.png

구성원 및 추진체계

◇ 유저 플로우 및 기획

이희영, 안광민, 채희진

◇ AI 모델 개발

이희영

◇ 백엔드 서버 구축

안광민

◇ 프론트엔드 개발 및 UI 디자인

채희진

설계

사용자 요구사항

Use case.png

◇ R1: 판매자, 또는 관리자가 키워드를 관리(조회, 추가, 삭제, 블랙)하는 기능

◇ R2: 고객이 키워드, 문장, 이름, 피드백을 사용해 옷을 검색하는 기능

◇ R3: 고객이 좋아요 목록을 관리(조회, 추가, 삭제)하는 기능

◇ R4: 로그인 기능

◇ R5: 회원정보 관리(회원가입, 탈퇴) 기능

◇ R6: 판매자 또는 관리자가 옷을 관리(조회, 추가, 삭제)하는 기능

사용자 요구사항 만족을 위한 기능 정의 및 기능별 정량목표

Performance table.png

기능 구현을 위한 세부기술 선택사항 (디자인)

Springboot & Java

(1) Springboot

1. 자주 사용되는 라이브러리들의 버전 관리 자동화

우리가 사용하는 도구들(프레임워크나 라이브러리 등)에는 기본적으로 버전이 존재하는데, 여러 도구들의 버전을 올바르게 조합해주지 않으면 예상치 못한 오류가 발생할 수 있습니다.

스프링부트는 직접 라이브러리 버전들을 관리해주기 때문에, maven이나 gradle 등과 같은 빌드 도구에 버전을 명시하지 않아도 적합한 라이브러리 버전을 찾아서 가져와줍니다.

2. AutoConfig로 복잡한 설정 자동화

스프링 부트는 개발을 위해 필요한 공통적인 부분들을 자동으로 구성해줍니다. 그래서 기본적으로 스프링 부트 프로젝트를 만들면 별도의 설정 없이 서버를 바로 띄울 수 있습니다.

그 뿐만 아니라 스프링부트는 ElasticSearch, Redis, Gson 등과 같은 자주 사용되는 외부 라이브러리들 역시도 자동 설정을 제공하고 있습니다.

3. 내장 웹서버 제공

스프링 부트는 내장 웹서버를 가지고 있어서 별도의 작업 없이 빠르게 서버를 실행할 수 있도록 도와줍니다.

(2) Java

Java는 한 컴퓨터 시스템에서 다른 시스템으로 쉽게 이동할 수 있습니다.. 서로 다른 여러 시스템에서 동일한 프로그램을 실행하는 기능은 월드 와이드 웹 소프트웨어에 매우 중요하며 Java는 소스 레벨과 2진 레벨에서 독립적인 플랫폼으로 이 기능을 갖추었습니다

Vue.js & Typescript

(1) Vue.js

· React에서 반복문을 사용할 때는, map, forEach, for, for in, for of등 다양한 문법을 사용하고 컴포넌트 render() 바깥에서 이 반복문을 쓸지 그 안에서 쓸지 방법이 다양하다. 그러나 Vue.js에서는 v-for라는 문법 하나로 통일된다. 그 외에도 조건부 렌더링에서 React는 여러 방법이 있지만 Vue.js는 v-if, v-else만 사용하면 된다.

· Vue.js는 현재 안정적으로 성장하고 있다. 따라서, 장기적인 지원에 걱정없이 사용할 수 있다는 장점이 있다.

· Vue.js는 .vue 파일 하나에 html, css, js를 작성할 수 있는 단일 파일 컴포넌트가 가능하다. 이는 캡슐화를 제공하여 보다 깨끗하고 풍부한 컴포넌트의 표현이 가능하게 한다.

(2) Typescript · Typescript는 브라우저에서 실행하고 잘못된 결과를 확인하기 전에 미리 컴파일(코드 변환) 시점에 타입 변환으로 인한 에러를 검출할 수 있다.

· Typescript는 Javascript와 100% 호환되고 대부분의 라이브러리들이 Typescript를 지원하며 마이크로소프트의 비주얼 스튜디오 코드(VSCode)를 비롯해 각종 에디터가 Typescript 관련 기능과 플러그인을 지원한다.

ML

(1) 키워드 추출 및 키워드 통한 이미지 검색

소량의 데이터로도 분류가 가능해야 한다는 요구 사항을 만족해야 하기 때문에 학습에 사용된 키워드에 대해서만 분류만이 필요한 경우 CoOp [Zho+22a]나 ProDA [Lu+22a]를 베이스라인으로 삼습니다. 만약 학습에 사용되지 않은 키워드에 대한 분류가 요구되는 경우 CoCoOp [11]을 베이스라인으로 삼습니다.

검색 창에 학습 때 존재하지 않았던 키워드를 입력하는 경우 학습 때 존재했던 키워드 중 가장 가까운 키워드를 추천 키워드와 같은 형식으로 제공합니다.. 이 때 키워드 간의 유사도는 프롬트를 포함해서 만들어진 텍스트 임베딩의 유사도를 이용해 구합니다.

(2) 텍스트 이용한 이미지 검색

개발 기간에 제한이 있기 때문에 사전학습된 CLIP 모델을 zero-shot 설정에서 주로 이용합니다. 추가 학습이나 성능 평가에는 의류 이미지와 그에 설명을 포함하는 Fashion-200K [Han+17], FACAD [Yan+20], Fashion Gen [Ros+18], Polyvore Outfits [Vas+18] 데이터셋을 이용할 수 있습니다.

(3) 텍스트 형식의 유저 피드백 통한 상품 제안

Fashion IQ [Wu+21] 혹은 Challenging Fashion Queries [DCS22] 데이터셋을 사용하여 학습된 모델로 서비스를 제공합니다. Fashion IQ 데이터셋의 경우 “dresses”, “shirts”, “tops & tees” 세 가지 카테고리에 대한 상품들로 구성이 되어 있기 때문에 실제로 사용할 때에는 위 카테고리에 속하지 않는 상품에 대해서도 적절한 응답을 하는지에 대한 점검이 필요합니다.

실제 사용 환경에서는 유저가 여러 번 피드백을 주는 상황이 존재할 수 있어 성능에 따라 모델을 여러 턴에 대해 학습이 필요할 수 있다는 점도 염두해 두어야 합니다.

시스템 설계

System d.png

시스템 구성

프론트엔드는 Netlify 를 사용해 배포했으며, 이를 통해 소스가 푸시될 때마다 자동으로 빌드되고 배포될 수 있도록 구성했습니다.

Netlify 에는 깃허브 레포지토리에 프론트엔드 패키지를 올린 후, 이를 연동해서 패키지를 설치합니다.

백엔드는 AWS EC2 인스턴스를 사용해 백엔드 서버를 구동하고 배포했습니다.

또한, Redis 를 사용해 JWT 토큰 중에서 리프레시 토큰을 관리합니다.

Redis 는 인메모리 상태에서 데이터를 처리하기 때문에 다른 DB보다 빠르고 가벼워서, 리프레시 토큰을 처리함에 있어 용이하다고 판단했습니다.

반면 그 이외의 데이터의 경우 MySQL 을 설치해서 데이터베이스를 관리합니다.

AWS 에는 역시 깃허브를 사용해 소스가 변경될 때마다 푸시를 하고 다시 실행합니다.

AI 는 AWS EC2 인스턴스를 사용해 서버를 구동했습니다.

세부 항목

Client PC

실제 사용자의 컴퓨터로, 사용자는 웹 브라우저를 통해 서비스를 이용할 수 있다.

Netlify

이미지를 업로드하는 저장소 역할을 수행함과 동시에,

프론트엔드 파일을 호스팅해서 사용자가 원격으로 웹사이트에 접속해 기능을 사용할 수 있도록 한다.

Index.html

public 폴더의 index.html에 의해 페이지로 표현된다.

index.html 내부에 14번줄에 해당하는
로 표시된 부분을 볼 수 있는데, 여기에 main.ts에서 지정하는 컴포넌트들이 마운팅 된다.

main.ts

인스턴스를 생성하고 index.html 파일과 연결해준다.

App.vue

실제 컴포넌트 파일이다.

여러 컴포넌트들을 불러와서 main.ts로 넘겨주는 통합 컴포넌트이다.

<template>, <script>, <style> 구조로 이루어진다.

components

views에서 코드양을 줄이기 위해 공통적으로 사용되는 부분을 분리해서 component 폴더에 저장한다. 이 후, 폴더를 import하여 컴포넌트를 개별적으로 사용할 수 있다.

assets

자산파일(assets files)을 저장한다.

font, icons, images, styles etc 이 있다.

router

vue-router와 관련된 모든 파일을 저장한다.

store

vuex와 관련된 파일을 저장하는 vuex 스토어 디렉토리다.

이 폴더에는 state, actions, mutations, getters를 저장한다.

views

어플리케이션 경로에 대한 모든 진입점을 저장한다.

AWS

백엔드 파일을 실행하여 프론트엔드로부터 요청이 오면 그에 대한 비즈니스 로직을 수행한다.

FashionSearch

백엔드 비즈니스 로직 코드를 담은 최상위 패키지로, Auth, Service, Controller, Util, Config, Domain, Repository 서브 패키지를 포함한다.

이것을 build 해서 jar 파일을 만든다.

FashionSearch.jar

백엔드 비즈니스 로직을 담은 jar 파일로, 이것을 AWS 서버에 넣은 후 해당 파일을 실행해서 백엔드 서버를 가동한다.

Redis

Key-Value의 비정형 데이터로 구성해 저장 , 관리하기 위한 오픈소스 비관계형 데이터베이스 관리 시스템이다.

이를 사용해 리프레시 토큰을 관리한다.

MySQL

RDS DB 에 사용되는 것으로 MySQL 을 사용한다.

MLModelServer

여러 ML 모델들이 이곳에 배포된다. image_classification_service.py 아티팩트로 구현된 image_classification_service 컴포넌트, text2image_service.py 아티팩트로 구현된 text2image_service 컴포넌트, text_conditioned_retrieval_service.py 아티팩트로 구현된 text_conditioned_retrieval_service 컴포넌트가 이곳에 배포되어 활용된다.

이론적 계산 및 시뮬레이션

해당 없음.

소프트웨어 설계

유즈케이스도

Use case.png

상호작용하는 모든 사용자들은 로그인 또는 인증 기능이 필요하므로, Member 라는 액터를 상속하도록 설정했다.

또한 옷과 키워드를 관리하는 행위자를 직원(Employee)로 설정하고, 관리자(Manager)와 판매자(Seller)가 이를 상속해서 동일한 유즈케이스와 관계맺도록 설정했다.

Login seq.png

Search clothes table.png

Search clth seq.png

Mng wish.png

Mng clth.png

Mng clth seq.png

Mng kw.png

Mng kw seq.png

Mng mem.png

Mng mem seq.png

Activity Diagram

Activity diag.png

고객, 판매자, 관리자 인증 수행 흐름

초기에는 기능을 사용하기 위해 로그인을 진행한다[로그인]. 이때 사용자가 회원가입을 하지 않았던 상태라면, 회원가입을 진행한 후[회원가입] 로그인을 재시도한다.

로그인을 하면 회원가입 시 선택한 고객 또는 판매자 역할에 따라 기능을 선택할 수 있다. 이때 사용자 정보를 조회한 후[사용자 정보 조회] 정보를 수정하거나[사용자 정보 수정] 탈퇴할 수 있다[회원 탈퇴].

또한 고객의 경우 자신이 좋아요를 누른 항목을 보거나[좋아요 목록 조회], 옷들에 대해 좋아요를 하거나[좋아요] 취소할 수 있다[좋아요 취소]

관리자의 경우, 인증코드를 입력해서 인증을 시도한다[인증코드 입력]. 이후 인증되었으면 기능을 실행할 수 있다.

로그인

사용자로부터 아이디와 비밀번호를 입력받아 로그인을 수행한다.

회원가입

만약 회원가입이 안되어있다면 회원가입을 수행하고 다시 로그인을 수행한다.

로그인이 된다면 사용자는 기능을 선택한다.

사용자 정보 조회

고객 또는 판매자는 자신의 사용자 정보를 조회한다.

회원 탈퇴

회원을 탈퇴한다.

좋아요 목록 조회

고객이 좋아요를 한 옷 목록을 조회한다.

좋아요 취소

좋아요를 한 옷에 대해 좋아요를 취소한다.

사용자 정보 수정

사용자의 핸드폰 번호, 이름 등 사용자 정보를 수정한다.

인증코드 입력

관리자는 인증코드를 입력해서 관리자임을 인증한다.

고객 기능 수행 흐름

고객의 경우 원하는 문장으로 옷을 검색할 수 있다[옷 검색]. 검색이 진행되면 AI 모델 서버로 입력된 문장을 전달해 해당 옷을 조회하거나[AI 모델 서버로 입력된 문장 전달], 이름으로 옷을 검색하거나[이름으로 검색], 문장 속 키워드를 추출해서 해당 키워드를 갖는 옷을 검색할 수 있다[해당 키워드를 갖는 옷 검색]. 이후 3개의 검색 결과를 취합해 사용자에게 보여준다[검색 결과 반환].

각각의 검색 결과에 대해 더보기 버튼을 눌러 상세한 결과를 볼 수 있다[더보기].

이때 옷 검색 결과에 만족했을 경우, 검색을 완료한다[검색 완료]. 만족하지 않았다면, 피드백을 입력해서[피드백 입력], 해당 피드백이 반영된 옷을 다시 고객에게 제공한다[새로운 옷 제공].

검색된 옷에 대해 사용자는 해당 옷에 대해 좋아요를 할 수 있고[좋아요], 상세 페이지로 이동해서 실제 주문을 할 수 있다 [상품 상세 페이지 이동]. 이후 기능이 완료된다.

또는, 처음부터 화면에 보여진 옷에 대해 피드백을 입력한다[피드백 입력]. 그리고 피드백에 맞는 옷을 새롭게 제공한다[새로운 옷 제공]. 마음에 들지 않으면 이 과정을 반복한다. 이후 옷이 마음에 들었다면, 기능이 완료된다.

옷 검색

사용자가 원하는 문장을 자유롭게 입력해서 옷을 검색한다.

AI 모델 서버로 입력된 문장 전달

사용자가 입력한 문장이 AI 모델 서버로 전달되어 그에 맞는 옷을 검색한다.

이름으로 검색

사용자가 입력한 문장에 해당하는 이름을 갖는 옷을 검색한다.

해당 키워드를 갖는 옷 검색

사용자가 입력한 문장 속에서 키워드를 추출해, 해당 키워드에 맞는 옷을 검색한다.

검색 결과 반환

사용자가 입력한 문장에 따른 3개의 검색 결과를 화면에 표시한다.

피드백 입력

사용자가 반환된 검색 결과에 만족하지 않는다면 피드백을 입력한다. 사용자의 피드백을 바탕으로 사용자들은 새로운 옷을 추천받을 수 있다.

새로운 옷 제공

피드백에 따른 새로운 옷을 제공한다.

검색 완료

사용자가 반환된 검색 결과에 만족하거나 피드백을 통해 추천받은 옷에 만족한다면 검색이 완료된다.

좋아요

사용자는 완료된 검색을 바탕으로 옷을 찜할 수 있고 로직은 종료된다.

상품 상세 페이지 이동

사용자는 완료된 검색을 바탕으로 옷을 클릭하여 상세 페이지로 이동할 수 있고 로직은 종료된다.

판매자 또는 관리자 기능 수행 흐름

판매자와 관리자는 먼저 어떤 기능을 수행할 것인지 선택한다. 수행할 수 있는 기능에는 키워드 조회와 옷 조회가 있다.

만약 키워드 조회를 선택했다면 관리자의 경우 화면에는 현재 키워드 분류 모델 서버에 등록되어 있는 키워드들이 나열된다[키워드 조회] 판매자의 경우에는 자신이 추가한 키워드만 화면에 표시된다.

판매자는 자신이 추가한 키워드 중에서 삭제하고 싶은 키워드를 골라 삭제할 수 있다[키워드 삭제]. 관리자의 경우 모든 키워드를 삭제할 수 있다. 모델이 추출할 수 있는 키워드를 추가하기를 원하는 경우 새로운 키워드를 입력하여 추가한다 [키워드 추가]. 이때 관리자가 추가한 키워드는 모든 옷에 반영되고, 판매자가 추가한 것은 판매자가 올리는 옷에만 반영된다.

만약 옷 조회를 선택했다면 화면에 현재 등록된 옷들이 나열된다[추가한 옷 조회]. 판매자의 경우 자신이 올린 옷만, 관리자의 경우 모든 옷이 표시된다.

관리자 또는 판매자는 조회된 옷들 중에서 삭제하고 싶은 옷들을 골라 삭제할 수 있다[옷 삭제].

판매자 또는 관리자는 추가하고 싶은 옷을 알맞은 형태로 입력하여 서비스되고 있는 사이트에 추가할 수 있다. [옷 추가]. 옷을 수정하는 것 역시 가능하다[옷 수정].

키워드 조회

현재 키워드 분류 모델 서버에 등록된 키워드들을 나열한다.

키워드 추가

키워드 분류 모델 서버에 새로 등록할 키워드를 추가한다.

키워드 삭제

키워드 분류 모델 서버에 등록된 키워드 중 일부를 삭제한다.

추가한 옷 조회

상품 제목 혹은 ID에 대한 간단한 검색 기능을 통해 옷을 조회한다.

옷 추가

엑셀 파일 등의 형식으로 구성된 파일을 업로드하는 등 서비스에서 검색 가능하도록 새로운 옷을 추가한다.

옷 삭제

조회된 상품들 중 삭제하고 싶은 상품들을 골라 삭제한다.

옷 수정

조회된 상품들 중 수정하고 싶은 상품들을 골라 수정한다.

Architecture Diagram

Arch diag.png

1. Frontend

사용자와 상호작용하는 시스템이다.

사용자로부터 입력값을 받거나 사용자가 볼 수 있는 화면을 구현한다.

2. Backend

사용자로부터 받은 입력을 내부적으로 처리하는 시스템이다.

사용자가 요청한 데이터를 가공하고 전달한다.

3. AI

검색 기능에 있어 추가적인 기능을 제공하는 시스템이다.

자연어 문장을 검색하거나 사용자 피드백으로부터 새로운 옷을 검색해주는 기능을 구현한다.

4. Resources

관리자와 상호작용하는 시스템이다.

관리자로부터 입력값을 받거나 사용자가 볼 수 있는 화면을 구현한다.

패키지 별 클래스도

프론트엔드

Front class diag.png

<main.js>

인스턴스를 생성하고 index.html 파일과 연결해준다.

<App.vue>

실제 컴포넌트 파일, App.vue 파일은 하나의 컴포넌트이고, 여기에 여러 컴포넌트들을 불러와서 main.js로 넘겨주는 통합 컴포넌트라고 볼 수 있다. 컴포넌트 파일은 <template>, <script>, <style> 부분으로 나누어져 있다.

<router>

Vue가 단일 페이지로 작동(SPA)하기 때문에, 페이지에 요청이 올 때마다 서버에 요청을 보내서 페이지를 받아오는게 아니라, 미리 페이지들을 로딩해서 갖고 있다. 이런 각 페이지들로 이동할 수 있게 해주는 것이 Router이다.

<Views>

views는 경로에 대한 모든 진입점을 저장한다.

UserAll.vue

사용자가 All 카테고리를 클릭했을 때 보여지는 화면이다.

UserOuter.vue

사용자가 Outer 카테고리를 클릭했을 때 보여지는 화면이다.

UserTop.vue

사용자가 Top 카테고리를 클릭했을 때 보여지는 화면이다.

UserPants.vue

사용자가 Pants 카테고리를 클릭했을 때 보여지는 화면이다.

UserSkirts.vue

사용자가 Skirts 카테고리를 클릭했을 때 보여지는 화면이다.

UserDress.vue

사용자가 Dress 카테고리를 클릭했을 때 보여지는 화면이다.

UserMyPage.vue

사용자와 판매자가 Account를 클릭한 후 MyPage를 클릭했을 때 보여지는 화면이다.

-clickSaveEdit()

사용자와 판매자의 정보를 수정한 후 Edit 버튼을 눌렀을 때 호출되는 함수이다.

-deleteAccount()

사용자와 판매자가 Delete Account을 클릭한 후 뜨는 모달에서 Yes 버튼을 눌렀을 때 호출되는 함수이다.

SearchResult.vue

사용자가 돋보기 버튼을 통해 검색을 한 후 보여지는 화면이다.

SearchKeyword.vue

사용자가 SearchResult 화면에서 키워드를 클릭했을 때 보여지는 화면이다.

SearchName.vue

사용자가 SearchResult 화면에서 Search Sentence 항목의 View More을 클릭했을 때 보여지는 화면이다.

SearchSentence.vue

사용자가 SearchSentence 화면에서 Search Name 항목의 View More을 클릭했을 때 보여지는 화면이다.

Login.vue

사용자와 판매자가 Account를 클릭할 수 Login을 클릭했을 때 보여지는 화면이다.

-clickOption()

사용자와 판매자가 로그인 화면에 있는 Log In, Create User Account, Create Seller Account를 클릭했을 때 호출되는 함수이다.

CreateUserAccount.vue

사용자가 로그인 화면에서 Create User Account를 클릭했을 때 보여지는 화면이다.

-clickUserSignUpButton()

사용자가 사용자의 정보를 입력한 후 Sign Up 버튼을 눌렀을 때 호출되는 함수이다.

CreateSellerAccount.vue

판매자가 로그인 화면에서 Create Seller Account를 클릭했을 때 보여지는 화면이다.

-clickSellerSignUpButton()

판매자가 판매자의 정보를 입력한 후 Sign Up 버튼을 눌렀을 때 호출되는 함수이다.

SellerAddClothes.vue

판매자가 Add Clothes를 클릭했을 때 보여지는 화면이다.

-bringImage()

판매자가 Place Image를 클릭했을 때 호출되는 함수이다.

-clickAddKeyword()

판매자가 + 버튼을 눌렀을 때 모달을 호출하는 함수이다.

-saveAddKeyword()

판매자가 키워드를 검색하여 이 키워드가 존재할 경우 Add 버튼을 클릭하면 호출되는 함수이다.

-clickAddNewKeyword()

판매자가 검색한 키워드가 존재하지 않을 경우 Add 버튼을 클릭하면 호출되는 함수이다.

-clickSaveClothes()

판매자가 Save 버튼을 클릭했을 때 호출되는 함수이다.

SellerEditClothes.vue

판매자가 등록한 옷을 클릭했을 때 보여지는 화면이다.

WishList.vue

사용자가 Account에서 WishList를 선택했을 때 보여지는 화면이다.

-deleteHeartOffClothes()

사용자가 빨간 하트를 눌렀을 때 호출되는 함수이다.

<Component>

:HTML Element를 확장하고 재사용 가능한 형태로 구현하는 것이다.

HeaderTop.vue

-clickAccount() : 사용자와 판매자가 Account를 눌렀을 때 호출되는 함수이다.

-selectedOption(): 사용자와 판매자가 Account 아래에 나타나는 Login MyPage Logout을 선택할 때 호출되는 함수이다.

-clickSearch(): 사용자와 판매자가 돋보기 아이콘을 눌렀을 때 호출되는 함수이다.

-clickAddClothes(): 판매자가 Add Clothes를 눌렀을 때 호출되는 함수이다.

-clickCategory(): 사용자와 판매자가 상단의 SHOP에서 All, Outer, Top, Pants, Skirts, Dress를 눌렀을 때 호출되는 함수이다.

ClothesDeleteWarningModal.vue

-deleteClothes(): 판매자가 체크한 카테고리 내의 옷을 삭제할 때 호출되는 함수이다.

FeedbackModal.vue

-enterKeyword(): 사용자가 주어진 문장에 맞는 키워드를 입력하여 엔터를 누를 때 호출되는 함수이다.

-clickFeedback(): 사용자가 피드백 버튼을 누를 때 호출되는 함수이다.

WarningModal.vue

-deleteAccount(): 사용자와 판매자가 계정을 삭제할 때 호출되는 함수이다.

AddKeywordModal.vue

-enterKeyword(): 사용자가 원하는 키워드를 입력했을 때 호출되는 함수이다.

-selectKeyword(); 사용자가 키워드를 선택했을 때 호출되는 함수이다.

-addKeyword(): 사용자가 키워드를 추가했을 때 호출되는 함수이다.

백엔드
세부 패키지 다이어그램

Back pkg diag.png

Controller

프론트엔드와 백엔드를 연결하는 데 사용하는 클래스를 담는다.

Service

실제 백엔드 로직을 처리하는 클래스를 담는다.

Repository

데이터베이스에 접근해 데이터를 가져오는 데 사용하는 클래스를 담는다.

Domain

데이터베이스 테이블에 해당하는 객체(Entity)와 값 객체(VO)를 위한 클래스를 담는다.

DTO

각 계층 간 데이터 교환을 위한 객체들을 담당하는 클래스를 담는다.

Util

백엔드 로직을 처리함에 있어 공통적으로 사용할 수 있는 도구 클래스를 담는다.

Auth

사용자 인증 관련 로직을 수행할 때 사용되는 클래스를 담는다.

Config

AWS, Redis, Spring Security 등 관련 구성요소를 설정할 때 사용하는 클래스를 담는다.

Application

서비스의 진입점을 담당하는 클래스이다.


세부 패키지 별 클래스 다이어그램

◇ Controller

Ctr class diag.png

- ClothesController

옷(Clothes) 데이터와 관련하여 데이터 처리 요청을 받아 결괏값을 반환하는 클래스이다.

- KeywordController

키워드(Keyword) 데이터와 관련하여 데이터 처리 요청을 받아 결괏값을 반환하는 클래스이다.

- MemberController

사용자(Member) 데이터와 관련하여 데이터 처리 요청을 받아 결괏값을 반환하는 클래스이다.

- WishListController

좋아요(WishList) 데이터와 관련하여 데이터 처리 요청을 받아 결괏값을 반환하는 클래스이다.

- ManagerController

관리자의 요청을 받아 결괏값을 반환하는 클래스이다.

- IndexController

관리자 화면 요청을 받아 화면에 데이터를 표시하거나 요청을 전달하는 클래스이다.

◇ Service

Serv class diag.png

- ClothesService

옷(Clothes) 데이터를 가져와 실제 비즈니스 로직을 수행하는 클래스이다.

- KeywordService

키워드(Keyword) 데이터를 가져와 실제 비즈니스 로직을 수행하는 클래스이다.

- WishListService

좋아요(WishList) 데이터를 가져와 실제 비즈니스 로직을 수행하는 클래스이다.

- MemberService

사용자(Member) 데이터를 가져와 실제 비즈니스 로직을 수행하는 클래스이다.

◇ Repository

Cls diag repo.png

- JPARepository

JPA에 특화된 기능이 추가된 인터페이스로, 이걸 상속함으로써 save, find와 같은 메소드들을 사용할 수 있다.

다른 Repository 클래스는 모두 이걸 상속해서 메소드를 구현한다.

- ClothesRepository

옷(Clothes) 데이터베이스에 접근해서 데이터를 가져오고 처리하는 기능을 담당하는 클래스이다.

- KeywordRepository

키워드(Keyword) 데이터베이스에 접근해서 데이터를 가져오고 처리하는 기능을 담당하는 클래스이다.

- WishListRepository

좋아요(WishList) 데이터베이스에 접근해서 데이터를 가져오고 처리하는 기능을 담당하는 클래스이다.

- MemberRepository

사용자(Member) 데이터베이스에 접근해서 데이터를 가져오고 처리하는 기능을 담당하는 클래스이다.

- ClothesWithKeywordRepository

ClothesWithKeyword 데이터베이스에 접근해서 데이터를 가져오고 처리하는 기능을 담당하는 클래스이다.

◇ Domain

Cls diag domain.png

- BaseTimeEntity

시간 값에 대한 변수를 편리하게 관리하도록 만든 클래스이다.

다른 클래스는 이걸 상속해 시간 관련 변수를 지정하지 않아도 되도록 한다.

- Clothes

옷(Clothes) 데이터베이스에 해당한다.

이때 옷 데이터의 경우 키워드 데이터와는 다대다 관계, 사용자 데이터와도 다대다 관계를 맺는다.

- Keyword

키워드(Keyword) 데이터베이스에 해당한다. 옷 데이터와 다대다 관계를 맺는다.

- WishList

좋아요(WishList) 데이터베이스에 해당한다. 옷은 여러 사용자로부터 좋아요를 받을 수 있고, 한 사용자는 여러 옷에 좋아요를 할 수 있다. 이런 측면에서 다대다 관계가 성립하여 이를 매핑하기 위한 클래스이다.

- Member

사용자(Member) 데이터베이스에 해당한다. 옷 데이터와 다대다 관계를 맺는다.

- ClothesWithKeyword

옷과 키워드는 N:N 관계인데, 이때 다대다 관계를 처리하기 위한 데이터베이스이다.

- Authority

사용자의 권한을 나타내는 enum 클래스이다.

판매자와 고객이 있다.

- Category

옷의 카테고리를 나타내는 enum 클래스이다.

- KeywordState

키워드의 상태를 enum 클래스이다.

◇ DTO

Cls diag dto.png

- ClothesResponseDto

옷 데이터를 반환하는 데 사용되는 클래스이다.

- ClothesSaveRequestDto

옷 데이터를 저장할 때 사용하는 클래스이다.

- KeywordResponseDto

키워드 이름 데이터를 반환하는 데 사용되는 클래스이다.

- KeywordSaveRequestDto

키워드 데이터를 저장하는 데 사용되는 클래스이다.

- MemberRegisterRequestDto

회원가입 시 사용자 정보를 받기 위해 사용되는 클래스이다.

- MemberResponseDto

사용자 정보를 반환할 때 사용하는 클래스이다.

- MemberLoginRequestDto

로그인 시 사용자의 입력 정보를 전달하는 데 사용되는 클래스이다.

- ClothesSellerResponseDto

판매자용 옷 데이터를 반환할 때 사용되는 클래스이다.

- ClothesUpdateRequestDto

옷 정보를 수정할 때 사용되는 클래스이다.

- ExtractKeywordResponseDto

옷 이미지에서 키워드를 추출한 후 해당 데이터를 반환하는 데 사용되는 클래스이다.

- MemberUpdateRequestDto

회원 정보 수정 시 정보를 받기 위해 사용되는 사용되는 클래스이다.

- TokenDto

액세스 토큰과 리프레시 토큰을 받을 때 사용되는 클래스이다.

- TokenRequestDto

액세스 토큰과 리프레시 토큰을 전달해 토큰을 갱신할 때 사용되는 클래스이다.

- FeedbackDto

피드백 검색을 할 때 사용되는 클래스이다.

- FeedbackResponseDto

피드백 검색을 한 후 반환되는 데이터를 위해 사용되는 클래스이다.

- ClothesListResponseDto

사용자의 문장을 입력받아 3개의 검색 결과를 표현할 때 하나의 결과를 반환할 때 사용되는 클래스이다.

- ClothesAllResponseDto

사용자의 문장을 입력받아 3개의 검색 결과를 표현할 때 전체 검색 결과를 반환할 때 사용되는 클래스이다.

◇ Auth

Cls diag auth.png

- CustomUserDetailsService

사용자 이메일로 사용자를 불러오며, DB 에 해당 사용자가 있는지 검증하는 로직을 처리하는 클래스이다.

- JwtAccessDeniedHandler

필요한 권한 없이 접근하려 할 때 오류를 발생시키는 클래스이다.

- JwtAuthenticationEntryPoint

유효한 자격증명을 제공하지 않고 접근하려 할 때 오류를 발생시키는 클래스이다.

- JwtFilter

Jwt 필터링 로직을 수행하며, SecurityContext 에 접근해 사용자 정보를 가져오는 클래스이다.

- TokenProvider

액세스 토큰과 리프레시 토큰을 생성 및 제공하는 클래스이다.


◇ Config

Cls diag conf.png

- AwsConfig

AWS 관련 구성요소를 설정할 때 사용하는 클래스이다.

- JwtSecurityConfig

Jwt의 구성요소를 설정할 때 사용하는 클래스이다.

- RedisConfig

Redis 구성요소를 설정할 때 사용하는 클래스이다.

- SecurityConfig

Spring Security 구성요소를 설정할 때 사용하는 클래스이다.

- GrpcConfig

Grpc 구성요소를 설정할 때 사용하는 클래스이다.

◇ Util

Cls diag util.png

- S3Upload

AWS S3 에 이미지를 업로드할 때 사용하는 클래스이다.

- SecurityUtil

Security Context 에 실제 접근해서 JWT 토큰에 기반한 사용자 정보를 가져올 때 사용하는 클래스이다.

AI

◇ Image Classification

Cls diag kw.png

MockImageClassificationServicer

개발에 사용되는 클래스로 가짜 값들은 반환하는 클래스이다.

pb2_grpc.ImageClassificationServicer

gRPC 통신에 사용되는 기능들이 제공되는 클래스이다. 자동으로 생성된다.

ClassSimilarityScoreRequest

클래스 간의 유사도 계산 요청에 사용되는 클래스이다.

ClassSimilarityScoreResponse

클래스 간의 유사도 계산 값 반환에 사용되는 클래스이다.

GetStatussRequest

현재 상태 요청에 사용되는 클래스이다.

GetStatusResponse

현재 상태 반환에 사용되는 클래스이다.

ImageClassificationRequest

이미지 분류 요청에 사용되는 클래스이다.

ImageClassificationResponse

이미지 분류 결과 반환에 사용되는 클래스이다.

ImageClassificationServicer

키워드를 추출하는 모델에 사용하는 클래스로, 이 클래스를 사용해 백엔드와 AI 모델이 상호작용한다.

ImageClassifierInterface

이미지 분류 모델을 공통적으로 사용하기 위해 정의된 인터페이스이다.

CoCoOpCLIP

CoCoOp을 가지며 이를 ImageClassifierInterface에 적절하도록 조정하는 역할을 하는 클래스이다.

ZeroShotCLIP

Zero-shot CLIP을 이용하여 키워드를 분류하는 기능을 제공한다.

CoCoOp

CoCoOp 혹은 CoOp의 방법으로 실제 키워드를 분류하는 로직을 담당하는 클래스이다.

MetaNet

CoCoOp의 instance specific token 생성을 담당하는 모듈이다.

Prompter

연속적이며 학습 가능한 프롬트를 가지는 모듈이다.

BinaryCoCoOpDataModule

Train, validation 데이터 가져오기 등을 수행하는 클래스이다.

CenterPad

사진이 정사각형이 되도록 패딩을 넣는 클래스이다.

BinayCoCoOpDataset

학습 데이터를 학습 때 읽어 오는 클래스이다.

◇ Text-to-Image

Cls diag t2i.png

RetrieveImagesRequest

이미지 리트리벌 요청에 사용되는 클래스이다.

RetrieveImagesResponse

이미지 리트리벌 결과 반환에 사용되는 클래스이다.

AddImagesResponse

이미지 더하기 요청에 사용되는 클래스이다.

AddImagesRequest

이미지 더하기 결과 반환에 사용되는 클래스이다.

DeleteImagesRequest

이미지 삭제 요청에 사용되는 클래스이다.

DeleteImagesRequest

이미지 삭제 결과 반환에 사용되는 클래스이다.

GetStatusRequest

상태 조회 요청에 사용되는 클래스이다.

GetStatusResponse

상태 조회 결과 반환에 사용되는 클래스이다.

Status

상태 값들을 가지는 이누머레이션이다.

pb2_grpc.Text2ImageServicer

gRPC 통신에 사용되는 기능을 가진 클래스이다. 자동으로 생성된다.

Text2ImageServicer

옷의 특성을 자연어 문장으로 검색하는 AI 모델에 사용하는 클래스로, 이 클래스를 사용해 백엔드와 AI 모델이 상호작용한다.

MockText2ImageServicer

가짜 결과 값들을 반환하는 클래스이다. 개발에 사용된다.

Text2ImageRetriever

자연어 문장으로 옷을 검색하는 로직을 담당하는 클래스이다.

◇ Text Conditioned Retrieval

Cls diag text.png

pb2.grpc.TextConditionedRetrievalServicer

gRPC 통신에 사용되는 기능이 구현된 클래스이다. 자동으로 생성된다.

RetrieveImagesRequest

텍스트와 이미지에 대해 적절한 이미지를 가져오는 요청에 대한 클래스이다.

RetrieveImagesResponse

텍스트와 이미지에 대해 적절한 이미지를 가져오는 결과 반환에 대한 클래스이다.

AddImagesRequest

검색될 수 있도록 이미지를 더하는 요청에 대한 클래스이다.

AddImagesResponse

이미지를 더하는 요청에 대한 결과 반환과 관련된 클래스이다.

GetStatusRequest

상태 조회 요청을 위한 클래스이다.

GetStatusResponse

상태 조회 요청의 반환 값을 가지는 클래스이다.

DeleteImagesRequest

등록된 이미지 삭제 요청에 쓰이는 클래스이다.

DeleteImagesResponse

등록된 이미지 삭제 요청에 대한 결과를 가지는 클래스이다.

MockTextConditionedRetrievalServicer

가짜 결과 반환 값 반환 기능을 가진 클래스이다.

TextConditionedRetrievalServicer

이미지와 텍스트에 대해 적절한 이미지를 검색하는 기능을 백엔드에 제공하는 클래스이다.

TextConditionedRetriever

이미지와 텍스트에 대해 적절한 이미지를 검색하는 기능을 실제로 수행하는 클래스이다.

Status

상태 값에 대한 이누머레이션이다.

Resources

Cls diag rsc.png

static

Cls diag static.png

Index

관리자 화면에서 요청을 받으면 비즈니스 로직을 실행해 백엔드 API를 호출하는 것을 담당하는 요소이다.

templates

Cls diag temp.png

clothes.mustache

옷을 관리하는 화면을 담당하는 요소이다.

keyword.mustache

키워드를 관리하는 화면을 담당하는 요소이다.

footer.mustache

관리자 화면의 기본 설정을 관리하는 요소이다.

header.mustache

관리자 화면의 기본 설정을 관리하는 요소이다.

index.mustache

관리자 화면의 초기 화면을 담당하는 요소이다.

Usecase 별 Sequence Diagram

Login

Seq login.png

Alt 1. 판매자 또는 고객의 경우

1. 사용자가 Header에서 clickAccount() 함수를 통해 기능 선택을 준비한다.

2. 기능들 중 로그인 버튼을 눌러 selectedOption() 함수를 호출해 로그인 화면으로 이동한다.

3. 로그인 화면에서 사용자 정보를 입력한 후, MemberController의 login() 함수를 호출해 로그인 요청을 보낸다.

이때는 사용자 정보를 담은 MemberLoginRequestDto를 전달한다.

4. MemberController 에서 MemberService 에 로그인 처리를 맡긴다.

5. MemberService 는 전달받은 데이터를 바탕으로 authenticationToken 을 만들고,

AuthenticationManagerBuilder 클래스의 getObject.authenticate() 함수를 호출해 해당 데이터를 전달한다.

6. 이를 통해 Authentication 객체를 반환받는다.

7. TokenProvider 의 generateTokenDto() 함수를 호출하고 앞선 Authentication 객체를 전달한다.

8. TokenProvider 는 액세스 토큰과 리프레시 토큰을 만들고, TokenDto 를 반환한다.

9. RedisTemplate 클래스의 opsForValue.set() 함수를 호출해 해당 토큰에 대한 정보를 설정한다. 이때는 name, refreshToken, expireTime, TimeUnit 을 전달한다.

10. MemberService는 TokenDto 를 반환한다.

11. MemberController는 TokenDto를 반환해 Login.vue 단에 전달한다. 사용자는 이후 모든 요청의 Header 에 해당 JWT 토큰을 전달해서 사용자 정보를 바로 식별하거나 인증할 때 사용한다.

Opt 1. 사용자 정보 가져오는 경우

12. SecurityUtil의 getCurrentMemberId() 함수를 호출해 현재 JWT 토큰에 해당하는 사용자 id를 요청한다.

13. memberId를 반환받는다.

14. MemberRepository의 findById() 함수를 호출하고 memberId를 전달해 Member를 요청한다.

15. Member 객체를 반환받는다.

Alt 2. 관리자의 경우

16. 인증 코드를 입력하고, 옷 또는 키워드 버튼을 클릭한다.

17 ~ 18. index.mustache 는 index 파일의 get_clothes() 또는 get_keyword() 함수를 호출해 해당 기능을 요청한다.

19. index 파일은 인증 코드를 검증하고, 이후 관리자가 선택한 화면을 표시한다.

Manage Member

Seq mng mem.png

공통

1. 사용자가 clickAccount() 함수를 통해 Header에서 Account를 클릭한다.

Opt 1. Register

2. Account에서 selectOption() 함수를 통해 로그인 화면으로 이동한다.

3. 로그인 화면에서 clickOption() 함수를 통해 회원가입 창으로 이동한다.

4. 회원가입 화면에서 사용자 정보를 입력한 후, MemberController 의 register() 함수를 호출해 회원가입 요청을 보낸다.

이때 사용자 정보를 담은 MemberRegisterRequestDto 를 전달한다. 5. MemberController는 MemberService 의 register() 함수를 통해 사용자 정보 저장을 요청한다.

이때도 MemberController에서 전달받았던 데이터를 전달한다.

6. MemberServic는 MemberRepository의 existsByEmail() 함수를 호출하고 사용자의 email 을 전달해, 해당 사용자의 회원가입 여부를 판별한다.

7. 이후 회원가입되어있지 않은 사용자라면, requestDto 로 Member 를 만든 후, MemberRepository의 save() 함수를 호출해 회원 정보를 저장한다.

Opt 2. Withdrawal

8. Account에서 selectOption() 함수를 통해 MyPage 화면으로 이동한다.

9. MyPage 화면에서 회원탈퇴 버튼을 눌러서, MemberController 의 withdrawal() 함수를 호출한다.

10. MemberController는 MemberService 의 withdrawal() 함수를 호출해 회원 정보 삭제를 요청한다.

Alt 1. 고객이라면

11. WishListRepository의 deleteByMember() 함수를 호출해 Member 를 전달해서 해당 고객의 좋아요 목록을 모두 제거한다.

Alt 2. 판매자라면

12. ClothesService의 findBySeller() 함수를 호출하고 memberId를 전달해 해당 사용자의 옷 목록을 요청한다.

13. Clothes의 List를 반환받는다.

14. 앞서 받았던 Clothes의 List를 Id들만 추출하여 ClothesDeleteRequestDto 를 만든다.

그리고 ClothesService의 deleteByIdFromSellers() 함수를 호출하고 이때 해당 데이터를 전달한다.

이를 통해 해당 판매자가 올린 옷을 제거한다.

15. KeywordRepository의 deleteAllByCreator() 함수를 호출하고 사용자의 email 을 전달해서 해당 판매자가 올린 키워드를 모두 제거한다.

16. MemberRepository의 deleteById() 함수를 호출하고 사용자의 id를 전달해서 해당 사용자 정보를 제거한다.

Opt 3. ReviseUser

17. Account 에서 selectOption() 함수를 호출해 MyPage 화면으로 이동한다.

18. MyPage 화면에서 회원정보를 수정하고 편집 버튼을 눌러, MemberController 의 updateMember() 함수를 호출한다.

이때 수정된 정보를 담은 MemberUpdateRequestDto 를 전달한다.

19. MemberService 의 update() 함수를 호출해 수정 로직을 진행한다.

20. PasswordEncoder 의 matches() 함수를 호출하고 reqeustDto의 password 랑 원래 사용자의 password를 비교한다.

Alt 1. password가 둘이 일치한다면

21. request를 전달한 후, Member의 update() 함수를 호출해서 정보를 갱신한다.

Alt 2. password가 둘이 일치하지 않으면

22. Member의 update() 함수를 호출하고, 이때 비밀번호도 갱신해야 하므로, request와 passwordEncoder를 같이 전달한다.

23. 새로 바뀐 사용자 정보를 담은 MemberResponseDto를 반환한다.

24. 해당 데이터를 MyPage.vue 로 전달해서 사용자 화면에 표시한다.


Manage Keyword

Seq mng kw.png

Alt 1. 판매자의 경우

Opt 1. Get Keyword

1. 옷 추가 버튼을 눌러 clickAddClothes() 함수를 호출해 SellerAddClothes 화면으로 이동한다.

2. clickAddKeyword() 함수를 호출해 키워드를 조회 및 추가할 수 있는 모달창을 띄운다.

3. 검색어 이름을 입력한 후 KeywordController 의 findKeywordByName() 함수를 호출해 키워드 조회를 요청한다. 이때 Name 을 전달한다.

4. KeywordController 에선 KeywordService 의 findByName() 함수를 호출해서 이름에 매치되는 키워드를 조회한다.

5. KeywordRepository의 findAllAndFromCreatorByName() 함수를 호출하고, 이때 관리자가 추가한 키워드와 판매자가 추가한 키워드만 조회되도록 Manager, 판매자의 email, name을 전달한다.

Alt. 만일 입력받은 이름에 해당하는 키워드가 있을 경우

6. KeywordResponseDto의 List 를 반환받는다.

Alt. 만일 입력받은 이름에 해당하는 키워드가 없을 경우

7. keywordRepository의 findAllFromCreator() 함수를 호출하고 현재 판매자의 email 을 전달해 판매자가 추가한 키워드 리스트를 요청한다.

8. Keyword의 List 를 반환받는다.

9. 키워드 분류 모델 서버에 키워드 유사도 계산 요청을 보낸다.

10. 키워드 분류 클래스를 가지고 있는 클래스에 키워드 유사도 계산 메소드를 호출한다.

11. 적절한 키워드인지 판단하도록 학습된 프롬트와 키워드를 이용해 텍스트 임베딩을 계산하는 메소드를 호출한다.

12. 계산된 텍스트 임베딩을 전달한다.

13. 적절하지 않은 키워드인지 판단하도록 학습된 프롬트와 키워드를 이용해 텍스트 임베딩을 계산하는 메소드를 호출한다.

14. 계산된 텍스트 임베딩을 전달한다.

15. 입력된 클래스와 등록되어 있는 클래스에 대해 계산된 유사도를 반환한다.

16. 입력된 키워드에 대해 계산된 유사도를 백엔드 서버에 전달한다.

17. 키워드의 이름 리스트의 길이, 또는 3번 반복한다.

KeywordRepository의 findByNameForLearn() 함수를 호출하고 nameForLearn 을 전달해서 해당 키워드를 찾는다.

18. Keyword 를 반환받는다.

19~20. KeywordResponseDto 를 반환받아 SellerAddClothes 화면으로 전달해 화면에 표시한다.

Opt 2. Add Keyword

만일 검색한 키워드가 존재하지 않을경우, 키워드 추가 버튼이 표시된다.

21. 키워드를 입력하고 clickAddNewKeyword() 함수를 호출해 검색어 추가 기능을 진행한다.

22. KeywordController 의 saveKeyword() 함수를 호출해 검색어를 추가한다.

이때 키워드 정보는 keywordSaveReqeustDto 로 담아서 전달한다.

23. KeywordController 는 KeywordService 의 save() 메소드를 호출해 키워드 추가를 맡긴다.

24. KeywordRepository의 save() 함수를 호출하고, 이때 requestDto를 바탕으로 만든 Keyword 객체를 전달한다.

Opt 3. Delete Keyword

25. 사용자가 Header 에서 clickAccount() 함수를 호출해 기능 선택을 준비한다.

26. MyPage 버튼을 눌러 selectedOption() 함수를 호출해 MyPage 화면으로 이동한다.

27. 키워드 삭제 버튼을 누르면 KeywordController의 deleteKeywordById() 함수를 호출해 키워드 삭제를 진행한다. 이때는 해당 키워드의 id 값을 전달한다.

28. KeywordController는 KeywordService 의 deleteById() 함수를 사용해 키워드 삭제를 진행한다.

29. KeywordRepository의 findById() 함수를 호출하고 id를 전달해서 해당 키워드 객체를 요청한다.

30. 키워드 객체를 반환받는다.

31. ClothesWithKeywordRepository 에서 deleteByKeyword() 함수를 호출해 keyword 를 갖는 항목들을 모두 제거한다.

32. KeywordRepository의 deleteById() 함수를 호출해 실제 Keyword 테이블에서 해당 키워드를 제거한다.

Alt 2. 관리자의 경우

33. 관리자는 인증 코드를 입력한 후 키워드 버튼을 누른다.

34. index 파일의 get_keyword() 함수를 호출한다.

35. IndexController의 getKeyword() 함수를 호출한다.

36. KeywordService의 findAllKeyword() 함수를 호출한다.

37~38. Keyword의 List를 반환받아 화면에 키워드 정보를 표시한다.

Opt 1. Add Keyword

39. 키워드 정보를 입력한 후, 키워드 저장 버튼을 누른다.

40. index 파일의 save_keyword() 함수를 호출한다.

41. ManagerController의 saveKeyword() 함수를 호출하고, 이때 키워드 정보를 담은 KeywordSaveRequestDto를 전달한다.

42. KeywordService의 saveFromManager() 함수를 호출하고 데이터를 전달한다.

43. KeywordRepository의 save() 함수를 호출하고, requestDto를 Keyword 객체로 만든 후 전달한다.

이를 통해 키워드를 저장한다.

Opt 2. Delete Keyword

44. 키워드 삭제 버튼을 누른다.

45. index 파일의 delete_keyword() 함수를 호출한다. 이때 선택된 키워드의 id를 전달한다.

46. ManagerController의 deleteKeyword() 함수를 호출하고, 이때 키워드 id를 전달한다.

47. KeywordService의 deleteByIdFromManager() 함수를 호출한다.

48. KeywordRepository의 findById() 함수를 호출하고 키워드 id를 전달해, 해당 키워드 객체를 요청한다.

49. Keyword 객체를 반환받는다.

50. ClothesWithKeywordRepository의 deleteByKeyword()를 호출하고 해당 keyword 객체를 전달해서 목록을 삭제한다.

51. KeywordRepository의 deleteById() 함수를 호출하고 keyword id를 전달해서 해당 키워드를 제거한다.


Manage Clothes - 판매자

Seq mng clth s.png

Opt 1. Get Clothes

1. 판매자가 Header 에서 clickAccount() 함수를 호출해 기능 선택을 준비한다.

2. 로그인 버튼을 누르면 selectedOption() 함수를 호출해 로그인 화면으로 이동한다.

3. 로그인이 완료되면 SellerAll 화면으로 이동한다.

4. 해당 화면에서 판매자가 올린 옷들을 불러오기 위해 ClothesController 의 findAllClothes() 함수를 호출해 옷 조회 기능을 실행한다.

이때는 sort 와 category 를 전달한다.

5. ClothesService 의 findAll() 함수를 호출해 옷 조회 기능을 진행한다.

6. ClothesRepository 의 findAll() 함수를 호출해서 Clothes 데이터베이스에 접근해 전체 옷 데이터를 반환한다.

7. Clothes 의 리스트를 반환받는다.

8. 반환받은 각각의 Clothes 에 대해서, ClothesWithKeywordRepository 의 findAllByClothes() 함수를 호출해 해당 옷에 대한 전체 키워드를 반환받는다.

9. ClothesWithKeyword 의 List 를 반환받는다.

10. WishListRepository의 existByMemberAndClothes() 함수를 호출해서 사용자가 해당 옷에 대해 좋아요를 했는지 여부를 요청한다.

11. 좋아요 여부를 반환받는다.

12. WishListRepository의 findAllByClothes() 함수를 호출하고 clothes를 전달해서 총 좋아요 수를 요청한다.

13. wishListSize를 반환한다.

14 ~ 15. 이 정보들을 바탕으로 ClothesResponseDto 의 리스트를 만들어 사용자 화면에 표시한다.

Opt 2. Add Clothes

16. 판매자가 Header 에서 clickAddClothes() 함수를 호출한다.

17. SellerAddClothes 화면으로 이동한다.

18. 옷 이미지를 업로드한 후 ClothesController 의 extractKeyword() 함수를 호출해 키워드 추출을 진행한다.

이때 옷 이미지를 MultipartFile 형식으로 전달한다.

19. ClothesController 는 ClothesService 의 uploadImage() 함수를 호출해 키워드 추출을 실행한다.

20. S3Upload의 upload() 함수를 호출하고 이미지를 전달해서 해당 이미지를 S3 저장소에 저장한다.

21. 해당 이미지의 url 을 반환받는다.

22. KeywordRepository의 findAllFromCreator() 함수를 호출하고 사용자의 email을 전달해서 해당 판매자가 올린 키워드를 모두 요청한다.

23. List<Keyword>를 반환받는다.

24. 해당 옷의 이미지를 ImageClassificationServicer 의 ClassifyImage() 메소드를 호출해 전달한다.

25. CoCoOpCLIP의 classify_image() 메소드를 호출해서 분류를 진행한다.

26. CoCoOp 클래스의 predict() 메소드를 호출해 실제 이미지 분류를 진행한다.

27. 각 클래스에 대한 로짓을 반환한다.

28. 각 클래스에 대한 로짓을 정규화한 뒤 딕셔너리 형태로 반환한다.

29. ImageClassificationServicer 는 해당 결과를 받아 ImageClassificationResponse 로 ClothesService 에 반환한다.

30. 반환받은 데이터에서 Keyword의 개수만큼 반복문을 돌린다.

먼저 학습 시 사용한 키워드 이름을 반환받으므로, KeywordRepository의 findByNameForLearn() 함수를 사용해 Keyword 객체를 요청한다.

31. 키워드 객체를 반환받는다.

그리고 키워드와 Score를 바탕으로 리스트에 저장한다.

32 ~ 33. 해당 데이터들을 ExtractKeywordResponseDto 로 만들어, 반환한다.

34. 판매자는 옷에 대한 세부정보를 입력한 후, ClothesController 의 saveClothes() 함수를 호출하고 ClothesSaveRequestDto 를 전달한다.

35. ClothesService 의 saveFromSeller() 함수를 호출해 옷 저장 기능을 진행한다.

36. ClothesService 에서 Text2ImageServicer의 AddImages() 함수를 호출해서 문장 검색용 AI 모델 데이터 저장을 요청한다.

37. Text2ImageRetriever 클래스의 add_images() 메소드를 호출해 데이터셋에 저장한 후 분석을 진행한다.

38. 임베딩 인덱스에 해당하는 값들을 반환한다.

39. Text2ImageServicer에서 AddImagesResponse 를 ClothesService 로 반환한다.

40. ClothesService 는 TextConditionedRetrievalServicer의 AddImages() 메소드를 호출해 피드백 검색용 AI 모델 데이터 저장을 요청한다.

41. TextConditionedRetriever 클래스의 add_images() 메소드를 호출해 데이터셋에 저장한 후 분석을 진행한다.

42. 임베딩 인덱스에 해당하는 값들을 반환한다.

43. AddImagesResponse 값을 반환한다.

44. ClothesRepository 의 save() 함수를 호출해 데이터베이스에 옷을 저장한다.

45. 현재 옷에 해당하는 키워드 리스트만큼 반복문을 돌리고,

이때 KeywordRepository의 findByName() 함수를 호출해서 Keyword 객체를 요청한다.

46. Keyword 객체를 반환받는다.

47. ClothesWithKeywordRepository의 save() 함수를 호출해서 해당 키워드와 옷을 매핑한 ClothesWithKeyword 객체를 저장한다.

Opt 3. Delete Clothes

48. SellerAll 화면에서 옷 삭제 버튼을 눌러 ClothesController의 deleteClothes() 함수를 호출하고, 이때 옷의 id 를 전달한다.

49. ClothesService 의 deleteByIdFromSeller() 함수를 호출해서 옷 삭제 기능을 진행한다.

50. ClothesRepository의 findById() 함수를 호출하고 id를 전달해서 Clothes 객체를 요청한다.

51. Clothes 객체를 반환받는다.

52. ClothesWithKeywordRepository의 deleteByClothes() 함수에 Clothes를 전달해서 호출해 키워드와 매핑된 목록을 제거한다.

53. WishListRepository의 deleteByClothes() 함수를 호출하고 Clothes를 전달해서 해당 옷에 좋아요를 한 목록을 제거한다.

54. ClothesService 에서 Text2ImageServicer의 DeleteImages() 함수를 호출해서 AI 모델의 데이터셋에서도 삭제를 요청한다.

55. Text2ImageRetriever 의 delete_image_embeds() 함수를 호출해 모델에서 삭제한다.

56. DeleteImagesResponse 를 반환한다.

57. TextConditionedRetrievalServicer의 DeleteImages() 함수를 호출해서 다른 모델의 데이터셋에서도 삭제를 요청한다.

58. TextConditionedRetriever의 delete_image_embeds를 통해 삭제한다.

59. DeleteImagesResponse를 반환한다.

60. 최종적으로 ClothesRepository의 deleteById() 함수를 호출하고 id를 전달해서 옷을 제거한다.

Opt 4. Revise Clothes

61. 수정할 옷을 클릭해 SellerAddClothes 화면에 진입한 후, 수정할 정보를 입력한 다음 버튼을 누른다.

그러면 ClothesController의 updateClothes() 함수를 호출할 수 있고, 이때 수정할 정보를 전달한다.

62. ClothesController에서 ClothesService의 updateById()를 호출해 옷 수정 기능을 진행한다.

63. ClothesService에선 ClothesRepository의 findById() 함수를 호출해 해당 옷 정보를 요청한다.

64. Clothes 객체를 반환받는다.

65. ClothesWithKeywordRepository의 findByClothes() 함수를 호출하고 clothesId를 전달해 해당 옷에 있던 키워드 아이디 리스트를 요청한다.

66. 키워드 아이디의 리스트를 반환받는다.

67. 원래 키워드에 있던 아이디 리스트 개수만큼 반복문을 돌린다.

이때 KeywordRepository의 findByNameForDisplay() 함수를 호출하고 id를 전달해서 Keyword 객체를 요청한다.

68. Keyword 객체를 반환받는다.

69. 해당 키워드를 사용자가 제거하도록 했다면, ClothesWithKeywordRepository의 deleteByClothesAndKeyword() 함수를 호출하고 옷과 키워드를 전달해 제거한다.

70. 사용자가 요청한 키워드 아이디 리스트 개수만큼 반복문을 돌린다.

KeywordRepository의 findByNameForDisplay(() 함수를 호출하고 id를 전달해서 Keyword 객체를 요청한다.

71. Keyword 객체를 반환받는다.

72. 해당 키워드를 추가해야 한다면, ClothesWithKeywordRepository의 save() 함수를 호출하고 ClothesWithKeyword 객체를 전달한다.

73. WishListRepository의 findAllByClothes() 함수를 호출하고 clothes 를 전달해 해당 옷의 좋아요 개수를 요청한다.

74. wishListSize를 반환받는다.

75 ~ 76. ClothesSellerResponseDto 를 반환받는다.

Manage Clothes – 관리자

Seq mng clth mng.png

Opt 1. Get Clothes

1. 관리자가 옷 버튼을 눌러(clickClothesButton) 옷 조회 화면으로의 이동을 요청한다.

2. index.mustache는 index.js 파일의 get_clothes() 함수를 호출해서 옷 목록을 요청한다.

3. indexController의 getClothes() 파일을 호출한다.

4. ClothesService의 findAllClothes() 함수를 호출해서 전체 옷 목록을 표시한다.

5. ClothesRepository의 findAll() 함수를 호출해서 전체 옷 데이터를 요청한다.

6~7. Clothes의 List를 반환받는다.

8. IndexController에선 clothes.mustache 화면으로 이동하고, 해당 데이터를 model에 설정해 화면에 표시한다.

Opt 2. Add Clothes

9. 관리자가 엑셀 형태의 옷 목록 파일을 업로드한다.

10. clothes.mustache 에선 index.js 의 save_clothes() 함수를 호출해 옷 저장을 요청한다.

11. ManagerController의 saveClothes() 함수를 호출하고, MultipartHttpServletRequest 형태로 엑셀 파일을 전달한다.

12. ClothesService의 saveFromManager() 함수를 호출하고 앞선 데이터를 request 로 전달한다.

13. 전체 엑셀에 있는 행의 개수, 즉 항목의 개수만큼 반복문을 돌린다.

먼저 ClothesService는 자기 자신에게 있는 extractKeyword() 함수를 호출하고 이미지의 url을 넘긴다.

14. 해당 옷의 이미지를 ImageClassificationServicer 의 ClassifyImage() 함수를 호출해 전달한다.

15. CoCoOpCLIP의 classify_image() 함수를 호출해서 분류 요청을 전달한다.

16. CoCoOp 클래스에게 이미지 분류를 요청한다.

17. 각 키워드에 해당하는 로짓을 반환한다.

18. 로짓들을 정규화한 뒤 딕셔너리 혀태로 반환한다.

19. ImageClassificationServicer 는 해당 결과를 받아 ImageClassificationResponse 로 ClothesService 에 반환한다.

20. 반환받은 데이터에서 Keyword의 개수만큼 반복문을 돌린다.

먼저 학습 시 사용한 키워드 이름을 반환받으므로, KeywordRepository의 findByNameForLearn() 함수를 사용해 Keyword 객체를 요청한다.

21. 키워드 객체를 반환받는다.

그리고 키워드와 Score를 바탕으로 리스트에 저장한다.

22. ClothesService 에서 Text2ImageServicer의 AddImages() 함수를 호출해서 문장 검색용 AI 모델 데이터 저장을 요청한다.

이때는 앞서 만든 데이터 리스트에서 옷의 이미지만을 따로 리스트로 만들어서 전달한다.

23. Text2ImageRetriever 클래스의 add_images() 함수를 호출해 이미지에 대한 임베딩을 저장한다.

24. 이후 임베딩에 대한 인덱스 값들을 값을 반환한다.

25. Text2ImageServicer에서 AddImagesResponse 를 ClothesService 로 반환한다.

26. ClothesService 는 ImageRetrievarConditionedOnTextServicer 의 AddImages() 함수를 호출해 피드백 검색용 AI 모델 데이터 저장을 요청한다.

27. TextConditionedRetriever 클래스의 add_images() 함수를 호출해 이미지에 대한 임베딩을 계산한 뒤 저장한다.

28. 추가된 임베딩에 해당하는 인덱스들을 반환한다.

29. AddImagesResponse 값을 반환한다.

30. 현재 옷의 id 개수만큼 반복문을 돌린다.

먼저 ClothesRepository 의 save() 함수를 호출해 데이터베이스에 옷을 저장한다.

31. 현재 옷에 해당하는 키워드 리스트만큼 반복문을 돌리고,

이때 KeywordRepository의 findByName() 함수를 호출해서 Keyword 객체를 요청한다.

32. Keyword 객체를 반환받는다.

33. ClothesWithKeywordRepository의 save() 함수를 호출해서 해당 키워드와 옷을 매핑한 ClothesWithKeyword 객체를 저장한다.

Opt 3. Delete Clothes

34. 관리자는 옷 삭제 버튼(clickDeleteButton)을 눌러 옷 삭제 요청을 한다.

35. clothes.mustache는 index.js 파일의 delete_clothes() 함수를 호출한다.

36. index.js 파일은 ManagerController의 deleteClothes() 함수를 호출하고 이때 해당 옷의 id를 전달한다.

37. ClothesService의 deleteByIdFromManager() 함수를 호출하고 id를 전달한다.

38. ClothesRepository의 findById() 함수를 호출하고 id를 전달해서 Clothes 객체를 요청한다.

39. Clothes 객체를 반환받는다.

40. ClothesWithKeywordRepository의 deleteByClothes() 함수에 Clothes를 전달해서 호출해 키워드와 매핑된 목록을 제거한다.

41. WishListRepository의 deleteByClothes() 함수를 호출하고 Clothes를 전달해서 해당 옷에 좋아요를 한 목록을 제거한다.

42. ClothesService 에서 Text2ImageServicer의 DeleteImages() 함수를 호출해서 AI 모델의 데이터셋에서도 삭제를 요청한다.

43. Text2ImageRetriever 의 delete_image_embeds() 함수를 호출해 모델에서 삭제한다.

44. DeleteImagesResponse 를 반환한다.

45. ImageRetrieverConditionedOnTextServicer 의 DeleteImages() 함수를 호출해서 다른 모델의 데이터셋에서도 삭제를 요청한다.

46. TextConditionedRetriever의 delete_image_embeds() 를 통해 삭제한다.

47. DeleteImagesResponse를 반환한다.

48. 최종적으로 ClothesRepository의 deleteById() 함수를 호출하고 id를 전달해서 옷을 제거한다.

Manage WishList

Seq mng wish.png

Opt 1. Get WishList

1. 사용자가 Header 에서 clickAccount() 함수를 호출해 WishList 화면으로 이동을 요청한다.

2. Header에서 selectedOption() 함수를 호출해 WishList.vue 화면으로 이동한다.

3. WishList 화면에서 MemberController의 findClothesInWishLists() 함수를 호출해서 사용자 좋아요 목록을 조회한다.

4. MemberService의 findClothesInWishList() 함수를 호출한다.

5. WishListRepository의 findAllByMember() 함수를 호출해 사용자의 wishList 목록을 요청한다.

이때 로그인시 받았던 JWT 토큰을 사용해 사용자 객체를 얻고, 사용자의 memberId를 전달한다.

6. WishList의 List를 반환받는다.

7. WishList의 List만큼 반복문을 돌려서, getClothesResponse() 함수를 호출하고 Clothes 와 score, Member를 전달한다.

8. ClothesWithKeywordRepository 를 사용해, 현재 조회했던 각각의 옷에 대해 Keyword 들을 추출한다.

9. List<ClothesWithKeyword> 를 반환받는다. 그리고 이것을 통해 각각의 옷에 대한 Keyword 의 List를 추출한다.

10. WishListRepository의 existByMemberAndClothes() 함수를 호출하고 Member와 Clothes객체를 전달한다.

11. 좋아요를 했는지에 대한 여부를 나타내는 isLiked를 반환받는다.

12. WishListRepository의 findAllByClothes() 함수를 호출하고 Clothes 객체를 전달한다.

13. 총 좋아요 수 wishListSize를 반환받는다.

14~ 15. 해당 데이터를 ClothesResponseDto 로 변환해 List 형태로 전달한다.

이를 화면에 표시한다.

Opt 2. Add Or Delete WishList

16. 사용자가 옷의 좋아요 버튼을 눌러 WishListController의 saveWishList() 함수를 호출한다.

이때는 사용자 id 와 옷 id 값을 WishListRequestDto 로 감싸서 전달한다.

17. 사용자가 좋아요를 한 옷에 대해 좋아요 버튼을 다시 눌러, WishListController 의 deleteWishList() 함수를 호출해 좋아요 삭제를 요청한다.

이때 userId 와 clothesId 를 감싼 WishListRequestDto 를 전달한다.

18. 사용자는 WishList 화면에서도 옷에 대해 좋아요 버튼을 다시 눌러 동일한 기능을 요청할 수 있다.

19. WishListService의 addOrDelete() 함수를 호출하고, 전달받은 requestDto를 파라미터로 넘긴다.

20. MemberRepository의 findById() 함수를 호출하고 memberId를 전달한다.

21. Member 객체를 반환한다.

22. ClothesRepository의 findById() 함수를 호출하고 clothesId를 전달한다.

23. Clothes 객체를 반환받는다.

그리고 Member 객체와 Clothes 객체를 WishList객체로 변환한다.

24. WishListRepository의 existByMemberAndClothes() 함수를 호출하고 Member와 Clothes를 전달한다.

25. 이미 좋아요를 했는지 여부를 나타내는 isInWishList를 반환받는다.

26. 만일 좋아요를 하지 않았다면, WishListRepository의 save() 함수를 호출하고 WishList 객체를 전달해 저장한다.

27. 만일 좋아요를 했었다면, WishListRepository의 deleteByMemberAndClothes() 함수를 호출하고 Member와 Clothes객체를 전달해 해당 좋아요 항목을 제거한다.

Search Clothes

Seq search cth.png

Opt 1. Input Search

1. 사용자는 Header.vue 에서 문장을 입력하고 검색한다.

2. ClothesController의 findClothesByInput()를 호출하고 sentence, sort, category 를 전달한다.

3. ClothesService의 findByInput() 함수를 호출하고 sentence, sort, category 를 전달한다.

4. Text2ImageServicer의 RetrieveImages() 함수를 실행해 자연어를 AI 모델로 전달한다.

5. Text2ImageRetriever 의 retrieve_images() 함수를 통해 검색을 실행한다.

6. Tuple 형태로 결과값을 반환받는다.

7. Text2ImageServicer 에선 RetrieveImagesResponse 를 반환한다.

여기서 Clothes 들의 Id 값들의 리스트를 추출한다.

8. ClothesId들의 리스트만큼 반복문을 돌린다.

ClothesRepository 의 findByModelForSentenceId() 함수를 호출하고 id를 전달해서 Clothes 객체를 요청한다.

9. Clothes 객체를 반환받는다.

10. 키워드 분류 모델 서버에 키워드 유사도 계산 요청을 보낸다.

11. 키워드 분류 클래스를 가지고 있는 클래스에 키워드 유사도 계산 메소드를 호출한다.

12. 적절한 키워드인지 판단하도록 학습된 프롬트와 키워드를 이용해 텍스트 임베딩을 계산하는 메소드를 호출한다.

13. 계산된 텍스트 임베딩을 전달한다.

14. 적절하지 않은 키워드인지 판단하도록 학습된 프롬트와 키워드를 이용해 텍스트 임베딩을 계산하는 메소드를 호출한다.

15. 계산된 텍스트 임베딩을 전달한다.

16. 입력된 클래스와 등록되어 있는 클래스에 대해 계산된 유사도를 반환한다.

17. 계산된 키워드 유사도를 백엔드 서버에 반환한다.

18. 키워드 이름 리스트만큼 반복한다.

KeywordRepository 의 findByNameForLearn() 함수를 호출하고 nameForLearn 을 전달한다.

19. Keyword 를 반환한다.

20. ClothesWithKeywordRepository 의 findAllByKeyword() 를 호출하고 keyword 를 전달해서 해당 키워드를 갖는 모든 옷 데이터를 요청한다.

21. List<ClothesWithKeyword> 를 반환받는다.

22. 이름 리스트만큼 반복한다.

ClothesRepository 의 findByNameContainsIgnoreCase() 함수를 호출해, 해당 이름을 포함하는 이름을 가진 옷들의 List 를 요청한다.

23. List<Clothes> 를 반환받는다.

24 ~ 25. ClothesAllResponseDto 를 만들어서 반환하고, 화면에 검색 결과를 표시한다.

Opt 1-1. Sentence Search

26. 사용자가 더보기 버튼을 클릭해 문장 검색 결과 더보기를 요청한다.

27. ClothesController 의 findClothesBySentence() 함수를 호출한다. 이때 사용자가 입력한 문장과 sort, category를 전달한다.

28. ClothesService 의 findBySentence() 함수를 호출해 자연어 문장 검색 기능을 진행한다.

29. Text2ImageServicer의 RetrieveImages() 함수를 실행해 자연어를 AI 모델로 전달한다.

30. Text2ImageRetriever 의 retrieve_images() 함수를 통해 검색을 실행한다.

31. Tuple 형태로 결과값을 반환받는다.

32. Text2ImageServicer에선 RetrieveImagesResponse 를 반환한다.

여기서 Clothes 들의 Id 값들의 리스트를 추출한다.

33. ClothesId들의 리스트만큼 반복문을 돌린다.

ClothesRepository 의 findByModelForSentenceId() 함수를 호출하고 id를 전달해서 Clothes 객체를 요청한다.

34. Clothes 객체를 반환받는다.

35 ~ 36. ClothesResponseDto 의 List 를 만들어서 반환하고, SearchSentence 화면에 검색 결과를 표시한다.

Opt 1-2. Name Search

37. 사용자가 더보기 버튼을 클릭해 이름 검색 결과 더보기를 요청한다.

38. ClothesController 의 findClothesByName() 함수를 호출해 이름 검색 기능을 요청한다. 이때는 이름과 sort, category를 전달한다.

39. ClothesService 의 findByName() 함수를 호출해 이름 검색 기능을 진행한다.

40. 이름 리스트만큼 반복한다.

ClothesRepository 의 findByNameContainsIgnoreCase() 함수를 호출해, 해당 이름을 포함하는 이름을 가진 옷들의 List 를 요청한다.

41. List<Clothes> 를 반환받는다.

42 ~ 43. ClothesResponseDto 의 List 를 만들어서 반환하고, SearchName 화면에 검색 결과를 표시한다.

Opt 1-3. Keyword Search

44. 사용자가 검색하려는 키워드를 클릭해 키워드 검색 결과 더보기를 요청한다.

45. ClothesController의 findClothesByKeywordName() 함수를 호출한다. 이때 사용자가 입력한 키워드와 sort, category 를 전달한다.

46. ClothesService 의 findByKeywordName() 함수를 통해 키워드 검색 기능을 진행한다.

47. KeywordRepository 의 findByNameDisplay() 함수를 통해 입력값에 해당하는 키워드를 요청한다.

48. 키워드의 List를 반환한다.

49. 키워드 List 의 크기만큼 반복한다.

ClothesWithKeywordRepository 의 findAllByKeyword() 를 통해 해당 키워드를 갖는 모든 옷 데이터를 요청한다.

50. List<ClothesWithKeyword> 를 반환받는다.

51 ~ 52. ClothesResponseDto 의 List 를 만들어서 반환하고, SearchKeyword 화면에 검색 결과를 표시한다.

Opt 2. Feedback Search

53. UserAll 화면에서 사용자가 피드백을 입력한 후 ‘검색’ 버튼을 누른다.

54. ClothesController 의 findClothesByFeedback() 함수를 호출한다. 이때 피드백 문장과 이미지 url을 담은 requestDto를 전달한다.

55. ClothesService 의 findByFeedback() 함수를 호출해 피드백 검색 기능을 진행한다.

56. TextConditionedRetrievalServicer의 RetrieveImages() 함수를 호출해 피드백을 AI 모델로 전달한다.

57. TextConditionedRetriever의 retrieve_images() 함수를 통해 검색 기능을 실행한다.

58. 결과값을 반환한다.

59. RetrieveImagesResponse 를 반환한다. 그리고 여기서 옷 id 값들을 추출한다.

60. ScoreMap 의 크기만큼 반복문을 돌린다.

ClothesRepository 의 findByModelForFeedbackId() 함수를 호출해, 각각의 옷 id 에 대응하는 Clothes 객체를 요청한다.

61. Clothes 객체를 반환받는다.

62 ~ 63. FeedbackResponseDto 의 List 를 반환해서 화면에 표시한다.

공통 - getClothesResponse

옷 반환 값을 만드는 공통 함수이다.

64. ClothesWithKeywordRepository 의 findByClothes() 함수를 호출한다.

이를 통해 반환받은 것으로부터 각각의 옷 객체마다, KeywordList 를 요청한다.

65. List<KeywordResponseDto> 를 반환받는다. 그리고 이를 받아 각각의 옷에 대해 Keyword List 를 만든다.

66. WishListRepository의 existByMemberAndClothes() 함수를 호출하고 Member와 Clothes 객체를 전달해서, 현재 사용자가 좋아요를 했는지 여부를 확인한다.

67. isLiked 변수를 반환받는다.

68. WishListRepository의 findAllByClothes() 함수를 호출하고 Clothes를 전달해 현재 옷의 좋아요 수를 요청한다.

69. wishListSize를 반환받는다.

이를 통해 ClothesResponseDto 를 생성한다.

컴포넌트도

Cmp diag.png

본 시스템은 Client, Server, Resources, AI 총 4개의 시스템으로 구성된다.

Client

Cmp diag cli.png

HeaderTop 컴포넌트

HeaderTop.vue 산출물로 구현된다.

모든 화면의 상단에 표출되는 컴포넌트로 아래의 모든 컴포넌트로 이동할 수 있다.

Login 컴포넌트

Login.vue 산출물로 구현된다.

사용자와 판매자가 로그인을 하여 사이트의 기능을 활용할 수 있다.

SearchResult 컴포넌트

SearchKeyword.vue, SearchName.vue, SearchSentence.vue 산출물로 구현된다.

사용자와 판매자가 검색을 했을 때의 결과이다.

SearchKeyword 컴포넌트

SearchKeyword.vue 산출물로 구현된다.

사용자가 SearchResult 화면에서 키워드를 클릭했을 때의 결과이다.

SearchName 컴포넌트

SearchName.vue 산출물로 구현된다.

사용자가 SearchResult 화면에서 Search Sentence 항목의 View More을 클릭했을 때의 결과이다.

SearchSentence 컴포넌트

SearchSentence.vue 산출물로 구현된다.

사용자가 SearchSentence 화면에서 Search Name 항목의 View More을 클릭했을 때의 결과이다.

UserAll 컴포넌트

UserAll.vue 산출물로 구현된다.

사용자와 판매자가 전체 옷을 조회할 수 있다.


UserOuter 컴포넌트

UserOuter.vue 산출물로 구현된다.

사용자와 판매자가 Outer 옷을 조회할 수 있다.

UserTop 컴포넌트

UserTop.vue 산출물로 구현된다.

사용자와 판매자가 Top 옷을 조회할 수 있다.

UserPants 컴포넌트 UserPants.vue 산출물로 구현된다.

사용자와 판매자가 Pants 옷을 조회할 수 있다.

UserSkirts 컴포넌트

UserSkirts.vue 산출물로 구현된다.

사용자와 판매자가 Skirts 옷을 조회할 수 있다.

UserDress 컴포넌트

UserDress.vue 산출물로 구현된다.

사용자와 판매자가 Dress 옷을 조회할 수 있다.

SellerAddClothes 컴포넌트

SellerAddClothes.vue 산출물로 구현된다.

판매자가 clothes를 추가할 수 있다.

SellerEditClothes 컴포넌트

SellerEditClothes.vue 산출물로 구현된다.

판매자가 추가한 clothes를 수정할 수 있다.

UserCreateAccount 컴포넌트

UserCreateAccount.vue 산출물로 구현된다.

사용자가 계정을 만들 수 있다.

SellerCreateAccount 컴포넌트

SellerCreateAccount.vue 산출물로 구현된다.

판매자가 계정을 만들 수 있다.

UserMyPage 컴포넌트

UserMyPage.vue 산출물로 구현된다.

사용자와 판매자가 회원 정보를 수정할 수 있다.

WishList 컴포넌트

WishList.vue 산출물로 구현된다.

사용자가 좋아요를 누른 clothes의 목록을 조회할 수 있다.

App 컴포넌트

App.vue로 구현된다.

여러 컴포넌트들을 불러와서 main.ts로 넘겨주는 통합 컴포넌트이다.

main 컴포넌트

main.ts로 구현된다.

인스턴스를 생성하고 index.html 파일과 연결해준다.

index 컴포넌트

index.html로 구현된다.

컴포넌트들을 mounting해준다.

AddKeywordModal 컴포넌트

AddKeywordModal.vue 산출물로 구현된다.

판매자가 키워드를 추가할 때 사용된다.

FeedbackModal 컴포넌트

FeedbackModal.vue 산출물로 구현된다.

사용자가 옷에 대해 피드백을 할 때 사용된다.

ClothesDeleteWarningModal 컴포넌트

ClothesDeleteWarningModal.vue 산출물로 구현된다.

판매자가 옷을 삭제할 때 사용된다.

WarningModal 컴포넌트

WarningModal.vue 산출물로 구현된다.

사용자와 판매자가 계정을 삭제할 때 사용된다.

Server

Package.png

Controller

프론트엔드와 백엔드를 연결하는 데 사용하는 컴포넌트를 담는 서브 패키지이다.

Service

실제 백엔드 로직을 처리하는 컴포넌트를 담는 서브 패키지이다.

Repository

데이터베이스에 접근해 데이터를 가져오는 데 사용하는 컴포넌트를 담는 서브 패키지이다.

Domain

데이터베이스 테이블에 해당하는 객체(Entity)와 값 객체(VO)를 위한 컴포넌트를 담는 서브 패키지이다.

DTO

각 계층 간 데이터 교환을 위한 객체들을 담당하는 컴포넌트를 담는 서브 패키지이다.

Util

백엔드 로직을 처리함에 있어 공통적으로 사용할 수 있는 도구 컴포넌트를 담는 서브 패키지이다.

Auth

사용자 인증 관련 로직을 수행할 때 사용되는 컴포넌트를 담는 서브 패키지이다.

Config

AWS, Redis, Spring Security 등 관련 구성요소를 설정할 때 사용하는 컴포넌트를 담는 서브 패키지이다.

Application

서비스의 진입점을 담당하는 Application 클래스를 구현하며, Application.java 파일로 구현된다.


[Controller]

Component controller.png WishListController 컴포넌트

WishListController 클래스로 구성되며, WishListController.java 산출물로 구현된다. WishListService, WishListRequestDto 를 사용한다.

MemberController 컴포넌트

MemberController 클래스로 구성되며, MemberController.java 산출물로 구현된다. MemberService, MemberRegisterRequestDto, MemberResponseDto, MemberLoginRequestDto, TokenDto, TokenRequestDto, ClothesSellerResponseDto, ClothesResponseDto, MemberUpdateRequestDto, KeywordResponseDto 를 사용한다.

KeywordController 컴포넌트

KeywordController 클래스로 구성되며, KeywordController.java 산출물로 구현된다. KeywordService, KeywordResponseDto, KeywordSaveRequestDto 를 사용한다.

ClothesController 컴포넌트

ClothesController 클래스로 구성되며, ClothesController.java 산출물로 구현된다. ClothesService, ClothesResponseDto, ClothesSaveRequestDto,, ClothesSellerResponseDto, ClothesUpdateRequestDto, ExtractKeywordResponseDto, ClothesAllResponseDto, FeedbackDto, FeedbackRequestDto 를 사용한다.

ManagerController 컴포넌트

ManagerController 클래스로 구성되며, ManagerController.java 산출물로 구현된다. ClothesService, KeywordService, KeywordSaveRequestDto 를 사용한다.

IndexController 컴포넌트

IndexController 클래스로 구성되며, IndexController.java 산출물로 구현된다. ClothesService, KeywordService를 사용한다.


[Service]

Component serviced.png WishListService 컴포넌트

WishListService 클래스로 구성되며, WishListService.java 산출물로 구현된다. ClothesRepository, WishListRepository, MemberRepository, WishListRequestDto를 사용한다.

MemberService 컴포넌트

MemberService 클래스로 구성되며, MemberService.java 산출물로 구현된다. ClothesWithKeywordRepository, ClothesRepository, KeywordRepository, WishListRepository, MemberRepository, TokenProvider, MemberRegisterRequestDto, MemberLoginRequestDto, TokenDto, TokenRequestDto, MemberUpdateRequestDto, MemberResponseDto, ClothesSellerResponseDto, ClothesResponseDto, Authority, Clothes, Keyword, KeywordResponseDto, Member, WishList를 사용한다.

KeywordService 컴포넌트

KeywordService 클래스로 구성되며, KeywordService.java 산출물로 구현된다. ClothesWithKeywordRepository, KeywordRepository, MemberRepository, KeywordResponseDto, KeywordSaveRequestDto, Keyword 를 사용한다.

ClothesService 컴포넌트

ClothesService 클래스로 구성되며, ClothesService.java 산출물로 구현된다. S3Upload, Category, ClothesSaveRequestDto, KeywordWithScoreDto, ClothesWithKeywordRepository, ClothesRepository, KeywordRepository, WishList, Keyword, KeywordResponseDto, Member, image_classification_service, text2image_service, text_conditional_retrieval_service, ExtractKeywordResponseDto, ClothesUpdateRequestDto, FeedbackDto, FeedbackResponseDto를 사용한다.


[Domain]

Component domain.png

Clothes 컴포넌트

Clothes 클래스로 구성되며, Clothes.java 산출물로 구현된다.

Keyword 컴포넌트

Keyword 클래스로 구성되며, Keyword.java 산출물로 구현된다.

BaseTimeEntity 컴포넌트

BaseTimeEntity 클래스로 구성되며, BaseTimeEntity.java 산출물로 구현된다.

ClothesWithKeyword 컴포넌트

ClothesWithKeyword 클래스로 구성되며, ClothesWithKeyword.java 산출물로 구현된다.

Member 컴포넌트

Member 클래스로 구성되며, Member.java 산출물로 구현된다.

WishList 컴포넌트

WishList 클래스로 구성되며, WishList.java 산출물로 구현된다.

Authority 컴포넌트

Authority 클래스로 구성되며, Authority.java 산출물로 구현된다.

Category 컴포넌트

Category 클래스로 구성되며, Category.java 산출물로 구현된다.

KeywordState 컴포넌트

KeywordState 클래스로 구성되며, KeywordStatejava 산출물로 구현된다.


[Dto]

Component dto.png

ClothesResponseDto 컴포넌트

ClothesResponseDto 클래스로 구성되며, ClothesResponseDto.java 산출물로 구현된다.

ClothesSaveRequestDto 컴포넌트

ClothesSaveRequestDto 클래스로 구성되며, ClothesSaveRequestDto.java 산출물로 구현된다.

KeywordResponseDto 컴포넌트

KeywordResponseDto 클래스로 구성되며, KeywordResponseDto[.java](http://Clothes.java) 산출물로 구현된다.

KeywordSaveRequestDto 컴포넌트

KeywordSaveRequestDto 클래스로 구성되며, KeywordSaveRequestDto.java 산출물로 구현된다.

MemberRegisterRequestDto 컴포넌트

MemberRegisterRequestDto 클래스로 구성되며, MemberRegisterRequestDto.java 산출물로 구현된다.

MemberResponseDto 컴포넌트

MemberResponseDto 클래스로 구성되며, MemberResponseDto.java 산출물로 구현된다.

MemberLoginRequestDto 컴포넌트

MemberLoginRequestDto 클래스로 구성되며, MemberLoginRequestDto.java 산출물로 구현된다.

ClothesSellerResponseDto 컴포넌트

ClothesSellerResponseDto 클래스로 구성되며, ClothesSellerResponseDto.java 산출물로 구현된다.

ClothesUpdateRequestDto 컴포넌트

ClothesUpdateRequestDto 클래스로 구성되며, ClothesUpdateRequestDto.java 산출물로 구현된다.

ExtractKeywordResponseDto 컴포넌트

ExtractKeywordResponseDto 클래스로 구성되며, ExtractKeywordResponseDto.java 산출물로 구현된다.

MemberUpdateRequestDto 컴포넌트

MemberUpdateRequestDto 클래스로 구성되며, MemberUpdateRequestDto.java 산출물로 구현된다.

TokenDto 컴포넌트

TokenDto 클래스로 구성되며, TokenDto.java 산출물로 구현된다.

TokenRequestDto 컴포넌트

TokenRequestDto 클래스로 구성되며, TokenRequestDto.java 산출물로 구현된다.

FeedbackDto 컴포넌트

FeedbackDto 클래스로 구성되며, FeedbackDto.java 산출물로 구현된다.

FeedbackResponseDto 컴포넌트

FeedbackResponseDto 클래스로 구성되며, FeedbackResponseDto.java 산출물로 구현된다.

ClothesListResponseDto 컴포넌트

ClothesListResponseDto 클래스로 구성되며, ClothesListResponseDto.java 산출물로 구현된다.

ClothesAllResponseDto.java 컴포넌트

ClothesAllResponseDto.java 클래스로 구성되며, ClothesAllResponseDto.java.java 산출물로 구현된다.


[Repository]

Component repository.png

WishListRepository 컴포넌트

WishListRepository 클래스로 구성되며, WishListRepository.java 산출물로 구현된다. Member, WishList, Clothes 를 사용한다.

MemberRepository 컴포넌트

MemberRepository 클래스로 구성되며, MemberRepository.java 산출물로 구현된다. Member를 사용한다.

KeywordRepository 컴포넌트

KeywordRepository 클래스로 구성되며, KeywordRepository.java 산출물로 구현된다. Keyword를 사용한다.

ClothesRepository 컴포넌트

ClothesRepository 클래스로 구성되며, ClothesRepository.jav[a](http://WishLostController.java) 산출물로 구현된다. Clothes, Keyword를 사용한다.

ClothesWithKeywordRepository 컴포넌트

ClothesWithKeywordRepository 클래스로 구성되며, ClothesWithKeywordRepository.java 산출물로 구현된다. ClothesWithKeyword, Keyword, Clothes를 사용한다.


[Auth]

Compoenet auth.png

CustomUserDetailsService 컴포넌트

CustomUserDetailsService 클래스로 구성되며, CustomUserDetailsService.java 산출물로 구현된다. Member, MemberRepository를 사용한다.

JwtAccessDeniedHandler 컴포넌트

JwtAccessDeniedHandler 클래스로 구성되며, JwtAccessDeniedHandler.java 산출물로 구현된다.

JwtAuthenticationEntryPoint 컴포넌트

JwtAuthenticationEntryPoint 클래스로 구성되며, JwtAuthenticationEntryPoint.java 산출물로 구현된다.

JwtFilter 컴포넌트

JwtFilter 클래스로 구성되며, JwtFilter .java 산출물로 구현된다. TokenProvider 를 사용한다.

TokenProvider 컴포넌트

TokenProvider 클래스로 구성되며, TokenProvider.java 산출물로 구현된다.


[Config]

Component config.png

AwsConfig 컴포넌트

AwsConfig 클래스로 구성되며, AwsConfig.java 산출물로 구현된다.

SecurityConfig 컴포넌트

SecurityConfig 클래스로 구성되며, SecurityConfig.java 산출물로 구현된다. TokenProvider를 사용한다.

JwtSecurityConfig 컴포넌트

JwtSecurityConfig 클래스로 구성되며, JwtSecurityConfig.java 산출물로 구현된다. JwtFilter, TokenProvider를 사용한다.

GrpcConfig 컴포넌트

GrpcConfig 클래스로 구성되며, GrpcConfig.java 산출물로 구현된다.

RedisConfig 컴포넌트

RedisConfig 클래스로 구성되며, RedisConfig.java 산출물로 구현된다.


[Util]

Component util.png

S3Upload 컴포넌트

S3Upload 클래스로 구성되며, S3Upload.java 산출물로 구현된다.

SecurityUtil 컴포넌트

SecurityUtil 클래스로 구성되며, SecurityUtil.java 산출물로 구현된다.

Resources

[static]

Component static.png

Index 컴포넌트

Index 클래스로 구성되며, Index.js 산출물로 구현된다.


[templates]

Componene template.png

clothes 컴포넌트

clothes 파일로 구성되며, clothes.mustache 산출물로 구현된다. footer 와 header 를 사용한다.

keyword 컴포넌트

keyword 파일로 구성되며, keyword.mustache 산출물로 구현된다. 또한, footer 와 header 를 사용한다.

index 컴포넌트

index 파일로 구성되며, index.mustache 산출물로 구현된다. clothes 와 keyword 컴포넌트를 사용한다.

footer 컴포넌트

footer 파일로 구성되며, footer.mustache 산출물로 구현된다.

header 컴포넌트

header 파일로 구성되며, header.mustache 산출물로 구현된다.

AI

Cmp diag ai.png

image_classification_service

클라이언트의 요청을 받아 이미지에 대해 적절한 키워드 분류를 담당하는 서버 실행과 관련된 컴포넌트이다. ImageClassificationInterface 인터페이스를 통해 이미지 분류 기능을 제공한다.

text2image_service

클라이언트의 요청을 받아 주어진 텍스트에 적절한 이미지를 검색하는 역할을 담당하는 서버 실행과 관련된 컴포넌트이다. Text2ImageInterface 인터페이스를 통해 텍스트 이용한 이미지 검색, 검색 가능한 이미지 추가 및 삭제 기능을 제공한다.

text_conditioned_retrieval_service

클라이언트의 요청을 받아 주어진 이미지와 그에 해당하는 피드백을 이용하여 원하는 이미지를 가져오는 서버 실행과 관련된 컴포넌트이다. TextConditionedRetrievalInterface를 통해 피드백 기반 이미지 검색, 검색 가능한 이미지 추가 및 삭제 기능을 제공한다.

utils

로깅 등 서버 관련 유틸리티를 제공하는 컴포넌트이다.

image_classification_servicer

클라이언트로부터 이미지를 받은 뒤 이미지 분류와 관련하여 적절한 응답 전달 기능을 담당하는 컴포넌트이다.

mock_image_classification_servicer

클라이언트로부터 이미지를 받은 뒤 이미지 분류와 관련하여 적절한 가짜 응답 전달 기능을 담당하는 컴포넌트이다.

text2image_servicer

클라이언트로부터 텍스트를 받은 후 이미지 리트리벌과 관련하여 적절한 응답 전달을 담당하는 컴포넌트이다.

mock_text2image_servicer

클라이언트로부터 텍스트를 받은 후 이미지 리트리벌과 관련하여 가짜 응답 전달을 담당하는 컴포넌트이다.

text_conditioned_retrieval_servicer

클라이언트로부터 이미지와 그에 대한 피드백을 받아 적절한 응답을 전달하는 기능을 수행하는 컴포넌트이다.

mock_text_conditioned_retrieval_servicer

클라이언트로부터 이미지와 그에 대한 피드백을 받아 가짜 응답을 전달하는 기능을 수행하는 컴포넌트이다.

image_classifiers

이미지에 대한 분류를 실제로 수행하는 컴포넌트이다.

torch_utils

torch와 관련된 유틸리티 기능을 제공하는 컴포넌트이다.

text2image_retrievers

주어진 텍스트에 대한 이미지를 가져오는 기능을 실제로 수행하는 컴포넌트이다.

text_conditioned_retriever

이미지와 그에 대한 피드백이 주어졌을 때 적절한 이미지를 가져오는 기능을 실제로 수행하는 컴포넌트이다.

cocoop_datamodule

데이터셋을 읽고 학습 때 접근 가능하게 하는 기능이 포함된 컴포넌트이다.

cocoop

이미지 분류 모델을 포함하고 있는 컴포넌트이다.

train_cocoop

이미지 분류 모델 학습을 실행하는 컴포넌트이다.

ER 다이어그램

Er diag.png

Clothes 테이블

옷 데이터를 담당하는 테이블이다.

id, name, price, imgUrl, detailUrl, category, modelForSentenceId, modelForFeedbackId, sellerId, createdDate, modeifiedDate 를 갖는다. id 를 primary key 로 사용한다.

sellerId는 Member 의 id를 참조하는 외래키로, 이 정보를 통해 Member 의 정보와 매핑한다.

Keyword 테이블

키워드 데이터를 담당하는 테이블이다.

id, nameForLearn, nameForDisplay, creator, state, createdDate, modifiedDate 를 갖는다.

id 를 primary key 로 사용한다.

ClothesWithKeyword 테이블

Clothes 데이터와 Keyword 데이터를 매핑하는 테이블로, 두 데이터 간 다대다 관계가 성립하기 때문에 생성하는 테이블이다.

id 를 primary key 로 사용한다.

clothesId 는 Clothes의 id를 참조하는 외래키이고, keywordId는 Keyword의 id를 참조하는 외래키이다.

Member 테이블

사용자 데이터를 담당하는 테이블이다.

id, email, password, name, phone, authority 를 갖는다.

id 를 primary key 로 사용한다.

WishList 테이블

좋아요 데이터를 담당하는 테이블이다.

좋아요 데이터의 경우 Member 데이터와 Clothes 데이터 간 다대다 관계가 성립하기 때문에 만든 매핑 테이블이다.

id, clothesId, memberId, createdDate, modifiedDate 를 갖는다.

id 를 primary key 로 사용한다.

clothesId 는 Clothes의 id를 참조하는 외래키이고, memberId는 Member의 id를 참조하는 외래키이다.

결과 및 평가

완료 작품의 소개

프로토타입 사진

Product pic 1.png Product pic 2.png

포스터

컴퓨터과학부 종합설계 404팀 포스터-1.png 컴퓨터과학부 종합설계 404팀 포스터-2.png 컴퓨터과학부 종합설계 404팀 포스터-3.png 컴퓨터과학부 종합설계 404팀 포스터-4.png

설치 (configuration)

KEYsCOVER 설치 메뉴얼

실행 (run)

KEYsCOVER 실행 메뉴얼

성과물

◇ 관리자 페이지

http://fashion-search-ai.tk/manager

◇ 웹 페이지

https://638ff7b181c1b2000863930e--keyscover.netlify.app/

◇ 유의 사항

서버 비용으로 인해 평가 기간 후에는 사이트가 동작하지 않을 수 있습니다.

관련사업비 내역서

Expenses.png

완료작품의 평가

Perf table 2.png

서버 부하 테스트 평가 결과

Server perf.png

옷을 저장하는 요청에 대해서는 0%의 오류율을 보였으며, 옷을 검색하는 요청과 옷을 조회하는 요청에 대해서는 각각 0.2%의 오류율을 보였습니다.

우선 옷을 저장하는 경우 서버에서 트렌젝션이 발생하며, 이 부분에 있어서 오류율이 없다는 것은 데이터를 저장하고 삭제하는 중요한 로직에 있어서 매우 안전하다는 것으로 판단할 수 있습니다.

서버에서는 평균적으로 1초당 45개의 요청을 처리했으며, 한 번에 30만 바이트, 즉 0.3 메가바이트를 처리했습니다.

하루 방문자가 1000명인 사이트의 경우 평균적으로 동시 접속자 수는 10명 정도로 산출됩니다.

가장 높은 월 방문자 수를 기록한 무신사 사이트의 경우 월 8백만명에 가까운 접속자 수를 보이며, 이는 단순 평균치를 계산했을 때 하루 평균 27만명 정보의 방문자 수를 갖고 있습니다.

하루 평균 접속자 수와 평균적인 접속자 수를 기반으로 동시 접속자 수를 구한다면, 무신사의 경우 대략 270명 정도의 동시 접속자 수를 가집니다.

대한민국에서 가장 인기있고 방문자 수가 높은 사이트의 경우에도 동시 접속자 수는 270명 정도를 보일 것으로 예상되며, 따라서 1000명의 동시 접속자 수에 있어서 오류율 0.2%를 기록하는 것은, 충분히 높은 품질을 보이는 것으로 판단할 수 있습니다.

결론적으로, 데이터를 실제 저장하고 삭제하는 중요한 비즈니스 로직의 경우 매우 안전하며, 옷을 검색하고 조회하는 기능에 있어서도 우수한 품질을 보이고 있습니다.

향후 평가

어려웠던 내용들

◇ 패션에 대한 도메인 지식이 없는 상태에서 구매자가 어떤 키워드들에 관심을 가질지 그리고 어떤 의류가 그 키워드에 해당하는 의류인지 판단하는 데에 어려움이 있었습니다.

◇ 프론트엔드 백엔드 서버 분리 배포

프론트엔드와 백엔드 서버를 분리하는 것을 결정했습니다.

그 이유로 우선 속도적인 측면에서, 서버를 한 곳에 모아둘 경우 당연하게 속도가 느립니다. 또한 ec2 의 메모리가 제한적이기 때문에, 더더욱 원활하게 사용하려고 한다면 분리해서 배포해야 합니다.

또한 관리적인 측면에서, 화면을 그려주는 방식과 데이터를 제공하는 방식은 많이 달라서 따로 분리해서 관리하는 것이 더 적절하다고 판단했습니다.

따라서 aws의 s3에서 정적 웹호스팅을 통해 프론트엔드를 배포했습니다. 그러나 이 과정에서 cors 문제가 발생했습니다.

CORS 문제는 요청 브라우저에서 다른 도메인을 가지는 서버로 요청이 보낼 때 브라우저에서 발생하는 보안정책입니다. 본 프로젝트에선 다른 서버에서 프론트엔드와 백엔드를 배포했기에 이 문제가 발생했습니다. 이것을 해결하기 위해 스프링부트에서 security 설정을 변경하는 등 다양한 노력을 했지만, 그럼에도 cors 문제는 사라지지 않았습니다.

따라서 netlify라는 서비스를 사용하는 것으로 바꾸었습니다. netlify는 자체적으로 proxy 를 제공하기 때문에, 설정 파일을 추가하는 것으로 cors 문제를 간단히 해결할 수 있었습니다. 또한, netlify의 경우 소스를 깃에 푸시하기만 하면 자동으로 빌드되고 재배포된다는 이점이 있습니다.

이러한 경험을 통해 프론트엔드와 백엔드 서버를 분리하여 배포할 때의 주의점을 인지할 수 있었고, 그에 대한 해결책을 찾아 추후 프로젝트에서도 사용할 수 있는 지식을 확보했습니다.

차후 구현할 내용

◇ 작성하였을 때 사용자가 얻게 되는 것이 불분명한 리뷰 데이터와 달리 자연어 피드백을 이용한 검색 기능은 응답에 적절한 새로운 상품 목록을 얻게 되어 사용자의 선호와 관련된 데이터 수집을 용이하게 합니다. 또한 이 피드백은 형식에 제약이 적은 자연어로 저장되기 때문에 다른 방법으로는 비교적 구하기 어려운 데이터입니다. 사용자가 어떤 상품을 선호했는지는 구매 내역을 통해 알 수 있지만 어떤 상품을 어떤 이유로 선호했는지는 구매 내역에 직접적으로 표현되지는 않기 때문입니다. 이를 사용자를 모델링 하는 용도로 사용할 수 있을 뿐만 아니라 상품의 어떤 부분이 불만족스러웠는지에 대한 정보를 익명화하여 판매자에게 제공하는 기능도 고려해 볼 수 있습니다.

◇ 사용자 피드백에 기반을 둔 모델 추천에 사용되는 자연어 데이터는 제작에 비용이 많이 들어 다양한 유형의 상품에 대해 만들기에 어려움이 있습니다. 데이터셋에 주어진 도메인에서 타겟 도메인에 적응하는 방법을 통해 이러한 제약을 줄여 관련 방법의 사용을 용이하게 할 수 있습니다.

◇ 사용자 수가 많아졌을 때 추천 등 개인화와 관련된 데이터를 수집하여 활용하는 것을 고려해 볼 수 있습니다. 쇼핑몰에서 빼놓을 수 없는 중요한 요소이지만 사용자에 대한 정보가 쌓여야 한다는 사전 조건이 있어 이번 프로젝트의 범위에서는 제외되었습니다.

◇ 판매자가 어떤 의류 이미지를 업로드했을 때 판매되고 있는 유사한 옷들을 확인할 수 있게 하여 경쟁 상품들이 어떻게 되는지 파악할 수 있는 기능도 유용할 수 있습니다.

특허 출원 내용

해당 없음.

부록

참고문헌 및 참고사이트

[Liu+16] Ziwei Liu et al. “DeepFashion: Powering Robust Clothes Recognition and Retrieval with Rich Annotations”. In: Proceedings of IEEE Conference on Computer Vision and Pattern Recognition (CVPR). 2016.

[BBS10] Tamara L. Berg, Alexander C. Berg, and Jonathan Shih. “Automatic Attribute Discovery and Characterization from Noisy Web Data”. In: Computer Vision – ECCV 2010. Ed. by Kostas Daniilidis, Petros Maragos, and Nikos Paragios. Berlin, Heidelberg: Springer Berlin Heidelberg, 2010, pp. 663–676. isbn: 978-3-642-15549-9.

[Zou+19] Xingxing Zou et al. “FashionAI: A Hierarchical Dataset for Fashion Understanding”. In: 2019 IEEE/CVF Conference on Computer Vision and Pattern Recognition Workshops (CVPRW). 2019, pp. 296–304.

[Den+09] Jia Deng et al. “ImageNet: A large-scale hierarchical image database”. In: 2009 IEEE Conference on Computer Vision and Pattern Recognition (2009), pp. 248–255.

[Rad+21] Alec Radford et al. “Learning Transferable Visual Models From Natural Language Supervision”. In: ICML. 2021.

[Jia+21] Chao Jia et al. “Scaling Up Visual and Vision-Language Representation Learning With Noisy Text Supervision”. In: ICML. 2021. [LAC21] Brian Lester, Rami Al-Rfou, and Noah Constant. “The Power of Scale for Parameter-Efficient Prompt Tuning”. In: Proceedings of the 2021 Conference on Empirical Methods in Natural Language Processing. Online and Punta Cana, Dominican Republic: Association for Computational Linguistics, Nov. 2021, pp. 3045–3059.

[LL21] Xiang Lisa Li and Percy Liang. “Prefix-Tuning: Optimizing Continuous Prompts for Generation”. In: Proceedings of the 59th Annual Meeting of the Association for Computational Linguistics and the 11th International Joint Conference on Natural Language Processing (Volume 1: Long Papers) abs/2101.00190 (2021).

[Zho+22a] Kaiyang Zhou et al. “Learning to Prompt for Vision-Language Models”. In: International Journal of Computer Vision (IJCV) (2022).

[Lu+22a] Yuning Lu et al. “Prompt Distribution Learning”. In: Proceedings of the IEEE/CVF Conference on Computer Vision and Pattern Recognition (CVPR). June 2022, pp. 5206–5215.

[Zho+22b] Kaiyang Zhou et al. “Conditional Prompt Learning for Vision-Language Models”. In: IEEE/CVF Conference on Computer Vision and Pattern Recognition (CVPR). 2022.

[Wan+22] Wenhui Wang et al. “Image as a Foreign Language: BEiT Pretraining for All Vision and Vision-Language Tasks”. In: arXiv preprint arXiv:2208.10442 (2022).

[Wu+21] Hui Wu et al. “The Fashion IQ Dataset: Retrieving Images by Combining Side Information and Relative Natural Language Feedback”. In: CVPR (2021).

[DCS22] Eric Dodds, Jack Culpepper, and Gaurav Srivastava. “Training and challenging models for text-guided fashion image retrieval”. In: arXiv preprint arXiv:2204.11004 (2022).

[Liu+21] Zheyuan Liu et al. “Image Retrieval on Real-life Images with Pre-trained Vision-and-Language Models”. In: ICCV. 2021.

[Goe+22] Sonam Goenka et al. “FashionVLP: Vision Language Transformer for Fashion Retrieval With Feedback”. In: Proceedings of the IEEE/CVF Conference on Computer Vision and Pattern Recognition (CVPR). June 2022, pp. 14105–14115.

[Che+18] Yilun Chen et al. “Cascaded pyramid network for multi-person pose estimation”. In: Proceedings of the IEEE conference on computer vision and pattern recognition. 2018, pp. 7103 7112.

[Ren+15] Shaoqing Ren et al. “Faster R-CNN: Towards Real-Time Object Detection with Region Proposal Networks”. In: Advances in Neural Information Processing Systems. Ed. by C. Cortes et al. Vol. 28. Curran Associates, Inc., 2015.

[Zha+21] Pengchuan Zhang et al. “VinVL: Revisiting Visual Representations in Vision-Language Models”. In: Proceedings of the IEEE/CVF Conference on Computer Vision and Pattern Recognition (CVPR). June 2021, pp. 5579–5588.

[Bal+22a] Alberto Baldrati et al. “Conditioned and Composed Image Retrieval Combining and Partially Fine-Tuning CLIP-Based Features”. In: Proceedings of the IEEE/CVF Conference on Computer Vision and Pattern Recognition. 2022, pp. 4959–4968.

[Bal+22b] Alberto Baldrati et al. “Effective Conditioned and Composed Image Retrieval Combining CLIP-Based Features”. In: Proceedings of the IEEE/CVF Conference on Computer Vision and Pattern Recognition. 2022, pp. 21466–21474.

[Han+17] Xintong Han et al. “Automatic Spatially-aware Fashion Concept Discovery”. In: ICCV. 2017.

[Yan+20] Xuewen Yang et al. “Fashion Captioning: Towards Generating Accurate Descriptions with Semantic Rewards”. In: ECCV. 2020.

[Ros+18] Negar Rostamzadeh et al. “Fashion-gen: The generative fashion dataset and challenge”. In: arXiv preprint arXiv:1806.08317 (2018).

[Vas+18] Mariya I Vasileva et al. “Learning type-aware embeddings for fashion compatibility”. In: Proceedings of the European conference on computer vision (ECCV). 2018, pp. 390–405.

[Che+21] Lili Chen et al. “Decision Transformer: Reinforcement Learning via Sequence Modeling”. In: Advances in Neural Information Processing Systems. Ed. by M. Ranzato et al. Vol. 34. Curran Associates, Inc., 2021, pp. 15084–15097.

[JLL21] Michael Janner, Qiyang Li, and Sergey Levine. “Offline Reinforcement Learning as One Big Sequence Modeling Problem”. In: Advances in Neural Information Processing Systems. Ed. by M. Ranzato et al. Vol. 34. Curran Associates, Inc., 2021, pp. 1273–1286.

[ZZG22] Qinqing Zheng, Amy Zhang, and Aditya Grover. “Online Decision Transformer”. In: Proceedings of the 39th International Conference on Machine Learning. Ed. by Kamalika Chaudhuri et al. Vol. 162. Proceedings of Machine Learning Research. PMLR, 17–23 Jul 2022, pp. 27042–27059.

[Lu+22b] Ximing Lu et al. “Quark: Controllable Text Generation with Reinforced Unlearning”. In: arXiv preprint arXiv:2205.13636 (2022).

[JDJ19] Jeff Johnson, Matthijs Douze, and Herv ́e J ́egou. “Billion-scale similarity search with GPUs”. In: IEEE Transactions on Big Data 7.3 (2019), pp. 535–547.

[Wan+21] Wenhui Wang et al. “Vlmo: Unified vision-language pre-training with mixture-of-modality-experts”. In: arXiv preprint arXiv:2111.02358 (2021).

[You+14] Peter Young et al. “From image descriptions to visual denotations: New similarity metrics for semantic inference over event descriptions”. In: Transactions of the Association for Computational Linguistics 2 (2014), pp. 67–78.

[Lin+14] Tsung-Yi Lin et al. “Microsoft coco: Common objects in context”. In: European conference on computer vision. Springer. 2014, pp. 740–755.

[Xin+22] Ji Xin et al. “Zero-Shot Dense Retrieval with Momentum Adversarial Domain Invariant Representations”. In: Findings of the Association for Computational Linguistics: ACL 2022. Dublin, Ireland: Association for Computational Linguistics, May 2022, pp. 4008–4020.

[YYS22] Xiang Yue, Ziyu Yao, and Huan Sun. “Synthetic Question Value Estimation for Domain Adaptation of Question Answering”. In: Proceedings of the 60th Annual Meeting of the Association for Computational Linguistics (Volume 1: Long Papers). Dublin, Ireland: Association for Computational Linguistics, May 2022, pp. 1340–1351.

[Xio+21] Lee Xiong et al. “Approximate Nearest Neighbor Negative Contrastive Learning for Dense Text Retrieval”. In: 9th International Conference on Learning Representations, ICLR 2021, Virtual Event, Austria, May 3-7, 2021. OpenReview.net, 2021.[Zha+22] Hang Zhang et al. “Adversarial Retriever-Ranker for Dense Text Retrieval”. In: The Tenth International Conference on Learning Representations, ICLR 2022, Virtual Event, April 25-29, 2022. OpenReview.net, 2022.

[Azu97] Ronald T Azuma. “A survey of augmented reality”. In: Presence: teleoperators & virtual environments 6.4 (1997), pp. 355–385.

관련특허

해당 없음

소프트웨어 프로그램 소스

해당 없음