KakaoMusic 플레이리스트 추출 파이프라인의 OCR 품질 개선 전략
초록
EasyOCR 기반 KakaoMusic 플레이리스트 추출 파이프라인에서 발견된 행 밀림·UI 잡음·근접 중복 문제의 원인을 진단하고 수정한 과정(2,361건→1,598곡)을 기록하고, 잔여 오류(~1.5%)의 근본 원인이 스크롤 경계 클리핑임을 좌표 기반으로 실측 확증했다. 이어 human-in-the-loop 검수 도구(/review)의 발전 과정과, 원본 스크린샷 대조를 통한 전수 검수가 왜 가장 확실하고 효율적인 품질 개선 경로인지, 그리고 이 과정에서 축적되는 143건의 (OCR 원본→정답) 학습 데이터 쌍을 기록한다.
[Thesis Appendix] OCR Quality Improvement Strategy for the KakaoMusic Playlist Extraction Pipeline
Abstract
이 문서는 Waydroid 컨테이너에서 캡처한 KakaoMusic 플레이리스트 스크린샷(170장)을 EasyOCR로 추출하는 과정에서 발견된 데이터 품질 문제들과 그 근본 원인, 적용한 수정 사항, 그리고 잔여 오류를 줄이기 위한 향후 개선 전략을 기록한다. 초기 추출 결과는 2,361건이었으나 실제 플레이리스트는 1,491곡이었고, 페어링 로직 결함으로 다수 행이 밀려 있었다. 좌표 기반 재설계와 근접 중복 제거, 로컬/외부 교차검증을 거쳐 1,598곡으로 정리했으며, 잔여 가비지(~1.5%)는 캡처 해상도/폰트 두께에서 기인하는 OCR 엔진 자체의 한계로 진단했다. 이에 대한 단계적 개선 전략과, 수작업 검수를 지속 가능하게 만드는 human-in-the-loop 검수 도구(/review)를 함께 제시한다. 이 도구로 실제 진행 중인 전수 검수 작업(작성 시점 기준 170장 중 약 1/6, 143건의 OCR-정답 학습 데이터 쌍 확보)과 그 결과를 7장에 기록한다.
1. 배경: 초기 파이프라인과 증상
extract_playlist_gpu_fix.py는 캡처 이미지를 크롭한 뒤 EasyOCR로 텍스트 라인을 읽고, "위에서부터 두 줄씩 제목/가수로 묶거나, 한 줄에 " - "가 있으면 그 지점에서 분리"하는 규칙으로 페어링했다. 이 결과 CSV/MD에는 다음과 같은 증상이 나타났다.
- 행 밀림: 제목에
" - "가 포함된 클래식 음악(Rodrigo : Concierto De Aranjuez - I. Allegro Con Spirito ...)에서 페어링이 어긋나면, 그 지점부터 페이지 끝까지 모든 항목이 한 줄씩 밀렸다. - UI 잡음 혼입: 하단 액션바 텍스트("앨범담기" 등)가 OCR 오인식(예: "엘범담기")되어 EXCLUDE_WORDS 필터를 통과, 곡 데이터처럼 집계됐다.
- 결과: 실제 1,491곡인 플레이리스트가 2,361건으로 부풀려짐.
2. 근본 원인 진단
원본 캡처 이미지(170장, 모두 2472×1557 동일 해상도)를 좌표 단위로 재분석해 다음을 확인했다.
- 행 내부 간격(제목→가수줄): 11~42px
- 행 사이 간격(가수줄→다음 제목): 55~95px
- 두 구간 사이에 완전히 비어 있는 대역(43~54px) 이 존재 — 페이지별 동적 임계값이 아니라 고정 임계값(48px) 으로 행을 구분하는 것이 훨씬 안정적임을 실측으로 확인.
" - "기반 분리는 클래식 음악 제목처럼 구두점이 콘텐츠의 일부인 경우 구조적으로 깨짐 — 애초에 제거하는 것이 맞는 설계였다.
3. 적용한 수정 사항과 효과
| 단계 | 조치 | 파일 | 결과 |
|---|---|---|---|
| 1 | 상/하단 고정 UI(헤더·액션바) 크롭으로 제외, OCR 신뢰도(prob) < 0.1 필터링 | extract_playlist_v2.py |
"엘범담기" 등 UI 잡음 0건 |
| 2 | Y좌표 클러스터링(고정 임계값 48px)으로 제목/가수 행 재페어링, 동일 줄 내 X좌표 정렬 버그 수정 | extract_playlist_v2.py |
행 밀림 완전 해소 (스크린샷과 1:1 대조 검증) |
| 3 | 170장 전체 재추출 | - | 2,361 → 1,757곡 |
| 4 | 스크롤 경계 근접 중복 제거(제목/가수 유사도 + 품질 점수 기반 병합) | dedupe_playlist.py |
1,757 → 1,598곡 (실제 1,491곡에 근접) |
| 5 | "Unknown 아티스트"의 절반가량이 실제로는 제목 줄이 인식 실패하고 가수 줄만 살아남은 역전 케이스임을 발견 → 자체 데이터(이미 확인된 990명 아티스트 목록)와 교차 대조 | 수작업 스크립트 | 72건 중 33건 무료·100% 확실하게 재분류 |
| 6 | 잔여 39건 중 실존 인물/그룹 여부를 웹 검색으로 개별 검증 | WebSearch | 11건 확정 수정 (심규선, Sagisu Shiro, 고영열, 탕웨이, 화사/휘인/김현철 콜라보, 이하이, 울랄라세션, PREP, 임도혁, 가을방학 등) |
| 7 | 사람이 계속 검수할 수 있는 UI 제공 | music_db_service/review |
곡별 맞음/틀림 체크 + 수정 메모, 즉시 DB 반영 |
핵심 교훈: 웹 검색은 "그럴듯한 이름"을 계속 제시하기 때문에, 실제로 확인 안 된 유사 발음 매칭(예: "쇠여관"→송대관)을 진짜 근거처럼 오인하기 쉽다. 완전한 문자열 일치 또는 명확한 출처가 있는 경우만 확정으로 채택하고, 나머지는 미해결로 남기는 원칙을 지켰다.
4. 잔여 문제 분석: 왜 OCR 자체가 한계인가
수정 이후에도 1,598곡 중 25~30건(약 1.5%)은 문자 단위로 복구 불가능한 가비지다(니I 'y니 II{, MwaX, 약단광질 등). 원인은 다음과 같다.
- 작은 글자 크기: 크롭된 열의 텍스트 높이가 20px 안팎으로, EasyOCR의 인식 정확도가 급격히 떨어지는 구간이다.
- 얇은 흰색/회색 폰트 + 어두운 배경: 안티앨리어싱 경계에서 획이 쉽게 끊기거나 뭉개진다.
- CRAFT 텍스트 검출기의 한글+영문 혼용 라인 분리 오류: 한 줄이 두 개의 박스로 쪼개지거나(이번에 병합 로직으로 완화), 반대로 다른 두 줄이 하나로 합쳐지는 경우가 존재.
- 스크롤 캡처 경계에서의 부분 렌더링: 페이지 전환 시 위/아래로 살짝 잘린 행이 저품질로 재캡처되어 원본보다 인식률이 낮다.
즉, 후처리(페어링/중복제거/교차검증)로 해결 가능한 문제는 대부분 해결했고, 남은 문제는 OCR 엔진의 입력 이미지 품질 한계로 후처리만으로는 더 줄이기 어렵다.
4.1 사례 연구: 스크롤 경계 클리핑이 근본 원인이었던 확증 사례
4장 4번 항목("스크롤 캡처 경계에서의 부분 렌더링")을 실제 좌표로 검증했다. /review에 추가한 원본 이미지 링크(6장 참고) 덕분에 가비지 행의 출처 페이지를 바로 열어볼 수 있었고, 그 결과 다음이 확인됐다.
- 근접 중복 제거(3장 4번)에서도 끝내 걸러지지 않았던 두 사례 —
니I 'y니 II{/Kenny G,거붉이처럼/전유준 — 은 둘 다page_002.png에서 나온 항목이었다. page_001.png에는 이미 온전한Stranger On The Shore/Kenny G,거북이처럼/전유준이 존재한다. 즉 위 두 항목은 같은 행이 스크롤 후 다음 캡처에서 다시 잡힌 것이다.page_002.png를 좌표로 재분석한 결과, 두 항목은 크롭 영역 상단 0.7%~9.8% 지점(y=9~124px, 전체 크롭 높이 1261px)에 위치 — 즉 크롭된 열의 맨 첫 줄들이었다. 밀도 높은(10x) 스크롤 캡처 특성상 화면 경계에 걸친 행은 렌더링이 완료되기 전 또는 스크롤 애니메이션 중간에 캡처되어 텍스트가 뭉개진 채로 인식된다.- 이 원리는 앞서 발견된 다른 가비지 사례(
Wiaiosl, y=986/1261=78%)에도 부분적으로 적용되는 것으로 보인다 — 다만 이 경우는 상단이 아니라 하단에 가까운 편이라 정확히 같은 경계는 아니고, 별도로 봐야 할 여지가 있다.
핵심 통찰: 이 문제는 후처리(유사도 기반 근접 중복 제거)로는 원리적으로 못 잡는다. 깨진 텍스트(니I 'y니 II{)는 원본 텍스트(Stranger On The Shore)와 문자 단위로 겹치는 부분이 거의 없어서, 아무리 유사도 임계값을 낮춰도 같은 곡으로 매칭되지 않는다. 애초에 크롭 영역 상/하단 가장자리(예: 상하 5% 이내)에 걸친 행을 OCR 결과에서 제외하는 것이 훨씬 근본적인 해결책이다 — 10x 밀도로 겹쳐 캡처했으므로, 가장자리에서 제외된 행은 다른 페이지에서 경계에 걸리지 않은 상태로 다시 잡힐 가능성이 높다.
5. 향후 OCR 품질 개선 전략
5.0 가장자리 행 제외 (검증 완료, 최우선 — 다음 재추출 라운드에 적용 예정)
extract_playlist_v2.py/v3의group_rows()이후, 각 행 그룹의 y범위가 크롭 영역 상단/하단 경계로부터 일정 마진(예: 5%) 이내에 있으면 해당 행을 통째로 버리도록 수정.- 4.1에서 실측으로 원인과 위치가 확인된 상태이며, 근접 중복 제거보다 구현이 단순하고 근본적이다. 다음 전체 재추출 시 최우선으로 반영한다(현재는 문서화만 하고 재추출은 보류 — 사용자 확인 필요 사항).
5.1 캡처 단계 개선 (가장 효과가 클 것으로 예상)
- KakaoMusic 앱의 글꼴 크기 설정을 확대하거나, Waydroid 디스플레이 DPI/해상도를 높여 재캡처 — 텍스트 높이를 현재 대비 1.5~2배로 늘리는 것을 목표.
- 크롭 영역을 원본 해상도로 유지한 채 OCR 입력 직전에 2배 업스케일(bicubic/Lanczos) + unsharp mask 적용.
5.2 OCR 엔진/전처리 비교 실험
- 현재 실패한 ~150여 행(가비지 + 잔여 Unknown)만 별도로 모아 Tesseract(LSTM), PaddleOCR, Google Cloud Vision API 등과 EasyOCR 결과를 나란히 비교하는 미니 벤치마크를 구성.
- 이진화/대비 강화(CLAHE) 등 전처리 옵션을 조합해 어느 조합이 재현율을 가장 높이는지 정량 비교.
- 전체 170장을 다시 도는 대신, 실패 사례만 골라 재처리하는 것이 비용 대비 효율적 (5.4 참고).
5.3 비전 LLM을 이용한 2차 재판독
- 전통적 OCR 엔진이 실패한 행에 한해, 원본 크롭 이미지를 멀티모달 LLM(Claude 등)에 직접 보여주고 문맥(주변 곡 목록, 앨범아트, 장르 추정)을 함께 판단하게 하는 타겟 재판독을 시도.
- 문자 단위 인식이 아니라 "이게 실존 곡/아티스트로서 그럴듯한가"까지 판단할 수 있어, 순수 OCR보다 가비지 필터링에 유리할 가능성이 높음. 단, 존재하지 않는 답을 "그럴듯하게" 만들어낼 위험이 있으므로 반드시 확신도가 낮으면 미해결로 남기고,
/review에서 사람이 최종 확인하도록 설계해야 함.
5.4 신뢰도 기반 트리아지
- 이미 확보한
prob(OCR 신뢰도) 값을 DB에 함께 저장해두면,/review페이지에서 신뢰도 낮은 순으로 정렬해 검수 우선순위를 정할 수 있음 — 1,598곡을 무작위로 훑는 대신, 문제가 있을 확률이 높은 순서로 효율적으로 검수 가능. - 현재
songs테이블에verified/correction컬럼은 있으나ocr_confidence는 없음 → 재추출 시 함께 저장하도록 확장 필요.
5.5 Human-in-the-loop 피드백 순환 구조
/review에서 확정된 수정 사항(맞음/틀림 + 수정 메모)을 다시 추출 파이프라인의 아티스트 사전(known-artist glossary) 으로 역주입 — 다음 번 비슷한 OCR 오류가 나왔을 때 자동으로 교차 대조할 수 있는 참조 데이터가 계속 축적되는 구조.- 이는 3장 5번 단계(자체 데이터 교차검증으로 33건을 무료로 확정)에서 이미 효과가 증명된 방식으로, 검수를 거듭할수록 자동 정확도가 함께 올라가는 선순환을 만든다.
6. 단계별 실행 로드맵
- (즉시, 검증 완료, 근본적) 가장자리 행 제외 로직(5.0)을 반영해 170장 전체 재추출. 근접 중복 제거보다 원인에 더 가까운 수정이라 우선순위를 최상단으로 둔다.
- (즉시, 비용 낮음)
ocr_confidence컬럼 추가 +/review정렬 옵션에 "신뢰도 낮은 순" 추가. - (단기) 실패 사례 ~150건만 추려 Tesseract/PaddleOCR 비교 벤치마크 실행, 승자 엔진 선정.
- (단기)
/review에서 확정된 수정 사항을 아티스트 사전으로 역주입하는 배치 스크립트 작성. - (중기) 가능하면 KakaoMusic 글꼴/해상도를 키워 재캡처 → 전체 재추출로 원본 데이터 품질 자체를 개선.
- (중기) 잔여 실패 사례에 한해 비전 LLM 2차 판독 파일럿, 정확도와 오탐률을
/review검수로 검증 후 채택 여부 결정.
7. 전수 검수 단계: 사람이 원본과 대조하는 것이 가장 확실한 길
5~6장의 전략들(엔진 교체, 전처리, 비전 LLM 2차 판독)은 모두 확률을 높이는 방법일 뿐, 어떤 자동화도 "원본 스크린샷과 실제로 일치하는가"를 완벽하게 보장하지 못한다. 그래서 자동화 개선과 별개로, /review 페이지를 통해 1,598곡 전체를 사람이 원본 이미지와 대조하며 하나씩 확인하는 작업을 병행하고 있다. 이 절은 그 도구가 어떻게 발전했는지와, 지금까지의 진행 상황을 기록한다.
7.1 검수 도구의 진화
| 반복 | 추가된 기능 | 이유 |
|---|---|---|
| 1 | 곡별 맞음(✓)/틀림(✗) 체크, 클릭 즉시 DB 저장 | 1,598곡을 순회하며 판정을 남길 최소 단위 |
| 2 | 곡명/가수 수정 입력칸을 분리하고, 현재 값으로 미리 채워둠 | 하나의 텍스트 필드에 통으로 적던 것을 나눠서 어느 쪽이 틀렸는지 명확히 하고, 빈 칸부터 타이핑하지 않도록 |
| 3 | "중복" 상태 추가 (✓/✗ 외 3번째 버튼) | 유사도 기반 중복 제거(3장 4번)가 놓친 근접 중복을 사람이 잡아낼 통로 필요 |
| 4 | 원본 캡처 이미지 링크 추가, /capture/<파일명> 라우트로 직접 서빙 |
OCR 텍스트만 보고는 판단이 안 되는 경우 원본 스크린샷을 바로 열어 대조 — 4.1절의 스크롤 경계 클리핑 사례도 이 기능으로 발견됨 |
| 5 | "모름"(Title/Artist가 Unknown) 전용 필터 | 72건의 Unknown 중 아직 못 채운 항목만 몰아서 보기 |
| 6 | "해외 아티스트"(아티스트명이 순수 라틴 알파벳) 전용 필터 | 발음 구별 기호(á, ü 등) 누락은 "그럴듯해 보이지만 틀린" 경우라 별도 검색 없이는 안 걸림 — 검수 시 우선순위를 매길 근거로 활용 |
| 7 | 앨범 필드 추가 | 원본 OCR 크롭 영역엔 없는 정보라, 원본 이미지를 열어 직접 확인하며 채워야 하는 항목 |
| 8 | OCR 원본 보존 원칙: correction_title/correction_artist는 title/artist를 덮어쓰지 않고 별도 컬럼에 저장 |
사람이 고친 값과 OCR이 원래 뭐라고 읽었는지를 둘 다 남겨야 나중에 학습 데이터로 쓸 수 있음 |
| 9 | ocr_correction_log 테이블 + /export/training-pairs |
/review가 생기기 전, 파이프라인 스크립트로 직접 고쳤던 44건은 원본이 덮어써진 상태였는데, 백업 CSV와 현재 DB를 대조해 복원 → 라이브 수정 99건과 합쳐 143건의 (OCR 원본 → 사람이 확정한 정답) 학습 데이터 쌍을 CSV로 내려받을 수 있게 함 |
7.2 진행 상황 (스냅샷)
이 표는 작성 시점 기준이며, 검수가 계속 진행 중이므로 최신 수치는 /review 페이지에서 확인하는 것이 정확하다.
| 지표 | 값 |
|---|---|
| 전체 곡 | 1,598곡 |
| 검토 완료 (맞음+틀림+중복) | 256곡 (맞음 241 · 틀림 8 · 중복 7) |
| 원본 스크린샷 기준 진행률 | 170장 중 약 27장 확인 (약 1/6) |
| 확보된 (OCR→정답) 학습 데이터 쌍 | 143건 (라이브 검수 99 + 이력 복원 44) |
| 한글 vs 영문 오류 비율 (수정 샘플 기준) | 한글 포함 수정 86% vs 영문만 14% — 한글 인식이 유의미하게 더 취약함을 데이터로 확인 |
7.3 이 접근이 "가장 효율적인 방법"인 이유
- 정확도의 상한: 5장의 어떤 자동화 전략(엔진 교체 포함)도 100% 정확도를 보장하지 않는다. 반면 사람이 원본 이미지와 1:1로 대조하는 검수는 그 곡에 한해서는 사실상 정답을 만든다.
- 일회성 투자가 아니라 복리 효과: 검수 한 번의 결과물이 두 가지로 동시에 남는다 — (1) 이 플레이리스트 데이터셋 자체의 신뢰도 상승, (2) 7.1의 9번처럼 향후 OCR 파인튜닝/프롬프트 개선에 쓸 수 있는 라벨링된 학습 데이터. 즉 검수에 들인 시간이 지금 데이터와 미래 자동화 품질에 동시에 투자된다.
- 자동화가 못 잡는 영역을 사람이 메움: 4.1(스크롤 경계 클리핑), 7.1의 6번(발음 구별 기호 누락)처럼, 근접 중복 제거나 신뢰도 임계값 같은 통계적 방법으로는 원리적으로 걸러지지 않는 오류들이 존재한다. 이런 경우 사람의 판단이 유일한 검증 수단이다.
8. 결론
이번 라운드에서 후처리 레벨의 개선(좌표 기반 재페어링, 근접 중복 제거, 로컬/웹 교차검증)만으로 오류를 2,361건 → 1,598건 수준까지 줄였고, 그 과정에서 얻은 교훈은 재사용 가능한 전략으로 정리됐다. 그러나 잔여 ~1.5%는 캡처 이미지 자체의 해상도/폰트 한계에서 오므로, 다음 개선의 핵심은 후처리가 아니라 입력 이미지 품질과 OCR 엔진 선택에 있다. 5장의 로드맵은 비용이 낮은 것부터 순서대로 배치했으며, /review 도구는 이 모든 단계에서 사람이 최종 판단을 내리는 안전장치로 계속 사용된다.
동시에 7장에서 기록했듯, 자동화 전략을 기다리는 동안에도 전수 검수 자체가 가장 확실하고 효율적인 품질 개선 경로라는 점이 실제 데이터로 확인되고 있다 — 검수 한 건이 현재 데이터셋의 신뢰도와 향후 학습 데이터를 동시에 쌓는다. 기록(이 문서, /export/training-pairs)과 그것을 기반으로 한 지속적 개선이 이 프로젝트가 나아갈 방향이다.
