defer (async throwing contexts)
iOYES
1. 이번 주에 집중한 이유와 목표
지난 5주 동안 LLM을 '터미널, 주피터 노트북 장난감' 수준에서만 굴려 봤다. 물론 쉘에서 모델을 돌려 보는 것도 재미는 있지만, "사람한테 보여 줄 수 있는 형태"로 만들지 않으면 언제까지나 개인 공부에 그친다. 그래서 6주차 미션은 딱 한 줄로 정의했다.
"전신 사진과 옷 사진 몇 장만 던지면, 착용자의 체형·취향·상황(TPO)을 고려해 코디를 추천하는 챗봇을 눈으로 볼 수 있게 만들어 보자!"
내가 잡은 세부 목표는 다음 넷이었다.
멀티모달 입력 – 이미지 여러 장 + 텍스트를 한 번에 받는다.
대화 문맥 유지 – 세션 스테이트를 써서 새로고침해도 톤·맥락이 끊기지 않는다.
로컬 테스트 완전 통과 – GPU(Tesla T4) 환경에서 지연 없이 동작.
다음 주 배포 준비 – 코드 구조·보안키 관리·리사이즈 파이프라인 모두 깔끔히.
체험해 보니 멀티모달 프롬프트 자체보다 이미지 사이즈·메모리 관리가 훨씬 큰 난관이었다. "모델 성능 <<<<< I/O·UX"를 다시 체감.
2. 구현 과정 자세히 뜯어보기
2‑1. Streamlit UI 설계 – 사용 흐름은 짧게, 피드백은 즉시
단계별 업로더: 전신 → 옷 → "대화 시작하기" 버튼.
⤷ 사용자는 업로드 상태를 시각적으로 확인 후 다음 단계로 넘어간다.
세션 스테이트: 업로드한 이미지 바이트와 대화 히스토리를 st.session_state
에 저장. 새로고침되더라도 그대로 복구된다.
스트리밍 응답: ChatOpenAI(..., streaming=True)
+ for chunk in model.stream([...])
로 매 0.5초마다 답변을 찍어내 UX를 부드럽게.
2‑2. 멀티모달 프롬프트 – 이미지와 텍스트를 한 그릇에 담기
content = [
{"type": "text", "text": f"{prompt_tpl}\n\n{history}\n\nUser: {question}"},
{"type": "image_url", "image_url": {"url": f"data:image/jpeg;base64,{body_img}"}},
] + [
{"type": "image_url", "image_url": {"url": f"data:image/jpeg;base64,{cloth}"}}
for cloth in clothes_imgs
]
GPT‑4o‑mini Vision이 base64 Data URI를 그대로 읽을 수 있다는 점을 활용.
대화가 길어질수록 history
문자열을 추려 주지 않으면 토큰 폭발이 일어나니, 최근 10개 메시지만 남기는 슬라이딩 윈도우를 적용.
2‑3. 추천 로직 – '왜 이 옷?'을 설명해 주기
체형·톤 분석: 전신 사진만 보고 착용자 타입을 3줄 요약.
아이템 매칭: 옷 사진의 색·실루엣·소재를 구분(class‑token prompt)해 상황에 맞춰 조합.
대안 제시: "비슷한 계열의 팬츠가 있을까?" 같은 추가 질문에 대비해 2~3개 옵션을 함께 추천.
2‑4. 로컬 테스트 시나리오
입력기대 결과실제 결과전신 + 옷 2장 + "출근용 데일리룩 추천"톤·실루엣 근거 + 상·하·악세서리 세트✅ 정확히 설명 + "비 오는 날엔 이런 재질 추천" 보너스
3. 아직 해결 못 한 문제 & 다음 주 계획
3‑1. 이미지 메모리 최적화(예정)
원본 이미지를 그대로 base64로 넣으니 평균 8~12MB, 사진 4장만 돼도 40MB를 훌쩍 넘는다. 모델이야 스트리밍이니 괜찮지만 RAM과 네트워크를 동시에 압박해 다음을 시도하려 한다.
Pillow
로 512px 썸네일 생성 후 인코딩 → 90% 용량 절감 목표.
JPG → WebP 변환도 고려.
링크 형태로 제공하는것도 고려. (gpt가 이미지 링크도 받길래)
3‑2. 클라우드 배포(계획)
Nginx Reverse Proxy + Let’s Encrypt SSL → https://fashion‑bot.my‑domain.com
노출 목표.
GitHub Actions → EC2 무중단 배포 파이프라인.
3‑3. RAG & 이미지 생성
룩북·쇼핑몰 크롤링 → 임베딩 → GPT + RetrievalQA.
DALL·E로 스타일 시뮬레이션 이미지 생성 → 사용자 피팅.
4. 배운 점 & 느낀 점
Streamlit만으로도 충분히 빠르게 MVP를 만들 수 있다. 세션 스테이트와 새 위젯(st.chat_*
) 덕분에 코드가 300줄을 넘지 않았다.
이미지 리사이즈·압축 파이프라인을 미리 짜 놓지 않으면, 멀티모달 서비스는 금방 병목에 부딪힌다. 실제 사용자에게 보이기 전에 시스템 한계를 확인할 수 있었다.
대화형 UX에서는 '응답 속도' 자체가 품질이다. 모델 정확도보다 빨리 돌아오는 스트리밍이 먼저 체감된다.
"AI가 전부 해결해 줄 거야"라는 막연한 기대와 달리, 사용자 경험을 완성하기까지는 여전히 인프라·UX·데이터 파이프라인이 70% 이상을 차지한다는 걸 다시 깨닫는 한 주였다.
5. 참고 코드 스니펫 (가독성을 위해 핵심만)
@st.cache_resource
def init_model():
return ChatOpenAI(model="gpt-4o-mini", streaming=True)
model = init_model()
with st.chat_message("assistant"):
response_placeholder = st.empty()
full_response = ""
for chunk in model.stream([HumanMessage(content=content)]):
full_response += chunk.content or ""
response_placeholder.markdown(full_response)
st.session_state.messages.append({"role": "assistant", "content": full_response})
@st.cache_resource
로 모델 객체를 한 번만 초기화해 메모리 절약.
스트리밍 루프에서 chunk.content
Null 체크를 꼭 해 줘야 잔문자 오류가 없다.
끝으로
친구에게 보여주고 피드백
이번 주는 '모델 완성'보다 "보여 줄 수 있는 상태"를 만드는 게 얼마나 많은 공정을 요구하는지 뼈저리게 느꼈다. 하지만 UI가 생기니 친구도 바로 테스트해 볼 수 있어서 피드백 루프가 훨씬 빨라졌다. 다음 주엔 진짜 배포까지 완주해서, "챗봇이 아니라 작은 서비스"로 만드는 게 목표다.
#항해99 #항해 플러스 AI 후기 #개발자 커뮤니티 #LLM
다음 내용이 궁금하다면?
이미 회원이신가요?
2025년 5월 11일 오전 5:43
AI(LLM) 애플리케이션의 발전 속도가 AI 지능(능력)의 발전 속도를 따라가지 못하고 있는 상태가 되었다. 즉, 이제 AI가 부족한 것이 문제가 아니라, AI의 능력을 100% 활용하지 못하고 있는 것이 문제인 상태가 되었다는 이야기.
d
최근에 친구가 추천해준 데일 카네기의 인간관계론을 읽던 중 고액 연봉을 받는 엔지니어들의 특징에 대한 흥미로운 내용이 있었다.
... 더 보기‘훌륭한 데이터 분석가란 어떤 사람인가?’에 대해
... 더 보기