Day14. 프롬프트 기반 음악 추천/작사 애플리케이션 개발 회고

2ㅣ2ㅣ·2024년 11월 21일

Project

목록 보기
13/13
post-thumbnail

개요

프롬프트 기반으로 노래 추천 혹은 가사를 생성해주는 애플리케이션을 기획한 바 있다. 기획부터 시작하여 로컬에서 리팩토링을 포함한 개발이 완성되기까지 약 한 달 정도의 시간이 소요됐다.
올해 초 개인 프로젝트로 진행했던 노래 추천 애플리케이션을 리팩토링하는 작업이었기 때문에 큰 어려움 없이 진행할 수 있을 거라고 생각하고 기획부터 배포까지 한 달을 잡았다.

하지만 현실은 배포는 시작도 못했다...😱

작업 속도가 나지 않았던 문제는 다른 기술 스택을 가진 개발자와의 소통에 어려움을 겪은 것에서 대개 파생되었다.

그로 인해 작업 도중에 메인 로직이 변경되면서 ERD, 디렉토리 구조를 대폭 수정해야 하는 일이 발생했다.
팀원이 개발에만 집중할 수 있는 상황이 아니었던 것과 나 또한 취업박람회별도의 스터디를 병행했던 점이 작업 속도가 더뎠던 이유 중 하나다.
비록 계획한 시간 안에 목표를 달성하는 데는 실패했지만, 프로젝트를 진행하며 얻은 교훈과 기술적인 성장은 무엇보다 값졌다.

As-Is: 리팩토링 이전

프로젝트 소개

항목내용
작업 기간2024.01 ~ 2024.02
작업 개요프롬프팅을 기반으로 한 음악 추천 웹 애플리케이션
참여 인원서버 개발자 1명( = 나)
사용 언어 및 개발 환경JavaScript, Python, FastAPI, Pandas
담당 역할Melon 실시간 Top100 노래 크롤링, 데이터 분석, OpenAI API를 이용해 GPT-3.5 모델로 노래 추천 알고리즘 적용



기능 1: 노래 추천

리팩토링 이전 노래 추천 기능은 아래와 같은 한계를 가지고 있었다.

  • 추천하는 곡 개수 : 1개
  • 추천하는 방법 : user_input을 임베딩하여 코사인 유사도를 구한 후 모델에 주입
  • 프론트엔드 미완성 : 기능 테스트는 포스트맨(Postman)을 사용



To-Be: 리팩토링 이후

프로젝트 소개

항목내용
작업 기간2024.10 ~ 2024.11
작업 개요프롬프팅을 기반으로 노래 추천 및 작사 생성 기능을 포함한 음악 추천 웹 애플리케이션
참여 인원스프링 서버 개발자 1명, 모델 서버 개발자 1명
사용 언어 및 개발 환경Spring Boot, React, FastAPI, PostgreSQL, Redis, Docker
담당 역할웹(프론트&서버) 전체 기능 담당, 전체 애플리케이션 리팩토링, Spring Boot 기반 API 개발, DB 설계 및 최적화 등



👋🏻 기능 1: 로그인 & 로그아웃

jwt + cookie로 로그인과 로그아웃을 구현했다

1-1. 로그인

  • 사용자는 로그인 시 form-data 형식으로 POST 요청을 보냄.
  • Spring Boot에서 로그인 요청을 처리하고 JWT를 생성하여 HttpOnly 설정된 쿠키에 저장.
  • HttpOnly 설정으로 인해 JavaScript에서 쿠키에 접근할 수 없으므로 XSS 공격을 예방하고, 프론트엔드는 Request를 보낼 때 credentials: 'include'로 쿠키를 포함하여 JWT를 확인하고 검증함
  • SameSite 설정으로 CSRF 공격을 방지함

1-2. 사용자 인증 API

  • 사용자가 Spring Boot에서 지정한 whiteListUris 경로 외에 API Call 발생 시 React/verify 경로로 POST 요청을 보냄
  • Spring BootReact로부터 받은 요청을 기반으로 JWT를 검증하여 인증 상태를 확인.
  • 추가적으로, Spring SecurityPrincipal 객체를 활용해 2중 인증을 수행하여 보안 강화함.
  • 인증 실패 시, 즉시 로그인 페이지로 리디렉션 시킴.

1-3. 로그아웃

  • 사용자가 로그아웃 요청을 보내면 Spring Boot가 다음 작업을 수행함.
    1. 기존 HttpOnly 쿠키를 제거.
    2. Max-Age=0 쿠키를 발급하여 쿠키의 유효기간을 즉시 만료.
  • JWT 기반 인증으로 서버에 세션 정보를 저장하지 않으며, 쿠키 삭제와 함께 인증 상태를 종료.
  • React는 로그아웃 후 LocalStorage 등 클라이언트 저장소를 초기화하여 브라우저에 남아있는 인증 정보를 제거.
  • 인증 정보 삭제가 완료되면 로그인 페이지로 리디렉션하여 사용자의 인증 상태를 완전히 초기화함.



🎶 기능 2: 노래 추천


