Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ feat: RSS 승인시 피드 크롤링 AI를 활용하여 태그 + 요약 기능 추가 #46

Merged
merged 19 commits into from
Feb 12, 2025

Conversation

Jo-Minseok
Copy link
Collaborator

@Jo-Minseok Jo-Minseok commented Feb 12, 2025

🔨 테스크

인공지능 모델 고려

  • Ollama
    Ollama를 이용하여 Deep Seek나 Llama 3.2, 3.3 버전을 고려했으나 클라우드 환경에 구축하기에는 자원이 많이 필요하고 동작하는데에도 클라우드 인스턴스 사양으로는 턱없이 부족하다고 판단.
  • ChatGPT
    Claude보다 부정확한 답변을 내는 경우가 많았으며, 비용도 Claude보다 비쌈
  • Clova
    프롬프트에 서비스에서 제공해주는 태그만 사용하라고 했으나, 제공한 태그 외의 태그를 부착하는 문제를 발견. 강제적으로 제한을 걸어도 되지 않았고, 출력 양식도 계속 지키지 않는 모습을 확인
  • Claude ⭐
    GPT 보다 저렴했고, 정확도가 상당히 높았음. 제공한 태그 목록 내에서의 태그만 부착하였고, 글 요약도 한국어를 자연스럽게 요약했음

인공지능으로 인해 느려진 API 속도 어떻게 개선할 수 있을까?

  • 기존에는 RSS 승인시, 피드 크롤링 하는 부분을 asynchronus + Blocking 방식을 사용했었다.
  • 기존에 이메일 전송은 asynchronus + non blocking 방식을 사용했었다. SMTP 서버로 요청을 보내는데 너무 오랜 시간이 지연됐었기 때문에 백그라운드로 돌릴 수 있게 했다.
  • AI 기능을 추가하니 피드 크롤링에서 asynchronus + blocking 방식이 상당히 느려졌다. 게시글 5개에 요약 및 태그를 달기 위해 claude에게 요청을 보내니 46초의 시간이 발생했다.
    클라이언트에게 응답을 보내기에는 너무 긴 시간이었고, 블로그 게시글이 20개만 되어도 이론상 46초*4의 시간이 발생한다.
  • 로직상 batch를 돌리기 어려웠고, 개선을 할 수는 있다만 이번 주 금요일 데모 발표를 위해 빠르게 구현할 필요가 있다.
  • 등록되었음을 알리는 응답 자체는 빠르게 하지만, 이메일 전송 로직을 어짜피 백그라운드에서 동작하게 했으니 피드 크롤링도 비동기로 돌리면 응답은 빠르게 할 수 있을 것이라 판단했다.
  • 46초(46200ms) -> 169ms로 줄일 수 있었다.
  • 위 방식을 사용할 때 주의해야 할 점은 무조건 우리가 처리할 수 있는 RSS가 들어와야 한다는 것이다. 현재 github.io rss는 받지 못하기에 이런 경우 RSS 등록만 되고 피드를 가져올 수 없다.

인공지능 추가로 비동기적으로 바뀐 피드 크롤링의 E2E 테스트 DB 판단?

  • 비동기적으로 피드 크롤링이 바뀌었기에 DB 테스트를 하는 시점에 데이터 삽입이 안 되어 있을 수 있다.
  • E2E 테스트에 대해서 알아보니 DB에 변경된 데이터를 검증하는 것은 E2E가 아닌 Unit 테스트에서 이루어져야 한다고 판단했다.
  • 결론적으로 DB에 데이터가 삽입되었는지 확인하는 테스트를 acceptRss에서 제거했다.
  • 추가적으로 테스트 코드 리팩토링이 필요할 것 같다. rejectRss, 회원가입 E2E 테스트에서는 DB에 데이터 삽입 확인도 함께하고 있기에 제거할 필요성이 있다.

인공지능 토큰 비용 줄이기

  • 우리는 RSS Xml에서 게시글 내용을 추출한다.
    image
    이럴 경우 XML 태그들이 함께 Claude에게 전송된다.
    Input 태그로 전부 인식 되기에 토큰 비용이 상당히 많이 발생한다.
    sanitizer 라는 html 태그 정리 라이브러리를 사용하여 태그를 전부 제거하고 내용만 보낼 수 있도록 하여 토큰 비용을 절감했다.

📋 작업 내용

  • Claude를 활용한 프롬프트 서비스 구현
  • RSS 승인시, AI로 글 요약 및 태그를 정리하도록 로직 추가
  • 테스트 코드 ai 기능 추가에 따라 AI 요청 Mocking 처리
  • 피드 크롤링에서 AI 기능이 추가되면서 API 응답 속도가 저조하여 크롤링 부분만 비동기로 추출
  • CI/CD 환경 변수 추가

