Reddit 댓글 수집은 왜 불완전할까: MoreComments를 빈 데이터로 취급하지 마세요
Reddit 댓글 트리, PRAW replace_more의 limit 의미, 펼쳐지지 않은 플레이스홀더, 댓글 수 불일치를 설명하고, 수집 누락, 답글 관계, 삭제 처리를 분석 결과에 반영하는 방법을 알아봅니다.
Reddit 댓글 수집 중 오류가 없었다고 해서 댓글 트리 전체를 읽었다는 뜻은 아닙니다. PRAW에서 MoreComments는 본문이 빈 댓글이 아니라 아직 펼쳐야 할 위치를 나타냅니다. replace_more(limit=0)은 수집량 제한을 없애는 것이 아니라 이 플레이스홀더를 제거합니다. 이 세부 사항 하나만으로도 깔끔해 보이는 내보내기 결과에서 토론 전체가 빠질 수 있습니다.
r/redditdev의 원래 토론에서 PrincessYukon은 게시물의 댓글을 가져오기 위해 트리 펼치기, 응답 구조, 인증 헤더 오류를 추적했습니다. 이 사례를 참고할 만한 이유는 예전 요청을 그대로 따라 할 수 있어서가 아니라 문제 해결 접근 방식에 있습니다. 먼저 실제로 받은 데이터를 정확히 확인하고, 그다음에 순회 알고리즘을 논의하는 것입니다.
이 글은 2026년 9월 5일 기준 PRAW 작성자가 제공한 문서와 Reddit 공식 규칙을 확인하여, 승인된 데이터 수집에서 완전성을 어떻게 선언해야 하는지 다룹니다. 실제 게시물 수집은 실행하지 않았으며, 과거 포럼 사례를 현재 인터페이스 문제로 설명하지 않습니다.
댓글 트리가 페이지네이션 문제가 아닌 이유
많은 목록 인터페이스는 커서 체인을 따라 페이지별로 순차적으로 읽을 수 있습니다. 하지만 토론 영역에는 같은 수준의 댓글이 더 있을 뿐 아니라 특정 댓글 아래에 더 깊은 답글도 있습니다. 최상위 배열만 순회하면 각 토론의 앞부분만 수집할 수 있고, body가 없는 객체를 건너뛰면 프로그램은 펼쳐지지 않은 부분이 있다는 경고조차 하지 않습니다.
PRAW 댓글 추출 튜토리얼은 MoreComments를 페이지의 “load more comments” 및 “continue this thread”에 대응시킵니다. 한 번 펼치면 새로운 대기 위치가 또 나타날 수도 있습니다. 따라서 노드 수와 요청 수는 서로 바로 환산할 수 없습니다. 플레이스홀더 10개를 처리했다고 해서 댓글을 10개만 얻는 것도 아니고, 완전한 스레드 10개를 다룬다는 뜻도 아닙니다.
파서를 작성할 때는 먼저 본문 노드와 펼치기 대기 노드를 구분해야 합니다. 로드되지 않은 하위 트리는 “아직 관측되지 않음”이지 “아무도 답글을 달지 않음”이 아닙니다. 이 구분은 분석 계층에서 특히 중요합니다. 펼쳐지지 않은 항목이 깊은 논쟁이라면 최상위 의견의 분포가 토론 전체를 대표하지 못할 수 있습니다.
replace_more limit이 실제로 제한하는 것
현재 PRAW 튜토리얼에 따르면 기본 호출은 MoreComments 인스턴스를 최대 32개까지 교체합니다. limit=0은 더 펼치지 않고 플레이스홀더를 제거하며, limit=None은 교체 횟수에 상한을 두지 않지만 다른 조건은 여전히 적용됩니다. 이 셋은 비슷한 성능 옵션 세 가지가 아니라 서로 다른 샘플링 결과 세 가지입니다.
예를 들어 빠른 미리보기에서는 펼치지 않기를 명시적으로 선택하고 이미 로드된 콘텐츠만 보여 줄 수 있습니다. 이는 합리적인 제품 기능입니다. 다만 버튼 이름은 “전체 댓글 내보내기”가 아니라 “로드된 댓글 미리보기”여야 합니다. 더 넓은 범위가 필요하면 상한이 있는 펼치기 예산을 설정하고, 예산에 도달하면 부분 결과를 전달하면서 그 결정을 기록합니다.
None 역시 프로덕션 시스템에서 무제한으로 작업해도 된다는 허가가 아닙니다. 작업에는 여전히 자체 최대 실행 시간, 오류 시 중단 조건, 승인된 요청 범위가 필요합니다. 인터페이스가 반환하지 않거나 접근할 수 없는 콘텐츠는 SDK의 수량 제한을 없앤다고 해서 저절로 나타나지 않습니다.
threshold도 명시적으로 기록해야 합니다. CommentForest 메서드 설명에 따르면 이 값은 어떤 플레이스홀더를 펼칠지에 영향을 줍니다. “전체 수집” 파라미터 하나만 기억하고 다른 필터 조건을 무시하면 여전히 너무 일찍 완료를 선언할 수 있습니다.
최종 배열에만 의존하지 말고 펼쳐지지 않은 항목을 저장하기
replace_more는 교체되지 않은 MoreComments 인스턴스 목록을 반환합니다. 플레이스홀더가 현재 트리에서 제거되면 최종 배열에는 더 이상 나타나지 않을 수 있습니다. 따라서 “최종 목록에 MoreComments가 없다”는 사실만으로는 누락이 전혀 없다는 것을 증명할 수 없습니다. 메서드가 반환한 미교체 항목을 작업 결과에 포함해야 합니다.
여기서 피해야 할 정밀도 함정이 하나 더 있습니다. 펼쳐지지 않은 플레이스홀더가 5개라고 해서 댓글 5개가 빠졌다는 뜻은 아닙니다. 플레이스홀더 하나가 하위 트리 전체를 나타낼 수 있고, 더 펼치면 플레이스홀더가 더 나올 수도 있습니다. 외부에는 “펼쳐지지 않은 위치 5개가 남아 있음”이라고 밝힐 수 있지만, 완료율을 함부로 계산해서는 안 됩니다.
작업은 최소한 로드된 고유 댓글, 완료되지 않은 범위, 중단 사유라는 세 가지 정보를 출력하도록 권장합니다. 중단 사유에는 미리보기를 직접 선택한 경우, 펼치기 예산 소진, 요청 속도 제한, 인증 실패, 파싱 예외 등이 있습니다. 필드 이름은 애플리케이션이 정하면 됩니다. 핵심은 다운스트림 시스템이 “결과 없음”과 “실행 미완료”를 구분할 수 있어야 한다는 점입니다.
서드파티 래퍼 인터페이스를 사용한다면 그 “댓글 수”가 최상위 댓글 수인지, 로드된 모든 계층의 댓글 수인지, 작업에서 일부를 잘라 낸 뒤의 결과 수인지도 확인해야 합니다. 파라미터 이름이 똑같이 limit이라고 해서 의미도 같은 것은 아닙니다. PRAW 파라미터 해석을 EveryInfra나 다른 인터페이스에 적용하지 마십시오.
평탄화한 뒤에도 답글 대상 추적하기
CommentForest의 list()는 로드된 콘텐츠를 순회 순서대로 펼칠 수 있지만, 평탄화한다고 데이터가 추가로 채워지지는 않습니다. 1차원 배열을 얻은 뒤에도 댓글 ID, 게시물과의 연결, 부모 관계를 버려서는 안 됩니다.
최상위 댓글이 “새 릴리스에서 문제가 해결됐다”고 말하고, 그 아래에 “데스크톱만 그렇고 모바일은 아직이다”라는 답글이 달렸다고 가정해 보십시오. 내보내기 결과에 두 번째 문장만 남아 있으면 모델은 이를 새로운 독립 불만으로 취급할 수 있습니다. 부모 댓글마저 없다면 모델이 앞의 내용을 추측하게 두지 말고 맥락 누락을 표시해야 합니다.
중복 제거도 식별자를 중심으로 해야 합니다. 재시도 후 같은 댓글이 다시 나타나면 다른 사용자의 의견으로 만들지 말고 현재 관측값을 업데이트합니다. 텍스트가 같더라도 문자열이 같다는 이유만으로 서로 다른 댓글을 병합할 수는 없습니다. 콘텐츠 수정, 작성자 정보 누락, 보이지 않는 부모 노드는 모두 빈 문자열로 바꾸지 말고 각각 별도의 상태로 유지하십시오.
이러한 레코드는 적용되는 데이터 사용 및 보존 범위 안에서만 유지합니다. 관계 정보를 보존하라는 제안이 모든 원문을 영구적으로 저장해도 된다는 허가는 아닙니다.
댓글 수, 권한, 삭제도 분석 범위에 포함됩니다
PRAW 튜토리얼에 따르면 게시물의 num_comments 수에는 삭제되거나 제거되었거나 스팸으로 처리된 댓글이 포함될 수 있으므로, 실제로 추출할 수 있는 수와 일치한다고 보장할 수 없습니다. 이 수는 검증 단서로 쓸 수 있지만, 재시도를 거듭해서 반드시 맞춰야 하는 목표로 삼아서는 안 됩니다.
수집 권한은 별도로 확인해야 합니다. Reddit의 Data API Wiki는 적절한 OAuth 자격 증명과 명확한 User-Agent를 요구하며, 요청 속도 제한 응답 헤더와 접근 규칙을 안내합니다. PRAW를 설치할 수 있다고 해서 임의의 프로젝트에 데이터를 사용할 권한이 생기는 것은 아니며, 과거 게시물에 나온 코드가 동작한다고 해도 현재의 연동 조건을 대신할 수는 없습니다.
같은 공식 페이지는 플랫폼에서 이미 삭제된 콘텐츠를 처리하도록 요구합니다. 분석 시스템에서는 삭제가 원본 테이블에서 끝나서는 안 된다는 뜻입니다. 텍스트가 검색 인덱스, 캐시, 기타 파생 저장소에 들어갔다면 그곳에 적용되는 정리 요구 사항도 확인해야 합니다. 공식적으로 삭제가 요청된 콘텐츠를 “익명화”를 핑계로 보존해서는 안 됩니다.
이는 재현성 설계에도 영향을 줍니다. 관측한 모든 원문을 영구 보존하겠다고 약속하기보다 허용된 방법과 작업 범위를 보존하는 것이 더 안전한 목표입니다. 연구 결론에는 수집 날짜와 표본 범위를 명시해야 하며, 현재 이용할 수 없는 과거 텍스트를 언제든 다시 검증할 수 있는 증거로 취급해서는 안 됩니다.
Reddit 댓글 내보내기 결과를 검증하는 방법
먼저 합성 트리에서 세 가지 반례를 확인합니다. 펼쳐지지 않은 하위 트리가 있는 최상위 노드, 텍스트가 똑같은 서로 다른 댓글 2개, 결과에 여러 번 들어간 같은 댓글입니다. 올바른 구현이라면 각각 미완료 상태를 보존하고, 두 식별자를 따로 유지하고, 중복된 식별자를 병합해야 합니다. “프로그램 예외 없음”만으로 성공을 판단해서는 안 됩니다.
다음으로 범위가 제한된 작업의 중단 결과를 살펴봅니다. 펼치기 예산에 도달하면 부분 완료로, 자격 증명이 유효하지 않으면 인증 실패로, 예상치 못한 응답 구조는 파싱 실패로 표시되어야 합니다. 세 경우 모두 빈 목록을 반환해서는 안 됩니다. 일반적인 오류 분류는 이 사이트의 API 오류 처리를 참고할 수 있지만, 플랫폼 응답의 세부 사항은 현재 인터페이스를 기준으로 합니다.
마지막으로 보고서 문구를 확인합니다. 결과가 어떤 게시물에서 나왔는지, 그 게시물을 왜 선택했는지, 어디까지 펼쳤는지, 미완료 항목이 남아 있는지입니다. 인기 게시물 몇 개만 수집했다면 “Reddit 사용자들은 대체로 이렇게 생각한다”는 결론을 내릴 수 없습니다. 이 사이트의 멀티 플랫폼 여론 모니터링 블루프린트도 마찬가지로 수집 범위와 비즈니스 판단을 분리합니다. EveryInfra의 Reddit 댓글 API로 내보낼 때도 같은 항목으로 범위를 명시하십시오.
신뢰할 수 있는 Reddit 댓글 데이터라고 해서 누락이 없는 척할 필요는 없습니다. 필요한 것은 누락을 드러내고, 부모-자식 관계를 추적할 수 있게 유지하고, 삭제 요청과 함께 사용 범위를 지키는 것입니다. 그래야 이후 분석에서 어떤 판단에 근거가 있는지, 어떤 부분을 여전히 미지의 영역으로 남겨 두어야 하는지 알 수 있습니다.
참고 BL-05