Doupamine
Reviews/ORIGINAL

조회수는 거짓말하지 않는다. 다만 수집기가 자꾸 거짓말했다

웹소설 작가가 CSV 한 장에서 Chrome 웹스토어 출시까지 간, 조금 길고 자주 망가진 바이브 코딩 기록

D
Doupamine
2026년 7월 14일 · 읽는 시간 16분
FREE
조회수는 거짓말하지 않는다. 다만 수집기가 자꾸 거짓말했다

웹소설을 연재하다 보면 새로고침 한 번에도 온갖 의미를 부여하게 된다.

조회수가 세 명 늘면 드디어 입소문이 시작된 것 같고, 어제보다 연독이 조금 떨어지면 7화의 그 장면을 괜히 넣었나 싶다. 사실 독자 세 분은 우연히 같은 시간에 접속했을 뿐이고, 최신화 조회수는 아직 덜 쌓였을 수도 있다. 하지만 연재 중인 작가에게 숫자는 숫자로 끝나지 않는다. 대개 희망이거나 불안이고, 가끔은 사형 선고문처럼 보인다.

필자도 별반 다르지 않았다.

플랫폼의 회차 목록을 들락날락하며 계산기를 두드리다가 문득 생각했다.

이걸 왜 내가 매번 계산하고 있지?

엑셀에 회차와 조회수를 넣으면 연독률을 그려 주는 작은 페이지가 있으면 좋을 것 같았다. 파란 선 하나가 흐름을 보여 주고, 크게 무너진 지점에는 빨간색 표시가 뜨는 정도. 처음 머릿속에 있던 것은 정말 그게 전부였다.

말이 씨가 된다는 말이 있다. 개발에서는 대체로 좋지 않은 쪽으로 씨가 된다.

CSV 한 장은 곧 작품 페이지 자동 수집이 되었고, 자동 수집은 여러 페이지를 넘겨야 했으며, 숫자를 모으고 나니 왜 떨어졌는지 읽어 주는 화면이 필요했다. 그러다 등급이 생기고, 그래프가 생기고, 최신 회차 보정과 시간별 추적, 내 서재까지 생겼다.

그렇게 웹소설 지표 분석기 - 이탈 진단소가 만들어졌다.

현재 분석 개요. 처음 꿈꿨던 파란 선 하나는 어느새 건강도, 초반 정착, 최대 급락과 객관적 해석을 품은 대시보드가 되었다.
현재 분석 개요. 처음 꿈꿨던 파란 선 하나는 어느새 건강도, 초반 정착, 최대 급락과 객관적 해석을 품은 대시보드가 되었다.

숫자들이 갑자기 말을 걸기 시작했다

처음 만든 CSV 분석기는 제법 그럴듯했다.

1화를 100%로 놓고 이후 회차에 독자가 얼마나 남았는지 선으로 이었다. 회차 하나가 갑자기 꺼지면 점의 색을 바꾸고, 세 회차 이동 평균을 겹쳐서 일시적인 흔들림과 진짜 추세를 나누었다. 숫자를 표로 볼 때는 그저 91.2, 89.7, 90.1이었는데 선으로 이어 놓으니 작품의 호흡처럼 보였다.

여기까지는 평화로웠다. CSV는 적어도 거짓말을 하지 않았으니까.

그런데 사용자가 직접 CSV를 만들어야 한다면 결국 나만 쓰는 프로그램이 된다. 남에게 엑셀을 켜라고 요구하는 순간, 편리한 도구는 숙제가 된다. 그래서 작품 페이지에서 버튼 한 번으로 회차를 가져오기로 했다.

이때부터 숫자들이 갑자기 다른 말을 하기 시작했다.

노벨피아의 회차 한 줄에는 EP.7도 있고 글자 수도 있고 조회수도 있고 댓글과 추천도 있다. 처음에는 EP 다음 숫자가 조회수인 줄 알았다. 너무 자연스럽게 틀렸다. 그 숫자는 글자 수였다. 사람 모양 아이콘 다음에 있는 숫자가 조회수였고, 그 뒤로 댓글과 추천이 따라왔다.

페이지의 숫자들은 모두 비슷한 얼굴을 하고 있었지만 신분은 전혀 달랐다.