📷 스크린 샷(선택 사항)

image

@Jo-Minseok Jo-Minseok added the ✨ Feature 기능 구현 label Feb 12, 2025
@Jo-Minseok Jo-Minseok self-assigned this Feb 12, 2025
Copy link
Member

@asn6878 asn6878 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

고생 많으셨습니다 :)
함께 고민할 거리들 남겨보았어요!

추가적으로 테스트 코드 리팩토링이 필요할 것 같다. rejectRss, 회원가입 E2E 테스트에서는 DB에 데이터 삽입 확인도 함께하고 있기에 제거할 필요성이 있다.

에 대해서 저도 고민이 되어 조금 알아봤는데요.
제가 파악한 바에 따르면, 지금까지 저희가 'E2E 테스트'라고 명명해온 것들이 사실은 통합(Integration) 테스트의 성격을 띠고 있다는 점에서 혼란이 있었던 것 같습니다.

저는 그동안 단순히 두 테스트가 거의 동일한 것인줄 알았는데, 두 테스트는 원하는 요구사항의 시점이 다르더라구요. (E2E 테스트 vs Integration 테스트)

이 글에 따르면 어떤 곳에서는 E2E 테스트를 실제 프로덕션 레벨의 DB를 활용해 테스트를 수행한다고 합니다. (실제 DB내에 존재하는 데이터들과의 연관성 까지 배제할 수 없기 때문에) 그리고 이에 따른 사용자가 보게될 반환값 까지의 프로세스를 검증한다고 합니다.

결국 E2E 테스트는 실제 저희 서비스를 사용하는 사용자들의 관점, Integration 테스트는 해당 모듈(저희로 치면 NestJS)의 전체 동작이 정상적으로 이어지는지 검증하는 것이라고 하네요.

현재 테스트에서는 API 요청이 들어와 해당 모듈(예를 들어, NestJS 전체 스택)이 정상적으로 작동하는지, 그리고 내부적으로 Repository의 findOne 메서드를 통해 실제 DB에 데이터가 삽입되었는지 까지를 검증하고 있습니다. 그러나 실제 사용자 입장에서는 RSS 승인 후 DB 내부 데이터를 직접 조회하지 않고, 단지 API의 응답을 통해 결과를 확인할 것입니다.

따라서, 사용자 관점의 전체 플로우를 검증하는 것이 진정한 E2E 테스트라면, 현재 민석님이 수정해주신 것 처럼 API의 요구사항이 정확하게 수행되고 의도한 형태의 응답이 사용자에게 전달 되었는지 확인하는 것만으로 충분해야 합니다.

이러한 관점에서, 저희가 지금까지 'E2E 테스트'라고 부른 테스트들의 이름을 Integration 테스트로 분류하고, DB단 까지 확인하는 것이 더 적절하다고 생각합니다.

왜냐하면 이미 저희는 API의 비즈니스 로직이 DB까지 잘 처리 되었는지 확인할 수 있는 환경을 갖추고 있고, 이를 굳이 E2E 테스트를 해야한다! 라는 관점이 DB단 검증을 할 수 있음에도 불구하고 하지 않을 사유는 되지 않는다고 생각했기 때문입니다.

@Jo-Minseok @CodeVac513 두 분 생각은 어떠신가요?

server/src/rss/service/ai-tag-summary.service.ts Outdated Show resolved Hide resolved
server/src/rss/service/feed-crawler.service.ts Outdated Show resolved Hide resolved
server/src/rss/service/rss.service.ts Show resolved Hide resolved
Copy link
Collaborator

@CodeVac513 CodeVac513 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

민석님 수고 많으셨습니다! 👏
비슷한 내용을 작업했는데, 민석님께서 설계를 잘하셔서 그런지 배울 점이 많네요. :)


저도 acceptRssBackProcess 부분을 보면서, 비동기/논블로킹으로 진행한 작업의 확인이나 운영에서의 안정성을 위해 로그가 필요하다 느꼈습니다. request 부분에 로그를 남기기는 하지만, content만 남는 상황이라 어떤 피드인지 분석에 어려움이 있을 것 같더라구요.

이 부분은 성윤님이 코멘트를 잘 남겨주셔서 따로 더 작성하지는 않았고 살짝만 언급하겠습니다!

server/src/rss/service/ai-tag-summary.service.ts Outdated Show resolved Hide resolved
Copy link
Member

@asn6878 asn6878 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

질문사항 확인해주셔서 감사합니다!
고생하셨어요 👍

@Jo-Minseok Jo-Minseok merged commit 6c90781 into main Feb 12, 2025
2 checks passed
@Jo-Minseok Jo-Minseok deleted the feat/server-tag-summary branch February 12, 2025 17:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
✨ Feature 기능 구현
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants