실제 ZIP 포렌식

Instagram 데이터 ZIP 구조: followers와 following을 실제 파일로 해부하기

613MB Instagram 내보내기 ZIP과 테스트 파일을 직접 파싱해 관계 JSON의 경로, 래퍼 차이, 식별자, timestamp 관측기간과 정확도 한계를 설명합니다.

CheckMate 운영자 · 최초 발행 · 사실 검토 · 약 14

Instagram ZIP은 “팔로워 목록 두 개를 빼면 끝”인 단순한 파일이 아닙니다. 같은 관계 정보도 내보내기 버전과 언어에 따라 최상위 배열, relationships_followers 래퍼, relationships_following 래퍼, label_values 형식으로 달라질 수 있습니다. 파일 이름 하나와 특정 키 하나만 가정하면 일부 계정에서 0명으로 나오거나 첫 파일만 읽는 문제가 생깁니다.

CheckMate 운영자가 제공받은 613MB 실제 ZIP을 로컬에서 분석했을 때 followers 기록의 timestamp 범위는 2,794일, following은 2,783일이었습니다. 따라서 “followers는 언제나 약 365일만 제공된다”는 보편 규칙은 이 파일과 맞지 않습니다. 현재 버전은 각 목록의 최소·최대 timestamp 차이를 관측값으로 표시하고, 기간 차이만으로 누락을 단정하지 않습니다.

이 글은 파일 안에 실제로 있는 값과 그 값으로 알 수 없는 것을 분리합니다. username·프로필 URL·timestamp·일부 신형 파일의 fbid는 관찰할 수 있지만, 모든 내보내기에 영구 고유 ID가 있다고 가정할 수는 없습니다. 그래서 현재 비맞팔 계산, 닉네임 변경 가능성, 실제 과거 언팔 사건은 서로 다른 신뢰도로 다뤄야 합니다.

Instagram ZIP을 브라우저에서 로컬 분석하는 CheckMate 업로드 화면
파일 경로와 스키마는 브라우저에서 읽으며 원본 ZIP은 서버로 전송하지 않는다.

1. 관계 파일은 어디에 있고 왜 이름이 달라지는가

한국어 내보내기에서는 connections/followers_and_following 또는 이에 대응하는 번역 경로 아래에서 관계 파일을 자주 찾습니다. 그러나 Meta가 폴더명을 바꾸거나 전체 정보 선택 여부에 따라 더 깊은 경로에 둘 수 있어, CheckMate는 ZIP 엔트리의 끝 경로와 알려진 후보를 함께 검사합니다. followers_1.json만 찾고 종료하지 않고 번호가 붙은 모든 followers 파일을 합칩니다.

관계 파일 두 개는 모양도 다를 수 있습니다. followers 파일은 배열이 바로 시작하는 구형 사례가 있고, following 파일은 relationships_following이라는 객체 키 아래 배열이 들어가는 사례가 있습니다. 신형 export 일부는 label_values와 fbid를 사용합니다. “둘 다 같은 타입으로 캐스팅”하는 코드는 한쪽을 놓치기 쉽습니다.

대상관찰한 대표 형태파서가 해야 할 일
followers_N.json최상위 배열 또는 relationships_followers번호 파일을 모두 모으고 래퍼를 해제
following.jsonrelationships_following 객체래퍼 안의 배열을 읽기
신형 관계 항목label_values + 선택적 fbid표시 이름과 username을 분리하고 fbid가 있을 때 우선
알 수 없는 래퍼첫 비어 있지 않은 배열모르는 필드는 무시하되 섹션 오류를 기록
connections/
└── followers_and_following/
    ├── followers_1.json
    ├── followers_2.json   # 계정에 따라 존재
    └── following.json

2. 한 사람 항목에서 실제로 읽는 필드

구형 string_list_data 항목에는 title, value, href, timestamp가 함께 있거나 일부만 있습니다. title과 value가 과거 이름이고 href에서 뽑은 username이 현재 이름처럼 보이는 사례도 있지만, 그 사실만으로 닉네임 변경을 확정할 수는 없습니다. 데이터 생성 시점과 필드 갱신 방식이 공개 계약으로 보장되지 않기 때문입니다.

신형 일부 항목의 fbid는 숫자 문자열 형태의 계정 식별자로 관찰됐습니다. 두 목록 모두 같은 fbid를 제공하면 username이 달라도 관계를 연결하는 가장 강한 키로 사용할 수 있습니다. 다만 구형 파일에는 없으므로 전체 서비스 설명을 “고유 ID로 100% 추적”이라고 바꾸면 안 됩니다. displayName은 동명이인이 가능해 관계 매칭 키로 사용하지 않습니다.

필드쓸 수 있는 범위주의할 점
fbid양쪽 파일에 있을 때 우선 관계 매칭모든 export에 존재하지 않음
href username프로필 경로에서 표시 username 추출경로가 영구 ID라는 보장은 없음
title / value구형 형식의 보조 username 후보서로 달라도 닉변 확정은 아님
timestamp목록 내부 관측기간과 일부 이벤트 시점계정 생성일이나 완전한 이력 기간이 아님
displayName화면 표시동명이인 때문에 매칭 키로 사용 금지
{
  "title": "sample_old_name",
  "string_list_data": [{
    "href": "https://www.instagram.com/_u/sample_name",
    "value": "sample_name",
    "timestamp": 1700000000
  }]
}