공지사항은 회차인 척 끼어들었고, 무료, PLUS, 19 같은 배지는 제목인 척 따라왔다. 수집 결과 중간에 조회수가 0으로 곤두박질친 적도 있었다. 작품이 망한 것이 아니라 수집기가 엉뚱한 숫자를 데려온 것이었다. 화면은 멀쩡했고 그래프도 아주 정직하게 잘못된 데이터를 그렸다.

이게 오히려 무서웠다. 깨진 화면은 누구나 알아보지만, 잘못된 숫자는 멀쩡한 표정을 짓는다.

이 앱은 작품명을 검색하는 도구가 아니다. 노벨피아나 문피아의 회차 목록에서 시작한다는 사실부터 다시 설명해야 했다.
이 앱은 작품명을 검색하는 도구가 아니다. 노벨피아나 문피아의 회차 목록에서 시작한다는 사실부터 다시 설명해야 했다.

20화에서 세계가 끝나는 기계

현재 페이지에서 20화를 가져오는 데 성공했을 때는 거의 다 만든 줄 알았다.

물론 아니었다.

연재작은 20화에서 끝나지 않는다. 화면 아래에는 1, 2, 3이라는 조그만 페이지 번호가 있었고, 수집기는 마지막 페이지까지 그것을 따라가야 했다. 사람 눈에는 너무 당연한 일이지만 프로그램은 페이지 번호와 작품 안의 다른 숫자를 구분하지 못했다.

처음에는 다음 페이지 주소를 추측했다. 어떤 작품에서는 잘 됐다. 그래서 기뻐했다. 다른 작품에서는 같은 1페이지만 계속 가져왔다. 페이지 번호처럼 보이는 버튼을 넓게 찾게 만들었더니 이번에는 엉뚱한 곳을 돌아다녔다. 100페이지 제한을 걸어 두었는데 100페이지까지 한참을 달리고도 같은 회차만 물어오는 광경을 본 적도 있다.

세계가 20화에서 끝나는 기계를 고치려다가, 같은 세계를 100번 반복하는 기계를 만든 셈이다.

심지어 수집이 끝난 뒤 공지사항을 눌러 버리거나 노벨피아의 알림 신청을 켜는 일도 있었다. 나는 조회수를 알고 싶었을 뿐인데 어느새 작품의 충실한 구독자가 되어 있었다.

이쯤 되면 버튼을 누를 때마다 무엇이 일어날지 약간 긴장하게 된다.

페이지 넘김은 결국 주소가 아니라 목록의 변화로 확인해야 했다. 화면 아래 실제 페이지 영역 안에서만 다음 번호를 찾고, 눌렀다면 이전과 다른 회차 번호와 조회수 묶음이 나타났는지 검사했다. 같은 목록이 다시 나오면 멈췄다. 예상 회차 수와 모은 회차 수가 맞지 않으면 성공한 척하지 않고 경고를 띄웠다.

말로 쓰면 몇 줄이다. 이 몇 줄에 가장 많은 시간이 들어갔다.

사이트는 얌전한 표가 아니었다. 화면 안의 목록만 바뀌기도 했고, 로그인과 성인 인증에 따라 보이는 범위가 달랐으며, 플랫폼이 개편되면 어제의 정답이 오늘의 오답이 되었다. 문피아는 /novel/574789였던 주소가 /novel/detail/574789가 되었고, 작품 하나에서 잘 되던 선택자는 다른 작품에서 아무것도 찾지 못했다.

그리고 어느 날 이런 문장이 떴다.

Extension context invalidated.

에러 문장은 놀라울 만큼 침착했다. 확장 프로그램을 다시 불러온 사이, 먼저 열려 있던 탭의 콘텐츠 스크립트가 옛 세계에 남겨졌다는 뜻이었다. 수집은 다 했는데 분석창을 열려는 마지막 순간에 세계가 사라진 것이다.

프로그램은 품위 있게 죽고, 그것을 보는 사람만 품위를 잃는다.

중간에는 Claude의 토큰을 다 써서 Codex로 작업을 이어 갔다. AI를 바꾸면 문제가 새것으로 교체될 줄 알았지만, 버그는 충성심이 강했다. 코드뿐 아니라 ‘왜 사람 아이콘 다음 숫자가 조회수인지’, ‘왜 공지를 제외해야 하는지’ 같은 맥락까지 다시 넘겨야 했다. AI에게도 인수인계는 필요했다.

