1편 - 댓글에서 쓸만한 것만 골라내는 도구

임기호·2026년 5월 25일

댓글필터

목록 보기
1/3
post-thumbnail

댓글필터


자주 보는 블로그가 있다.

글도 읽지만 댓글도 꽤 챙겨보는 편이다. 문제는 블로그가 커지면서 글만 늘어난 게 아니라 댓글도 같이 늘었다는 거였다.

본문은 읽으려고 들어간 거니 그렇다 치는데 댓글에는 이런 게 계속 섞였다.

좋은 글 감사합니다.
ㅎㅎ
놀러오세요.
이웃 추가했습니다.

가끔은 댓글에 본문보다 좋은 정보가 있기도 했다.

저도 비슷한 일을 겪었는데...
이 부분은 조금 다르게 생각합니다.

결국 내가 하고 싶은 건 단순했다.

댓글을 안 보는 게 아니라, 읽을 만한 댓글만 보고 싶었다.

처음에는 안드로이드 앱으로 만들었다.

네이버 블로그를 WebView로 띄우고 댓글 내용을 보고 특정 댓글을 숨기는 방식이었다. React Native로 만들었고 구글 플레이에도 올렸다.

기존 안드로이드 앱

6개월 정도 실제로 썼다.

쓰다 보니 두 가지가 계속 걸렸다.

첫 번째는 iOS에서 쓸 수 없다는 것.

두 번째는 더 컸다.

키워드와 정규식만으로는 댓글의 의미를 구분할 수 없었다.


"좋은 글 감사합니다"를 어떻게 걸러야 하나

광고 댓글은 상대적으로 쉽다.

구독 부탁드립니다.
제 블로그에도 놀러오세요.

특정 키워드만 봐도 어느 정도 걸러진다.

그런데 이런 댓글은 애매하다.

정말 좋은 글 감사합니다.

스팸은 아니다.

악성 댓글도 아니다.

그렇다고 내가 시간을 들여 읽고 싶은 댓글도 아니다.

반대로:

저는 이 부분은 조금 다르게 봤습니다.
실제로 비슷한 상황에서...

이런 댓글은 길이가 조금 짧더라도 남겨두고 싶다.

정규식으로 계속 규칙을 추가하면 가능할 것 같았다.

실제로 해봤다.

잘 안 됐다.

규칙 하나를 추가하면 정상 댓글이 같이 잘렸고, 예외를 하나 넣으면 또 다른 댓글이 빠져나갔다.

어느 순간부터는 댓글을 거르는 코드를 만들고 있는 건지, 예외 목록을 관리하고 있는 건지 구분이 안 됐다.

결국 필요한 건 단어가 아니라 문장의 의미를 어느 정도 보는 것이었다.

그래서 다시 만들기로 했다.

이번에는 웹으로.

그리고 댓글 분류에 모델을 써보기로 했다.


서버에서 돌릴 생각은 없었다

모델을 쓰기로 하고 가장 먼저 고민한 건 어디서 돌릴지였다.

OpenAI나 Claude API를 붙이면 구현 자체는 쉽다.

문제는 이 서비스를 무료로 공개하고 싶었다는 거다.

사용자가 늘수록 API 비용도 그대로 늘어난다.

자체 서버에 모델을 올리는 방법도 있었다.

그러면 이번에는 GPU 서버 비용을 계속 내야 한다.

또 하나 마음에 걸린 게 있었다.

분석 대상은 댓글과 블로그 본문이다.

공개된 글이긴 하지만 사용자가 읽고 있는 데이터를 굳이 내 서버나 외부 AI API까지 보내고 싶지는 않았다.

내가 원한 조건을 적어보니 대략 이랬다.

사용자가 늘어도 AI 비용이 거의 늘지 않을 것
댓글과 본문을 외부 AI 서버로 보내지 않을 것
별도 GPU 서버를 운영하지 않을 것

이 조건이면 선택지가 별로 없었다.

사용자 브라우저에서 직접 모델을 돌리는 것.

마침 WebLLM과 Transformers.js가 있어서 실제로 해볼 만했다.


처음 생각한 구조는 단순했다

한 모델로 전부 처리할 생각은 없었다.

댓글 하나하나를 분류하는 데 생성형 LLM을 돌리는 건 너무 무거웠다.

반대로 본문을 요약하거나:

이 글 3줄로 요약해줘.
댓글 반응은 어때?
사람들이 제일 많이 얘기하는 건 뭐야?

같은 질문에는 문장을 생성하는 모델이 필요했다.

그래서 역할을 둘로 나눴다.

댓글 목록
   ↓
가벼운 모델로 댓글 분류
   ↓
읽을 만한 댓글만 남김

본문 / 댓글 질문
   ↓
LLM으로 요약·분석

지금은 이렇게 돌아간다.

Phase 1
Transformers.js
paraphrase-multilingual-MiniLM-L12-v2
약 120MB

Phase 2
WebLLM
Qwen2.5-1.5B
약 900MB

Phase 1은 댓글을 384차원 벡터로 만든 뒤 내가 미리 만들어놓은 "읽을 만한 댓글"과 "버릴 댓글" 예시와 비교한다.

