DiffX – 차세대 확장 가능한 Diff 포맷
(diffx.org)- 기존 Unified Diff 포맷은 개발 환경의 요구사항을 충분히 반영하지 못하는 한계점 존재
- DiffX는 기존 형식과 완벽하게 호환되며, 미래를 고려한 구조와 메타데이터 확장성 제공
- 여러 커밋 정보와 바이너리 파일, 문자 인코딩 및 메타데이터를 구조화된 방식으로 저장 가능함
- 표준화된 파싱 규칙 도입으로 다양한 도구(패치, 코드 리뷰 등)가 쉽게 연동 가능함
- 기존 도구 및 워크플로우에서는 문제없이 사용 가능하며, 새로운 기능만 해당 도구의 지원 필요
개발자와 Diff 파일
- 소프트웨어 개발자들은 보통 Git, Subversion, CVS 등에서 diff 파일로 코드 변경 내역을 확인함
- Diff 파일은 텍스트 삽입(
+
)·삭제(-
) 와 파일 이름, 경로, 타임스탬프, 일부 메타데이터 등을 포함하는 구조임 - 대부분의 도구와 사용자는 Unified Diff 형식을 이용하며, 이 방식은 비교적 간단하게 차이점을 시각화함
Unified Diff의 한계
- Unified Diff는 파일 식별, 변경 범위, 삽입·삭제된 줄만을 표준화할 뿐, 인코딩, 리비전, 확장 메타데이터 등은 표준화하지 않음
- 다양한 소스 관리 시스템 지원, 신뢰성 있는 파싱, 풍부한 정보 추출이 어려움
- 다음과 같은 문제점이 계속 발생함
- 여러 개의 커밋을 한 번에 표현 불가함
- 바이너리 파일에 대한 전용 표준 형식 부족
- 문자 인코딩을 알 수 없어 정보 손실, 혼동 발생
- 임의 메타데이터의 표준화 미비로 각 도구별로 형태가 상이함
개선 방향
- 기존 Unified Diff는 구조와 표준이 부족하지만, 유연하고 다양한 환경에 이미 널리 퍼져 있음
- Git Diff가 사실상 표준 역할을 하는 중이지만, 여전히 포맷의 공식 명세와 범용 확장성은 부족함
- 기존 Unified Diff의 장점을 살리면서, 확장성과 표준 구조를 가미한 새로운 형식 필요성이 증대됨
DiffX란 무엇인가
- DiffX는 확장 가능한 Diff 포맷으로, 기존 도구와 완벽히 호환되며, 인적 가독성을 유지함과 동시에 메타데이터와 구성을 구조적으로 담을 수 있음
- 구문 예시:
- 파일, 커밋, 전체 diff 등에 대해 메타데이터와 본문을 구조적, 확장 방식을 활용해 저장함
- 예시 출력에서는
#diffx:
와 같은 구문과, section, 메타데이터(JSON), 파일 경로, 커밋 정보 등이 포함됨
DiffX의 주요 특장점
- 표준화된 파싱 규칙 제공, 도구에서 신뢰성 있게 정보를 읽고 쓸 수 있음
- 메타데이터 저장·관리의 공식화: 전체 diff, 커밋, 파일 단위별로 사용 가능함
- 기존 파서, 패처, 코드 리뷰 등 모든 도구와 호환됨 (새 기능은 지원 필요하나, 기존 기능은 호환성 보장)
- 한 파일에서 여러 커밋, 바이너리 diff, 텍스트 인코딩 정보 등 복수의 내용을 효율적 구조로 표현 가능함
- 도구에서 diff를 열어 필요한 정보를 기록 및 수정 후 다시 저장하는 변경성(mutability) 지원
DiffX의 지향점 및 비지향점
- 모든 도구의 포맷 지원을 강요하거나, 호환성 문제를 만들지 않음
- 벤더 종속성을 유발하지 않으며, 기존 워크플로우를 깨지 않음
- 기존 Diff 파일의 문제점을 해소하고, 개발·리뷰·분석 도구에서 일관되고 신뢰성 있는 사용 경험을 제공함
Hacker News 의견
-
나는 “..meta”와 “…meta” 등 계층적으로 복잡한 포맷이 마음에 들지 않음 표현의 명확성을 위해서는 diff 전체, 파일, 청크 등 세 단계로만 구분해서 각기 다른 이름을 부여하는 것이 더 알아보기 쉬운 포맷이 된다고 생각함 메타블록이 없어도 한눈에 대상을 구분 가능해서 실수나 오류도 줄일 수 있음 diff 전체의 메타데이터와 파일 단위의 메타데이터가 같은 필드로 구성되는 것도 비합리적임 그리고 왜 JSON과 key=value 두 가지 포맷이 필요한지 모르겠음, 관리할 대상이 적다면 하나의 포맷만 쓰는 게 구현이나 기존 툴과의 통합에 훨씬 이로움 (grep, sed 또는 jq 중 하나만 쓰면 충분함) 추가로 리스트에 trailing comma 허용이 있으면 좋겠고, diff는 원래 분할 적용이 가능한 구조인데 이 포맷이 그 점에 어떤 영향을 주는지 궁금함(예를 들어 diff의 일부만 적용하려면 프리앰블을 복사하고 블록도 따로 복사해야 해서 번거롭다고 생각함) revision은 파일 속성인지 아니면 커밋 체크섬인지 궁금증이 듬
- 우리는 구조에 대해 여러 접근을 실험해보다가 결국 파싱 관점에서 단순함을 위해
#<section_level><section_type>
형태로 정리함 메타블록마다 수직적으로 수준만 체크하면 되고, 점 개수를 세면 자연스럽게 어느 레벨의 메타인지 구분 가능 키/값 헤더 포맷은 파서가 미리 아는 간단한 속성만 담으려고 했고, 자유로운 메타데이터는 별도의 meta 블록에 담도록 설계 기존 JSON 뿐 아니라, 시간이 지나 다른 시리얼라이즈 방식이 필요할 때도 확장성을 갖도록 헤더에 포맷을 명기할 수 있음 단순함과 유연성 사이에서 균형을 잡으려고 노력한 결과임 trailing comma는 개인적으로 넣고 싶지만, base-level JSON의 호환성 문제 때문에 JSON5 파서를 필수로 요구하긴 어려움 diff는 여전히 분할 가능하고, Unified Diff가 무시하는 영역에 정보를 넣은 덕분에 GNU patch 등에서는 무시되어 문제 없음 다만 두 개의 DiffX 파일로 분할한다면 헤더를 새로 추가해야 하므로 조금 복잡해질 수 있음 어떤 SCM의 diff는 분할해도 일부 메타데이터(예: parent commit 정보)를 잃거나, 적용 대상에 따라 정보 손실이 생길 수 있음 revision은 SCM마다 다르며 커밋 ID, 파일별 ID 또는 그 조합, 추가 정보 등 매우 다양한 필요가 존재 SCM마다 다양한 요구를 충족하려 고려한 구조임
- 우리는 구조에 대해 여러 접근을 실험해보다가 결국 파싱 관점에서 단순함을 위해
-
내가 보기엔 아래 네 가지 지적 중, 실제로 diff 파일의 일반화로 합리적인 건 바이너리 패치 표기법 하나뿐임 나머지는 특정 버전 관리 시스템(SCM) 내부의 데이터나 프로토콜 문제라서 각자의 클라이언트, 서버, 백업 시스템에서만 통용되는 내용임 다른 모두는 불필요해 보임
-
하나의 diff로 여러 커밋 나열 불가
-
바이너리 패치에 대한 표준 없음
-
텍스트 인코딩 인식 불가(은근히 문제됨)
-
임의의 메타데이터 표준 포맷 부재
-
우리는 20년간 12개 이상의 SCM을 연동하는 코드 리뷰 제품을 개발해왔고, 상상지도 못한 diff 포맷 및 SCM별 문제들을 수도 없이 겪음 실제로 end user가 직접 신경 쓸 문제는 아니지만, 툴 개발 측에서는 반드시 해결해야 할 pain point들이었음 일부 SCM에는 자체 diff 포맷이 없거나, 빠진 정보가 많아(예: 삭제 파일 표시 불가) 다른 툴들이 파일을 제대로 식별하지 못하게 만드는 경우가 많음, 그래서 이런 개선이 필요하다고 느낌
-
요즘은 덜 흔하지만 나 역시 patch(1)와 비슷한 도구를 여전히 종종 씀 여러 플랫폼의 개발자가 협업할 때 파일명 대소문자, 문자 인코딩 이슈 등 때문에 다양한 문제가 여전히 생김
-
-
JSON을 길이 정보와 함께 self-delimitered 포맷으로 넣는 방식이라면, JSON 내용의 공백 한 칸만 바꿔도 JSON은 유효하지만 DiffX는 전체적으로 깨질 위험이 있음 구조적으로 클unky하고 messy하게 느껴지는 조합임(자체 헤더와 JSON payload 섞인 점, 점 개수를 안 세면 다른 meta 블록을 구분 못하는 점, 두 가지 파서가 필요한 구조 등) 메타데이터용 확장형 diff를 표준화하려는 발상은 좋으나, 이번 구현은 시행착오처럼 보임
-
patch 포맷이 이런 문제를 다 해결하고 있다고 생각함 git format-patch 설명 링크
-
오늘 처음 이런 포맷이 있다는 걸 알게 됐고, 참고함(나는 그냥 평범한 인터넷 이용자임, 저자는 아님)
-
git에서는 해결 가능하지만, Review Board 같은 제품이라면 SVN, CVS, Perforce 등 여러 VCS와 통합해야 해서 이런 포맷이 등장한 배경으로 보임 나도 Review Board와 SVN을 쓴 적이 있는데, 여러 개발자가 git-svn과 svn을 혼합해서 리뷰 시 diff 업로드에 종종 문제가 있었음 양쪽 모두 지원하는 표준 diff 포맷이 있었다면 툴 사용에 훨씬 도움이 됐을 것임
-
-
나는 실제로 제시된 문제들이 존재한다고 잘 못 느끼겠음(바이너리 파일 제외)
-
인코딩이 달라도 patch 알고리즘은 동일하니 신경 쓸 필요 없음(문자가 꼭 유효한 utf-8일 필요도 없음)
-
하나의 diff에 여러 커밋을 담고 싶을 일도 없음, 여러 diff로 나누는 게 직관적임
-
메타데이터는 시스템 내부에만 유효한 게 아닌가 생각함
-
인코딩 관련해서도 patch data는 어차피 ascii 기반 binary 데이터처럼 다뤄야 함 mixed encoding에 대해서 파일 수정을 할 수도 있으니 인코딩 고정의 의미가 별로 없음
-
전혀 문제가 아니라고 봄, diff를 실제로 많이 쓰는 사용자들의 실제 경험을 들어보는 게 낫다고 생각함, 기존에 잘 동작하는 포맷을 굳이 overengineering하지 않는 게 좋겠음
-
바이너리 데이터 문제는 확실히 존재함이라고 생각함
-
보통 직접 도구를 만들거나 특정 SCM과 인터페이스해야 할 때만 실제로 이런 문제들을 마주침
- 인코딩 문제는 파일명과 본문 양쪽에 존재함, Git은 파일명 인코딩을 신경쓰지만 대부분 SCM은 그렇지 않아서 한 환경에서 자동 생성한 diff가 다른 환경에선 파일명을 찾지 못하는 경우가 있음(Perforce, Subversion 등에서 봄), 본문 역시 SCM마다 지역 인코딩에 따라 diff가 깨질 수 있음, 윈도우-리눅스 환경 오갈 때 개행 문자가 뒤섞여서 patch 적용이 안 되거나 BOM 문제 때문에 GNU patch가 깨진 적도 있음
- 여러 커밋을 한 번에 다루거나 툴로 넘길 때, 파일 누락이나 일관성 문제 등 다양한 문제가 발생 가능하고, diff 간을 일일이 sanity check하기 번거로움, 도구마다 지원하는 포맷도 다르니 불편함
- 저장소에서 파일을 찾으려면 시스템마다 커밋 단위, 파일 단위, 조합, 관계 정보 등 각종 식별자가 필요함, 심볼릭 링크나 파일 모드, SCM 특성 정보처럼 Unified diff에 안 들어가는 데이터도 필수임
-
-
전체 문서는 읽기 어렵게 느껴짐 내게 ‘diff’란 두 항목(파일, 디렉터리 등)의 차이를 뜻하지만 TFA에서 말하는 diff는 내가 아는 ‘patch’임 여기서 논의되는 건 diff가 아니라 patch 메타데이터 관리에 관한 내용임 메타데이터를 JSON처럼 필수 형식으로 표준화한다면 괜찮겠지만, 애매하게 self-describing length-delimited 구조라 문제를 숨기는 느낌임 표준화 자체는 좋은데, 좀 더 명료하게 정리된 솔루션이 필요하다고 느낌 내가 보기엔 git diff 스타일이 사실상 표준에 더 가깝다고 생각이 드는 것도 재밌음
- 마지막 구절에 완전히 동의함, diff를 여러 개로 나누어 쓰면 됨
-
이런 포맷이 어떤 문제를 해결하려는지 궁금함 패치/디프 포맷이 충분히 좋지 않다는데, 누구를 위한 개선인지, GNU Patch 커뮤니티에서 불만이 늘어나서 그런 것인지, 뭐가 이유인지 더 구체적이어야 함 실제로 더 나은 패치 포맷이 꼭 필요한 이유가 뭔지 궁금증이 남음
-
내가 너무 길어서 여기에 못 쓰는 글을 따로 정리한 것이 있는데 요약하자면 SCM을 직접 만들거나 SCM과 연동하는 도구 개발자들을 위한 고민임 일반 사용자라면 신경쓸 필요 없음 diff 포맷도 SCM마다 전부 달라서, 정말 잘 만든 것이 있기도 하고 심각하게 부족하거나 포맷이 아예 없는 것도 있음 여러 SCM을 커버해야 하는 Review Board 같은 제품 입장에서는 이런 통합 표준이 실무적으로 꼭 필요함 실제로 SCM 벤더들과 협업한 피드백을 반영한 개선 시도임
-
Review Board 위주로 쓰이는 포맷으로 보이는데, 이 제품은 다양한 VCS를 지원하고 소스 리뷰에서 diff가 핵심이므로 도입한 듯함
-
-
가장 일반적이고 명확한 diff 표현법은 파일 두 개를 그냥 포함하는 방식임 지금은 데이터 용량이 문제되지 않으니
diff a b | patch c
대신apply a b c
처럼 만들면 내부 표현은 어떤 것이든 상관없음 diff는 인간이 읽기 어렵고, 컬러 사이드-바이-사이드 뷰가 훨씬 낫기 때문에 애초에 두 파일을 다 받아서 처리하는 게 직관적임 굳이 표준화되지 않은 diff를 전송할 필요가 없다 생각함-
파일 두 개로 만드는 diff는 하나뿐이 아니고, 다양한 목적에 맞는 여러 가지 버전의 diff가 나올 수 있음 diff 포맷이 있으면 diff 생성과 적용 로직을 분리해서 n*m 문제를 n+m 문제로 줄일 수 있음
-
프로그램 업데이트 등에서 매번 130GB 전체를 새로 받게 되는 건 짜증 나지만 거의 동일한 파일끼리는 압축도 쉬워서, 두 버전 파일 차이만 전달하는 방식도 실익이 크다고 생각함 오리지널 파일의 해시값만 보내고 압축 파일 본체를 전송하는 등 더 효율적인 방법도 가능성 있어 보임
-
파일 두 쌍의 전송 및 관리는 전용 컨테이너 없이는 어렵고, 여러 개의 변경(10개 파일 수정+삭제+추가 등)을 이메일 등으로 주고받으려면 오히려 tar/zip 등 복잡한 구조가 되는 pre-VCS 시절처럼 퇴보함 느낌임
-
diff 대신 전체 파일을 전송하는 게 더 직관적이어도, 실제 용도와 환경에 따라 diff는 여전히 중요한 의미를 가짐 요즘처럼 LLM으로 코드 에디트 등 결과물을 생성할 때 diff로 요청하면 토큰을 크게 아끼고, 응답 지연을 5-10배까지 줄이는 등 현격한 효율 향상이 있었음 파일 두 개 모두 보내는 건 토큰 낭비와 비용이 큼 코드 샌드박스나 원격 머신에 빠르게 적용하려면 diff가 큰 최적화 이점이 있음 파일 A와 A2, diff AxA2가 있으면 A2 재구성도 쉽고 저장소 최적화도 가능함 병합시 충돌 문제가 있다면 그때만 직접 개입하면 됨 요약하자면 diff는 훌륭함
-
-
diff 도구가 줄바꿈 단위에 너무 의존하는 점이 아직도 불만임 한 줄이 너무 길 때(예: JSON, 긴 배열 등) 리뷰가 어려움
-
나도 동감함 구조화된 데이터(예: AST diff 등)에서 더 나은 diff 표현 방식을 탐구할 여지가 많다고 생각함 이 포맷(DiffX)은 기존 Unified Diff 포맷의 확장형임에 중점을 두었고, 만약 AST 등 더 구체적인 포맷이 널리 쓰인다면 그 또한 쉽게 내장 및 지원할 수 있도록 설계했음
-
흔히 쓰는 형태는 인간 가독성과 툴 파싱의 절충점이라서 어중간한 구조임, 이번엔 메타데이터 확장으로 문제를 일부 해결하려 한 듯하지만 정말 좋은 솔루션은 평문이 아닌 읽기 쉬우면서 파싱 가능한 포맷을 새로 정하는 것일 듯함 긴 줄이나 구조 데이터에 대해 기존보다 더 나은 diff 알고리즘을 만드는 것이 어려운 과제지만 충분히 해결 가능하다 생각함
-
git은 line diff보다 세밀한 word diff도 지원하고, 기본 구분자는 공백임
-
-
JSON이 유일하게 지원되는 메타데이터 포맷이라는 점에 의문감이 듬 보편적인 목적으로 설계된 메타데이터 표준에 JSON은 오히려 복잡함
- 왜 JSON이 과도하게 복잡하다고 생각하는지 구체적인 설명을 듣고 싶음