리팩토링 후 UIUX를 대폭 개선하여 React 기반 프론트엔드를 구축했다.

  • 추천하는 곡 개수 : 1개 ~ 3개
  • 추천하는 방법 :
    • React에서 쿠키 + String이 담긴 RequestSpringboot에 요청
    • Springboot에서 FastAPI로 노래 추천 POST 요청
    • FastAPI에서 요청 받은 Request를 임베딩 후, 코사인 유사도로 유사한 곡 1~3개를 선별한 후 SpringbootString 값이 담긴 Response 보냄
      • OpenAI API를 통해 텍스트를 임베딩하고, Redis에서 코사인 유사도를 계산하여 곡 데이터를 검색
      • 검색된 곡 데이터를 JSON 형태로 Springboot로 반환
    • SpringbootString을 객체로 역직렬화시킨 후, React쿠키 + Response 보냄

상세 다이어그램



📝 기능 3: 작사 생성

  • 작사하는 곡 개수 : 1개
  • 작사하는 방법 :
    • React에서 쿠키 + String이 담긴 RequestSpringboot에 요청
    • Springboot에서 FastAPI로 작사 추천 POST 요청
    • FastAPI에서 요청 받은 Request를 임베딩 후, 코사인 유사도를 계산하여 유사한 가사를 생성한 뒤, SpringbootString 값이 담긴 Response 보냄
      • OpenAI API를 사용해 일기 내용을 임베딩하고, Redis에서 유사한 가사를 검색
      • 검색된 가사를 바탕으로 GPT 모델을 활용해 새로운 가사를 생성
      • 생성된 가사를 순수 문자열 형태로 Springboot에 반환
    • SpringbootString을 객체로 역직렬화시킨 후, React쿠키 + Response 보냄

상세 다이어그램



🛒 기능 4: 북마크 등록/제거

4-1. 북마크 등록

  • 사용자가 노래 추천 또는 작사 응답을 확인한 뒤, 해당 응답을 북마크에 추가할 수 있음.
  • React에서 북마크 등록 요청을 Spring Boot로 전달하며, Spring Boot는 북마크 데이터를 처리하고 데이터베이스에 저장.
  • 성공적으로 등록된 경우, 토스트 메시지를 통해 사용자에게 등록 성공을 알림

4-2. 북마크 제거

  • 등록된 북마크를 제거할 수 있으며, React에서 삭제 요청을 Spring Boot로 전달.
  • Spring Boot는 해당 데이터를 삭제하고 성공 여부를 반환.
  • 삭제된 경우, 토스트 메시지로 사용자에게 요청 성공을 알림.



💌 기능 5: 마이페이지

5-1. 북마크 목록 조회

  • React에서 Spring Boot로 북마크 목록 조회 요청을 전송.
  • Spring Boot가 저장된 북마크 데이터를 JSON 형식으로 반환하며, React이를 마이페이지 UI에 렌더링.
  • 페이지 로딩 중에는 로딩 스피너를 표시하여 사용자의 기다림을 시각적으로 보완.

5-2. 노래 추천 북마크 상세 조회

  • React에서 특정 북마크 ID를 기반으로 노래 추천 북마크 데이터를 Spring Boot로 요청.
  • Spring Boot는 해당 데이터를 조회하여 반환하며, React는 이를 상세 페이지에 표시.
  • 사용자에게 가독성을 높이기 위해 곡 정보(제목, 가수, 장르, 이미지)를 카드 형식으로 구성.

5-3. 작사 추천 북마크 상세 조회

  • React에서 특정 북마크 ID를 기반으로 작사 추천 북마크 데이터를 Spring Boot로 요청.
  • Spring Boot는 데이터를 조회하여 반환하고, React는 이를 상세 페이지에 텍스트 기반으로 표시.
  • 생성된 작사 내용을 한눈에 볼 수 있도록 적절한 텍스트 레이아웃을 카드 형식으로 구성.



👩🏼‍💻 6. UX 개선을 위해 고려한 부분

6-1. 로딩 처리


요청 문자열 길이가 길어지면 Read Timeout등이 발생할 수 있다. 이를 동적 타임아웃을 설정하고 Spring Retry를 활용한 재시도 로직을 구현했지만, 클라이언트 입장에서는 연결만 끊기지 않을 뿐 하염없이 기다리게 된다. 따라서 로딩 상태를 시각적으로 표현할 필요가 있었다.

  • 요청 처리 중에는 입력창버튼"처리 중..." 문구를 표시.
  • 챗봇 응답 영역에는 결과가 준비 중임을 알리는 시각적 요소를 추가.

6-2.토스트 메세지 혹은 모달 끄기

  • 토스트 메시지모달ESC 키나 컴포넌트 외부 클릭으로 닫을 수 있도록 구현.




🧽 회고

문제점과 해결 과정

1. 소통 문제로 인한 협업 비효율

  • 문제: Spring Boot와 FastAPI라는 서로 다른 기술 스택을 다루는 개발자 간 소통에서 이슈가 발생. Notion을 통해 API 명세를 진행하고, Github Template을 커스텀하여 진행상황, 변경사항, 결과 등을 공유했으나 역부족이었음.
  • 해결:
    • 백문불여일견!! 제아무리 정성껏 문서화해도, 누군가에겐 외계어 그 이상도 이하도 아닐 수가 있다. 개발 막바지에는 디스코드 등의 화면 공유를 적극 활용하여 상호이해를 위해 힘썼다.