1화는 100퍼센트다

수집기가 숫자를 제대로 데려오기 시작하자 이번에는 계산이 수상했다.

1화의 연독률이 100%가 아니었다.

이것은 꽤 철학적인 문제처럼 보일 수 있지만 사실 산수 문제다.

1화 조회수 ÷ 1화 조회수 × 100 = 100%

2화부터는 2화 조회수를 1화 조회수로 나눈다. 3화도 같은 방식이다. 처음 들어온 독자 가운데 지금까지 몇 명이 남았는지를 보는 기준선이므로 1화는 언제나 100%여야 한다.

직전 화 대비 연독은 또 다른 질문이다. 8화 조회수를 7화 조회수로 나누면 7화에서 8화로 넘어오며 얼마나 남았는지 알 수 있다. 작품 전체의 체력과 특정 경계의 낙폭은 같은 그래프에 억지로 섞으면 안 됐다.

4화 기준도 한동안 말을 서로 다르게 이해했다. 최종 정의는 간단했다. 4화를 새로운 출발선 100%로 고정한다. 5화는 5화 조회수를 4화로 나누고, 6화도 4화로 나누며, 최신화까지 같은 기준을 쓴다. 초반 탐색을 마친 독자들이 얼마나 남는지를 보려는 것이다.

그래서 지금은 세 개의 눈으로 작품을 본다. 1화 기준은 장기 생존율, 직전 화 기준은 이탈이 벌어진 순간, 4화 고정 기준은 초반 정착 이후의 체력이다.

한 작품도 기준선을 어디에 놓느냐에 따라 전혀 다른 이야기를 한다. 선과 점에 마우스를 올리면 회차 값과 의미를 바로 확인할 수 있다.
한 작품도 기준선을 어디에 놓느냐에 따라 전혀 다른 이야기를 한다. 선과 점에 마우스를 올리면 회차 값과 의미를 바로 확인할 수 있다.

상위·하위 5화도 처음에는 연독률 자체로 뽑았다. 그랬더니 뒤쪽 회차가 늘 하위권을 차지했다. 당연하다. 1화를 기준으로 보면 40화는 대개 10화보다 낮다. 그러나 작가가 정말 알고 싶은 것은 바닥의 위치가 아니라 갑자기 발이 빠진 계단이다.

지금의 급락 TOP 5는 직전 화보다 가장 크게 줄어든 변화 지점을 보여 준다. ‘어디가 가장 낮은가’가 아니라 ‘어디에서 가장 많이 잃었는가’를 묻는다.

낮은 회차를 줄 세우는 대신 독자가 크게 빠져나간 경계를 먼저 보여 준다. 원인은 단정하지 않고 확인할 지점을 남긴다.
낮은 회차를 줄 세우는 대신 독자가 크게 빠져나간 경계를 먼저 보여 준다. 원인은 단정하지 않고 확인할 지점을 남긴다.

예쁘지 않은 숫자는 오래 보지 않는다

기능이 작동하면 끝이라고 생각했던 시기도 있었다.

그런데 숫자는 보기 싫게 놓여 있으면 보지 않게 된다. 초창기 화면은 한 페이지에 카드와 표가 끝없이 이어졌다. 회차가 늘수록 그래프의 점은 서로 달라붙었고, 중요한 수치와 참고용 설명은 똑같은 목소리로 떠들었다.

Slack의 조용한 사이드바와 GitHub의 빽빽하지만 길을 잃지 않는 화면을 떠올렸다. 요약, 흐름 분석, 급락 분석, 데이터, 자동 추적, 내 서재를 나누고 핵심 지표에는 색과 크기의 차이를 줬다. 그래프는 선과 막대를 바꿔 볼 수 있게 했고, 긴 작품은 가로로 이동하며 회차를 좁혀 보게 했다.

한때 급락 표시 아이콘이 정말 한 글자였다.

기능적으로는 아무 문제가 없었다. 미학적으로는 많은 문제가 있었다. 그런 흔적도 하나씩 걷어 냈다.

