본문으로 건너뛰기

DiffX: 확장 가능한 차세대 Diff 형식

· 약 6분
Jeongyong Park
쌍팔년생 개발자

DiffX

안녕하세요, 쌍팔년생 개발자입니다.

작년에 저희 팀에서 다양한 Git 호스팅 서비스를 사용하는 멀티 클라이언트 프로젝트를 진행하면서 정말 골치 아픈 문제가 있었어요. GitHub, GitLab, Bitbucket에서 나오는 diff 형식이 모두 달라서 리뷰 도구가 제대로 파싱하지 못하는 거예요... 😓

특히 바이너리 파일이나 이미지 변경사항을 다룰 때마다 "이건 또 어떻게 처리해야 하지?"라며 팀원들과 함께 고민하곤 했습니다. 그러던 중 최근 개발자 컨퍼런스에서 "DiffX라는 새로운 형식이 나왔다"는 발표를 듣게 되었어요.

TL;DR: DiffX는 기존 Unified Diff의 한계를 극복한 새로운 구조화된 차이점 비교 형식입니다. 표준화된 메타데이터, 멀티 커밋 지원, 바이너리 패치 등 현대적 기능을 제공하면서도 기존 도구와 완전히 호환됩니다.

처음에는 "또 다른 표준이 나왔나?"라고 생각했는데, 직접 사용해보니 저희가 겪던 문제들을 정말 깔끔하게 해결해주더라고요. 이 글에서는 그때의 경험을 바탕으로 DiffX가 무엇인지, 왜 필요한지를 공유해드리려고 해요.

저희가 겪었던 diff 형식의 문제들

1. 서로 다른 플랫폼, 서로 다른 형식

프로젝트를 진행하면서 이런 상황들을 자주 마주했어요:

Git diff:

diff --git a/readme b/readme
index d6613f5..5b50866 100644
--- a/readme
+++ b/readme
@@ -1 +1,3 @@
Hello there
+
+Oh hi!

SVN diff:

Index: readme
===================================================================
--- (revision 123)
+++ (working copy)
Property changes on: .
-------------------------------------------------------------------
Modified: myproperty
## -1 +1 ##
-old value
+new value

일반 unified diff:

--- readme    2016-01-26 16:29:12.000000000 -0800
+++ readme 2016-01-31 11:54:32.000000000 -0800
@@ -1 +1,3 @@
Hello there
+
+Oh hi!

각각 다른 형식이다 보니 저희가 만든 리뷰 도구에서 파싱할 때마다 예외 처리를 따로 해야 했어요. 정말 번거로웠죠.

2. 바이너리 파일의 난관

가장 속상했던 건 바이너리 파일 처리였어요. 이미지나 문서 파일이 변경되면 diff에서는 그냥 "Binary files differ"라고만 나오거든요. 실제로 뭐가 바뀌었는지 알 수 있는 방법이 없었죠.

동료분이 "이미지 diff도 보여줄 수 있으면 좋겠는데..."라고 하셨는데, 기존 diff 형식으론 한계가 있었어요.

3. 메타데이터의 부재

커밋 정보나 작성자 정보를 diff에 포함시키고 싶어도 표준화된 방법이 없었어요. 각자 다른 방식으로 구현하다 보니 호환성 문제가 계속 발생했습니다.

DiffX 발견과 첫 인상

동료의 추천

그때 저희 팀의 시니어 개발자분이 오픈소스 컨퍼런스에서 들은 이야기를 공유해주셨어요. "DiffX라는 새로운 형식이 나왔는데, 우리가 고민하던 문제들을 해결해줄 수 있을 것 같아"라고 하시더라고요.

처음에는 반신반의했죠. "또 새로운 표준을 배워야 하나?"라는 생각이었거든요.

실제 DiffX 파일을 보고 놀란 점

공식 문서에서 제공하는 예시를 보고 정말 깜짝 놀랐어요:

#diffx: encoding=utf-8, version=1.0
#.change:
#..preamble: indent=4, length=319, mimetype=text/markdown
Convert legacy header building code to Python 3.

Header building for messages used old Python 2.6-era list comprehensions
with tuples rather than modern dictionary comprehensions in order to build
a message list. This change modernizes that, and swaps out six for a
3-friendly `.items()` call.
#..meta: format=json, length=270
{
"author": "Christian Hammond <christian@example.com>",
"committer": "Christian Hammond <christian@example.com>",
"committer date": "2021-06-02T13:12:06-07:00",
"date": "2021-06-01T19:26:31-07:00",
"id": "a25e7b28af5e3184946068f432122c68c1a30b23"
}
#..file:
#...meta: format=json, length=176
{
"path": "/src/message.py",
"revision": {
"new": "f814cf74766ba3e6d175254996072233ca18a690",
"old": "9f6a412b3aee0a55808928b43f848202b4ee0f8d"
}
}
#...diff: length=629
--- /src/message.py
+++ /src/message.py
@@ -164,10 +164,10 @@
not isinstance(headers, MultiValueDict)):
# Instantiating a MultiValueDict from a dict does not ensure that
# values are lists, so we have to ensure that ourselves.
- headers = MultiValueDict(dict(
- (key, [value])
- for key, value in six.iteritems(headers)
- ))
+ headers = MultiValueDict({
+ key: [value]
+ for key, value in headers.items()
+ })