2. 병행 작업으로 인한 일정 지연

  • 문제: 취업 박람회 일정과 기타 스터디 병행으로 인해 프로젝트 진행 속도가 느려졌음. 팀원 또한 본업이 있기 때문에 야근이나 외근 등으로 진행이 어려운 상황이 종종 발생했음.
  • 해결:
    • 우선순위 재조정 -우리 프로젝트의 경우는 협업이 이루어지는 기능-을 통해 핵심 기능 구현을 우선적으로 완료함.
    • 서로의 일정을 존중하되, 마감일을 명확히 설정하여 프로젝트 텐션이 떨어지지 않게 유지함.

성과

기술적 성장

1. 리팩토링 과정에서의 클린 코드 적용

2. MSA 개발 경험

3. 프론트엔드 경험

협업 경험

  • NotionGit Issue 템플릿을 통한 문서화 경험.
  • 소규모 팀 내에서 명확한 역할 분담지속적인 회의를 통해 문제 해결.

느낀 점

1. 협업에서 소통의 중요성

이번 프로젝트를 통해 가장 크게 느낀 것은, 협업에서 소통의 중요성이다. 서로 다른 기술 스택을 사용하는 개발자 간에는 기술적 용어와 문서화된 내용만으로 모든 상황을 해결하기 어렵다는 것을 체감했다.
특히, 디렉토리 구조와 ERD 변경처럼 프로젝트의 근본적인 부분을 수정해야 할 때, 초반의 소통 미흡이 큰 영향을 미쳤다.
이후 디스코드 화면 공유와 같은 직접적인 커뮤니케이션 방법을 통해 문제를 해결했던 경험은 앞으로의 협업에서 매우 유용한 교훈이 될 것이다.

2. 계획보다 중요한 것은 유연성

애초에 한 달이라는 타이트한 일정으로 기획부터 배포까지 완성하는 것은 도전적인 목표였다.
하지만 예기치 못한 변수들로 인해 일정이 지연되면서, 계획을 수정하고 핵심 기능에 우선순위를 두는 유연함이 필요하다는 것을 다시 한번 느꼈다.
모든 작업을 한 번에 완벽하게 처리하기보다는, 진행 가능한 부분부터 차근차근 완성해나가는 것이 더 생산적인 결과를 만들어낸다는 점을 알게 되었다.

3. 기술적 성장과 책임감

이번 프로젝트는 단순히 기술을 배우고 적용하는 것을 넘어, 시스템 전체를 설계하고 최적화하며 사용자 경험까지 고려하는 과정이었다.
특히, 프론트엔드와 백엔드를 모두 담당하면서 데이터의 흐름과 API 설계, 그리고 사용자 인터페이스 간의 상호작용을 깊이 이해할 수 있었다.
특히, 프론트엔드 개발을 경험하며 얻은 자신감은 이후 프로젝트에서도 협업 혹은 프론트엔드 개발을 맡아야 하는 상황에서 큰 도움이 될 것이다.

4. 완벽하지 않아도 괜찮다

배포를 완료하지 못했다는 점은 아쉬움으로 남지만, 이번 프로젝트는 완벽보다는 학습과 성장에 집중하는 과정이었다.
웹을 온전히 도맡아 작업하면서 그동안 궁금했던 DDD 등의 방법론, 그리고 Spring Security, Spring Retry, WebClient같은 새로운 기술 스택을 성공적으로 적용한 경험은 목표 달성과 버금가는 가치가 있다고 생각한다.

⭐️ 5. 좋은 개발자란 무엇인가

이번 프로젝트를 진행하며 좋은 개발자란 무엇인가에 대해 깊이 고민하게 되었다.
마감 기한, 요구사항, 그리고 좋은 코드라는 세 가지 요소는 항상 개발자에게 주어진 중요한 과제다.
이번 프로젝트를 통해 깨달은 점은, 이 세 가지 요소를 균형 있게 맞추고, 상황에 따라 각 요소를 최대로 끌어올리는 것이 좋은 개발자의 역할이라는 것이다.

  • 마감 기한이 촉박한 상황에서는 최소한의 요구사항을 빠르게 충족시키는 현실적인 선택이 필요하다.
  • 반대로 시간이 충분하다면, 코드를 리팩토링하며 유지보수성과 재사용성을 높이는 데 집중할 수 있다.
  • 결국 좋은 개발자는 상황을 분석하고, 필요한 선택을 내릴 줄 아는 유연함을 가진 사람이라는 점을 깨달았다.

이번 프로젝트에서 목표를 완벽히 달성하지 못했지만, 이 과정을 통해 어떤 상황에서도 현실적이고 최선의 선택을 할 줄 아는 개발자로 성장할 수 있었다고 믿는다.

profile
https://sususoo.tistory.com/

1개의 댓글

comment-user-thumbnail
2024년 11월 22일

👍

답글 달기