등급은 SSS부터 D까지 붙였다. 헌터 등급처럼 한눈에 들어오지만 작품의 재미나 작품성을 판정하는 것은 아니다. 초반 정착, 최근 안정성, 급락 방어 같은 관측 가능한 수치의 상태를 읽기 쉽게 환산한 것이다. 왜 그 점수가 나왔는지 가중치와 계산 근거도 함께 열어 볼 수 있게 했다.

원고를 읽지도 않은 프로그램이 ‘사이다를 앞당기세요’, ‘주인공의 실력을 빨리 보여 주세요’라고 말하는 것도 없앴다. 그런 말은 대체로 어디에 붙여도 그럴듯하고, 그래서 어디에도 정확하지 않다.

지금의 기본 진단은 세 가지만 말한다. 무엇이 관측되었는지, 어떤 가능성이 있는지, 작가가 무엇을 직접 확인해야 하는지. 조회수만으로 독자의 마음을 독심술처럼 읽는 척하지 않는다.

출시 버튼은 결승선이 아니었다

Chrome 웹스토어에 올리기 직전에는 코드가 아닌 것들이 줄지어 나타났다.

아이콘이 필요했고, 스크린샷이 필요했고, 작은 프로모션 타일과 마키 이미지도 필요했다. 개인정보처리방침 주소를 적었더니 404가 떴다. 심사 화면은 원격 코드를 사용하는지 물었다. AI API 키는 어디에 저장되고 어떤 데이터가 전송되는지 설명해야 했다.

그전까지 제품은 ‘내 컴퓨터에서 작동하는 것’이었다. 출시를 준비하면서 비로소 ‘남의 컴퓨터에서 오해 없이 작동해야 하는 것’이 되었다.

그리고 결국 웹스토어에 올라갔다.

막상 출시하고 나니 처음 쓰는 사람은 이 앱을 작품명 검색기로 오해했다. 최신화는 조회수가 아직 쌓이는 중인데 전체 등급을 끌어내렸다. 수집이 실패하면 사용자는 자기가 잘못한 것인지 사이트가 바뀐 것인지 알 수 없었다.

그래서 첫 실행 안내를 만들고 현재 페이지가 수집 가능한 작품 페이지인지 팝업에서 알려 주었다. 최신 4화는 데이터를 지우지 않고 주요 점수와 급락 분석에서만 기본 제외했다. 그래프 안에서는 잠정 데이터로 남겨, 나중에 숫자가 자라는 모습까지 볼 수 있게 했다.

출시는 완성품을 세상에 내놓는 의식이라기보다, 혼자서는 생각하지 못한 오해를 수집하는 첫날에 가까웠다.

그래프에 시간이 들어왔다

한 번 찍은 조회수는 사진과 같다. 떨어진 흔적은 보여 주지만 움직이는 방향까지는 알 수 없다.

가령 1화 조회수가 어제보다 30 늘었다면 새로운 독자가 작품 입구로 30명 들어온 셈이다. 최신화 조회수가 같은 시간 동안 120 늘었다면 현재 연재를 따라오는 독자의 반응 속도를 볼 수 있다. 물리학을 전공한 사람답게 굳이 표현하자면, 조회수는 위치이고 증가량을 시간으로 나눈 값은 속도다.

드디어 전공이 아주 조금 쓸모를 찾았다.

그래서 자동 추적 화면의 맨 앞에는 1화 신규 유입최신화 조회 변화를 두었다. 실제 수집 간격이 달라도 시간당 변화량으로 환산하고, 새 회차가 올라오면 첫 관측부터 24시간 동안 조회수가 어떻게 성숙하는지 곡선으로 남긴다.

노벨피아에서는 선호작과 알림, 작품 추천 수를 같이 기록하고 문피아에서는 선호작과 좋아요를 읽는다. 작품 헤더를 못 찾았다고 회차 수집까지 같이 죽지 않도록 둘은 분리했다. 부가 지표는 부가 지표답게 실패해야 한다.

숫자에 시간이 붙자 유입과 최신화 반응이 속도로 보이기 시작했다. 최신화별 첫 24시간 성장 곡선도 같은 자리에서 비교한다.
숫자에 시간이 붙자 유입과 최신화 반응이 속도로 보이기 시작했다. 최신화별 첫 24시간 성장 곡선도 같은 자리에서 비교한다.