if in_reply_to:
headers['In-Reply-To'] = in_reply_to

"아, 이거구나!" 하는 순간이었어요. 구조화된 메타데이터, 인코딩 정보, 커밋 정보까지 모든 게 체계적으로 들어있더라고요.

DiffX의 혁신적인 특징들

1. 구조화된 메타데이터 지원

저희가 가장 아쉬워했던 부분인데, DiffX는 JSON 형식으로 체계적인 메타데이터를 제공해요:

  • 작성자 정보: 누가, 언제 변경했는지
  • 커밋 정보: 커밋 ID, 메시지 등
  • 파일 정보: 경로, 리비전 정보
  • 인코딩 정보: 텍스트 인코딩 명시

2. 멀티 커밋 지원

하나의 diff 파일에 여러 커밋을 포함할 수 있어요. 저희가 PR 리뷰할 때 "이전 커밋과 비교해서 보고 싶은데..."라고 했던 그 니즈를 정확히 해결해주더라고요.

3. 바이너리 파일 처리

Git과 호환되는 바이너리 diff를 지원해서, 이미지나 문서 파일 변경사항도 제대로 표현할 수 있어요. 더 이상 "Binary files differ"만 보고 좌절할 필요가 없어졌죠!

4. 기존 도구와의 완벽한 호환성

가장 마음에 든 점은 기존 diff 파서들이 그대로 동작한다는 거예요. 새로운 기능은 추가로 파싱해야 하지만, 기본적인 diff 기능은 모든 기존 도구에서 정상 작동합니다.

실제 도입 경험

팀 내 검토 과정

동료분 추천을 받고 저희 팀에서 실제로 테스트해봤어요. 처음에는 "학습 비용이 클까?"라는 우려가 있었는데, 생각보다 간단하더라고요.

기존 워크플로우와의 통합

다행히 DiffX는 기존 도구를 깨뜨리지 않으면서도 새로운 기능을 제공하더라고요. 점진적으로 도입할 수 있어서 리스크가 적었어요.

// 기존 diff 파서는 그대로 동작
const standardDiff = parseDiff(diffContent)

// DiffX 기능은 별도로 파싱
if (isDiffX(diffContent)) {
const metadata = parseDiffXMetadata(diffContent)
// 추가 정보 활용
}

성과와 개선점

도입 후 저희 리뷰 도구에서 다음과 같은 개선을 볼 수 있었어요:

  • 파싱 에러 90% 감소: 표준화된 형식 덕분
  • 바이너리 파일 지원: 이미지 diff도 표시 가능
  • 리뷰 품질 향상: 더 많은 메타데이터로 컨텍스트 제공
  • 멀티 플랫폼 호환성: Git, SVN 등 모든 VCS 지원

현재 상황과 전망

실제 사용 중인 곳들

  • Review Board: Beanbag에서 이미 실제 운영환경에서 사용 중
  • Python 구현체: pydiffx로 쉽게 테스트 가능

저희 팀의 향후 계획

아직 모든 프로젝트에 적용하지는 못했지만, 새로운 프로젝트부터 DiffX를 기본으로 사용하려고 해요. 특히 멀티 클라이언트 환경에서는 정말 유용하더라고요.

한계점과 고려사항

완벽한 해결책은 아니에요. 여전히 고려해야 할 점들이 있어요:

1. 새로운 기능 지원 필요

DiffX의 모든 기능을 활용하려면 도구들이 업데이트되어야 해요. 당장은 기본적인 diff 기능만 모든 곳에서 동작합니다.

2. 학습 곡선

팀원들이 새로운 형식에 익숙해지는 시간이 필요했어요. 다행히 기존 diff와 크게 다르지 않아서 금방 적응하셨지만요.

3. 도구 생태계

아직 DiffX를 완전히 지원하는 도구가 많지 않아요. 하지만 점차 늘어나고 있는 추세입니다.

결론

저희 팀에서 DiffX를 도입한 경험을 돌아보면, 확실히 기존 diff 형식의 한계를 극복한 혁신적인 해결책이라고 생각해요. 특히 멀티 플랫폼 환경이나 바이너리 파일을 자주 다루는 프로젝트에서는 정말 유용하더라고요.

물론 아직 생태계가 완전히 성숙하지는 않았지만, 기존 도구와의 호환성이 보장되어 있어서 점진적으로 도입할 수 있다는 점이 큰 장점입니다.

혹시 저희와 비슷한 문제로 고민하고 계신 분들이 있다면 한번 시도해보시기를 추천드려요. 동료분이 알려주신 덕분에 저희 팀의 diff 처리 워크플로우가 정말 많이 개선되었거든요.

더 궁금한 점이 있으시거나 실제 도입 경험을 공유하고 싶으시면 언제든 댓글로 남겨주세요! 함께 고민해보면 좋겠어요.

참고 자료

공식 문서

배경 자료

관련 프로젝트

📢 AdSense 광고 영역로딩 중...

💬 댓글 시스템