Phase 2는 본문 요약이나 댓글 반응 분석처럼 실제 문장을 만들어야 할 때만 사용한다.

처음부터 이 구조였던 건 아니다.


첫 모델부터 잘못 골랐다

처음에는 다국어 BERT 감성 분류 모델을 썼다.

긍정 / 부정 / 중립 정도를 구분하면 댓글 품질도 어느 정도 따라올 줄 알았다.

실제로 돌려보니 이런 댓글들이 문제였다.

철렁했습니다.
놀랐어요.

모델은 부정으로 분류했다.

틀린 결과라고 하기도 어렵다.

감성 분석 관점에서는 실제로 부정적인 표현일 수 있다.

문제는 내가 궁금한 게 감성이 아니었다는 거다.

나는 "이 댓글이 긍정적인가?"를 묻고 있었던 게 아니라 "읽을 만한가?"를 묻고 있었다.

모델보다 질문을 잘못 정한 쪽에 가까웠다.

그래서 감성 분류를 버리고 문장 임베딩으로 갈아탔다.

댓글을 직접 분류시키는 대신, 내가 만든 예시 중 어느 쪽과 더 비슷한지를 본다.

이렇게 바꾸고 나서야 내가 생각했던 필터에 가까워졌다.

이 부분은 2편에서 코드까지 포함해서 따로 정리했다.


브라우저에서 돌리면 공짜지만 공짜는 아니었다

서버 비용은 거의 없어졌다.

Vercel에 웹만 올리고 모델 계산은 사용자 기기가 한다.

댓글 원문도 분석 과정에서 사용자 단말 밖으로 보낼 필요가 없다.

이 부분은 생각했던 대로였다.

대신 비용을 사용자의 기기가 낸다.

특히 Phase 2가 그렇다.

Qwen 1.5B 모델은 약 900MB고 WebGPU가 필요하다.

데스크탑이나 노트북에서는 꽤 잘 돌아가는데 모바일은 상황이 다르다.

지원 여부도 기기와 브라우저마다 다르고 900MB짜리 모델을 휴대폰에서 받는 것 자체가 부담스럽다.

그래서 지금은 PC 사용을 권장하고 있다.

모바일에서는 앞으로 세 가지를 보고 있다.

분류만 켜고 요약 기능은 끄기
더 작은 모델로 자동 변경하기
필요한 경우에만 서버 API 사용하기

아직 어느 쪽으로 갈지는 정하지 않았다.

실제로 써보면서 정할 생각이다.


지금 제일 마음에 안 드는 건 요약이다

댓글 분류는 생각보다 괜찮아졌다.

오히려 현재 가장 아쉬운 건 본문 요약 쪽이다.

1.5B 모델이다 보니 가끔 없는 말을 만든다.

고유명사를 이상하게 바꾸기도 하고, 긴 본문에서는 별로 중요하지 않은 부분을 잡고 늘어질 때도 있다.

한국어 답변 중간에 영어 표현이 끼는 경우도 있다.

그래서 지금은 본문이 길면 한 번에 답을 만들지 않는다.

먼저 질문과 관련 있는 부분만 추리고, 그 결과만 가지고 다시 답하게 한다.

본문 전체
   ↓
질문과 관련 있는 구절 추출
   ↓
추출된 내용만 가지고 답변

이렇게 바꾸니 조금 나아졌다.

그래도 아직 만족스럽지는 않다.

한국어에 더 잘 맞는 모델을 써볼지, 본문을 잘게 나눠 필요한 부분만 찾는 식으로 갈지 계속 테스트하고 있다.


결국 하고 싶었던 건 거창하지 않았다

이걸 만들면서 LLM이 꼭 필요했느냐고 하면 기능 전체에는 아니다.

오히려 반대에 가깝다.

명백한 스팸은 정규식으로 거르면 되고, 댓글 분류에는 작은 임베딩 모델이면 충분하다.

LLM은 요약이나 질문처럼 정말 생성이 필요한 곳에만 쓴다.

처음에는 "브라우저에서 LLM을 돌려보자"가 재미있어서 시작한 면도 있었다.

만들다 보니 기준이 조금 바뀌었다.

모델을 어디에 쓸지가 아니라 어디에는 안 써도 되는지를 정하는 게 더 중요했다.

그리고 서버에서 모델을 돌리지 않아도 이런 정도의 기능은 브라우저 안에서 꽤 구현할 수 있다는 것도 확인했다.

물론 그 과정이 순탄하지는 않았다.

특히 Web Worker 하나 띄우는 데 며칠을 쓸 줄은 몰랐다.


다음 글에서는 실제 구현을 정리했다.

2편 — 브라우저에서 댓글을 분류하고 요약하기까지

감성 분석을 버리고 임베딩으로 바꾼 이유, 예시 기반 분류, WebLLM, 긴 글을 두 단계로 처리한 과정까지 담았다.

그리고 모델도 프롬프트도 다 만들어놓고 정작 Worker가 뜨지 않았던 문제는 3편에 따로 적었다.

3편 — Web Worker 세 번 막힌 기록

0개의 댓글