기록이 쌓이니 작품을 책장처럼 모아 보고 싶어졌다. 다만 플랫폼 랭킹을 긁어 타인의 작품을 멋대로 줄 세우지는 않았다. 사용자가 직접 등록한 작품만 내 서재에 꽂고, 1화 유입 속도와 최신화 성장, 최근 연독, 조회 대비 추천·좋아요와 댓글 반응을 같은 기준으로 비교한다.

금·은·동도 붙는다. 조금 유치한가 싶지만 이런 것은 원래 약간 유치해야 재미있다. 대신 작품성 순위가 아니라는 문장은 분명하게 남겼다. 숫자는 작품의 움직임을 보여 줄 수는 있어도 소설의 아름다움을 대신 읽어 주지는 못한다.

직접 고른 작품만 한 책장에 꽂아 같은 지표로 비교한다. 금·은·동은 재미를 위한 장치이지 작품성의 판결문이 아니다.
직접 고른 작품만 한 책장에 꽂아 같은 지표로 비교한다. 금·은·동은 재미를 위한 장치이지 작품성의 판결문이 아니다.

AI와 함께 만들었다는 말의 실제 의미

바이브 코딩이라고 하면 원하는 것을 말로 설명하고 커피 한 잔 마시는 동안 제품이 뚝딱 나오는 장면을 떠올리기 쉽다.

필자의 경험은 조금 달랐다.

AI는 코드를 아주 빨리 만들었다. 그리고 틀린 가정도 아주 빨리 코드로 만들었다.

EP 다음 숫자가 조회수겠지. 글자 수였다.

다음 페이지 주소는 일정하겠지. 같은 페이지가 돌아왔다.

좋아요는 구매수보다 작겠지. 문피아 유료 회차에서는 그렇지 않을 수 있었다.

최신화 조회가 낮으니 이탈이겠지. 아직 독자가 읽는 중이었다.

AI가 무능해서 생긴 일만은 아니다. 내가 요구를 대충 설명했기 때문에 대충 설명한 세계가 코드 안에 정확히 만들어진 경우도 많았다. ‘알아서 잘 수집해 줘’라는 문장에는 사람 눈에만 보이는 상식이 너무 많이 숨어 있었다.

노벨피아에서 사람 모양 아이콘 다음 숫자가 조회수라는 것, 문피아에서 무료 회차의 조회가 유료화 뒤 구매로 바뀐다는 것, 4화 기준은 4화를 분모로 고정한다는 것. 이런 규칙은 화면을 실제로 본 사람이 짚어 줘야 했다.

내가 해야 할 일은 프롬프트를 멋지게 쓰는 것이 아니었다. 틀린 결과를 보고도 ‘대충 맞네’라고 넘기지 않는 것, 이상한 숫자가 나온 화면을 붙잡아 반례로 만드는 것, 하나를 고쳤을 때 다른 하나가 다시 무너지지 않는지 확인하는 것이었다.

결국 파서 문장, 페이지 중복, 연독률 공식, 최신 회차 제외, 등급, 자동 추적을 각각 테스트로 묶었다. 브라우저에서 한 번 눌러 보고 끝내지 않고, 패키지 안에 필요한 파일이 모두 들어갔는지와 긴 그래프가 실제 픽셀로 그려지는지까지 검사했다.

돌이켜 보면 이 앱의 진짜 발전은 기능이 늘어난 일이 아니었다.

틀렸을 때 틀렸다는 사실을 알 수 있게 된 일이었다.

처음에는 오늘 성적이 좋은지 조졌는지 빨리 알려 주는 작은 도구를 원했다. 지금은 작품 페이지에서 회차를 모으고, 잘못 읽은 값을 고치고, 급락을 찾고, 최신화의 덜 익은 숫자를 걷어 내고, 시간에 따른 유입 속도를 기록하는 하나의 작업실이 되었다.

다음 업데이트에서도 무언가는 분명 깨질 것이다. 웹사이트는 바뀌고 브라우저도 바뀌며, 내가 또 새로운 욕심을 낼 테니까.

그래도 예전처럼 막막하지는 않다.

조회수는 거짓말하지 않는다. 수집기는 가끔 거짓말한다. 그리고 이제는 그 거짓말을 잡아낼 방법이 조금 생겼다.

웹소설 지표 분석기 - 이탈 진단소 설치하기

공유X에 공유Threads에 공유