3. 2,794일은 “전체 데이터 보장”도 “365일 제한”도 아니다

관측기간은 유효한 timestamp 중 가장 늦은 값에서 가장 이른 값을 빼 86,400초로 나눈 정수 일수입니다. 실제 ZIP에서 followers 2,794일, following 2,783일이 나왔다는 것은 그 사이의 기록이 파일에 존재한다는 뜻입니다. 모든 날짜가 빠짐없이 포함됐거나 그 기간의 모든 과거 팔로워가 들어 있다는 뜻은 아닙니다.

이전 버전은 following이 400일 이상이고 followers가 400일 미만이면 잘린 것으로 보는 휴리스틱과, followers 수가 following의 30%보다 작으면 의심하는 비율 규칙을 사용했습니다. 실제 관계 비율은 계정 성격마다 다르고, 제공 ZIP은 365일 가정을 반박했습니다. Recovery Release에서는 두 규칙을 제거했습니다.

현재 partial 판정은 별도 audience insight에서 실제 팔로워 수를 읽을 수 있을 때만 사용합니다. 파일의 followers 항목 수가 그 실제 수보다 10% 이상 적을 때 재다운로드 안내를 보여줍니다. 정확히 10%인 경계도 테스트합니다. 실제 수가 없으면 span이나 팔로잉 비율만으로 “전체 기간이 아니다”라고 단정하지 않습니다.

화면 값계산 방법말할 수 있는 것말할 수 없는 것
followers 2,794일followers timestamp 최대-최소파일 안 관측 시각 범위그 기간 전체 팔로워가 완전함
following 2,783일following timestamp 최대-최소파일 안 관측 시각 범위팔로잉 전체 이력 보장
누락 N명실제 팔로워 수-파일 항목 수10% 이상 차이의 정량 경고누가 누락됐는지 확정

4. 맞팔·현재 비맞팔 계산은 집합 비교지만 식별자가 핵심이다

기본 관계는 following에 있고 followers에는 없는 계정을 “현재 나를 팔로우하지 않는 계정”으로 분류합니다. 반대로 followers에만 있으면 “내 팬”, 양쪽에 있으면 맞팔입니다. 이 계산은 내보내기 생성 시점의 스냅샷을 비교하므로 “어제 누가 나를 언팔했다”는 사건 이력을 알려주지 않습니다. 실제 변화는 서로 다른 두 스냅샷을 비교해야 합니다.

동일성 매칭은 fbid가 있으면 fbid를 우선하고, 없으면 href에서 추출한 username·title·value 후보를 소문자로 정규화해 비교합니다. 한 항목 내부의 식별자가 어긋나면 결과 배지에 “닉네임 변경 가능성”이라고 표시할 수 있지만, 비활성화·탈퇴·재가입까지 구분하지는 못합니다.

5. 파서에서 반드시 처리해야 할 엣지 케이스

JSON 파서는 정상 파일만 처리하는 것보다 실패를 섹션 단위로 격리하는 것이 중요합니다. 광고 정보 형식이 바뀌어도 관계 결과가 사라지면 안 되고, unknown 필드 하나 때문에 ZIP 전체를 실패시켜서도 안 됩니다. CheckMate는 각 인사이트 파싱 오류를 기록하고 나머지 결과를 계속 표시합니다.

한글 label이 잘못된 latin1처럼 보이는 이중 인코딩 사례도 있습니다. 유효한 UTF-8 바이트열일 때만 재해석하고, 이미 정상 유니코드이거나 디코딩에 실패하면 원문을 유지합니다. timestamp는 초·밀리초·마이크로초가 섞일 수 있어 크기에 따라 초 단위로 정규화합니다.

확인한 출처와 검증 방법

자주 묻는 질문

followers가 following보다 기간이 짧으면 파일이 잘린 건가요?

그 차이만으로는 알 수 없습니다. 두 목록은 서로 다른 이벤트 집합이며 timestamp의 최소·최대도 다를 수 있습니다. 별도 실제 팔로워 수와 10% 이상 차이가 확인될 때만 누락 경고를 표시합니다.

profile URL의 /_u/username은 영구 고유 ID인가요?

아닙니다. 현재 파서는 경로에서 username을 추출하는 호환 형식으로만 사용합니다. 영구 불변 식별자라고 가정하지 않으며, fbid가 양쪽에 있을 때 그 값을 우선합니다.

한 번의 ZIP으로 누가 최근 언팔했는지 알 수 있나요?

알 수 없습니다. 한 ZIP은 생성 시점의 현재 관계를 보여줍니다. 실제 변화는 날짜가 다른 두 스냅샷을 같은 규칙으로 비교해야 합니다.

followers_2.json도 꼭 필요한가요?

있다면 반드시 함께 읽어야 합니다. 첫 파일만 사용하면 팔로워 수와 관계 계산이 실제 파일보다 작아집니다.

이어 읽기

전체 기간 JSON 다운로드분할 관계 파일이 포함된 올바른 ZIP을 다시 요청합니다.닉네임 변경 추적의 신뢰도fbid와 username 후보가 각각 어디까지 증거가 되는지 봅니다.두 시점 스냅샷 비교한 번의 현재 상태가 아닌 실제 관계 변화 후보를 계산합니다.결과가 다르게 보일 때시점 차이, 분할 파일, HTML 형식 문제를 빠르게 진단합니다.