충돌

Merge Conflict

개념

두 사람이 같은 파일의 같은 줄을 다르게 고쳐서 도구가 어느 쪽을 남길지 정하지 못하고 멈춘 상태입니다.

등장 배경

여러 사람이 같은 코드를 동시에 고칠 수 있게 된 것은 갈라진 변경을 다시 합치는 머지 덕분입니다. 두 사람이 한 파일의 다른 부분을 고쳤다면 도구가 양쪽 변경을 줄 단위로 붙여 넣어 줍니다. 파일 하나를 스무 명이 건드려도 대개는 아무 일 없이 합쳐집니다.

문제는 같은 줄을 둘이 다르게 고친 자리입니다. 알림 문구 한 줄을 태오는 "읽지 않은 댓글 3개" 로 고치고 동료는 "새 댓글 3개" 로 고쳤다면, 어느 쪽이 맞는지는 코드 밖의 결정이라 도구가 알 수 없습니다. 근거 없이 한쪽을 고르게 두면 지는 쪽 수정이 아무 흔적 없이 사라집니다. 없어진 줄을 아무도 모르니, 며칠 뒤 사라진 기능을 발견하고 나서야 어디서 어긋났는지 되짚게 됩니다.

그래서 도구는 고르지 않고 멈추는 쪽을 택했습니다. 두 수정을 파일 안에 나란히 남겨 두고, 합치기를 끝내지 않은 채 사람을 부릅니다. 그 멈춘 자리에 붙은 이름이 충돌입니다. 사고가 아니라 도구가 판단을 미뤄 둔 표시라는 점이 중요합니다. 잃어버릴 뻔한 수정을 붙잡아 두는 장치에 가깝습니다.

작동 방식

도구는 세 개의 상태를 겹쳐 보면서 합칠 자리를 정합니다. 갈라지기 직전의 공통 상태, 내가 고친 상태, 상대가 고친 상태 셋입니다.

  1. 한쪽만 바꾼 줄은 그 변경을 그대로 채택합니다. 상대가 건드리지 않은 줄이니 고민할 게 없습니다.
  2. 양쪽이 똑같이 바꾼 줄은 그 값 하나만 남깁니다.
  3. 양쪽이 서로 다르게 바꾼 줄에서 멈춥니다. 이 자리가 충돌입니다.

멈춘 파일을 열면 그 자리에 표시가 들어가 있습니다. 위쪽에 내가 고친 줄, 아래쪽에 상대가 고친 줄이 놓이고 그 사이에 구분선이 그어져 있어서, 양쪽이 뭐라고 썼는지가 한 화면에 보입니다. 푸는 순서는 이렇습니다.

  1. 셋 중 하나를 고릅니다. 내 것을 남기거나, 상대 것을 남기거나, 둘을 읽고 새로 한 줄을 씁니다. 세 번째가 정답인 경우가 생각보다 많습니다. 한쪽은 문구를 다듬었고 다른 쪽은 숫자 계산을 고쳤다면 둘 다 살려야 합니다.
  2. 표시를 지웁니다. 구분선과 표식이 코드에 남은 채로 저장하면 그 파일은 아예 돌지 않습니다.
  3. 정리가 끝났다고 도구에 알립니다. 여기까지 해야 멈춰 있던 합치기가 다시 이어집니다.
  4. 테스트를 돌리고 화면을 엽니다. 손으로 고른 결과라서 기계가 검증해 준 것이 하나도 없습니다.

한쪽을 통째로 고르는 버튼이 눈에 띄지만 그 버튼이 위험한 자리가 있습니다. 파일 전체를 내 것으로 덮으면 상대가 그 파일에 넣은 다른 기능까지 함께 사라지고, 합치기는 성공으로 끝나서 아무도 알아차리지 못합니다.

쓰이는 곳

가장 흔한 자리는 며칠 묵힌 브랜치를 본류에 합칠 때입니다. 브랜치는 본류에서 갈라져 나온 작업 줄기인데, 갈라져 있던 시간이 길수록 그사이 본류에 쌓인 변경과 겹칠 확률이 올라갑니다. 풀 리퀘스트 화면에 "이 브랜치는 충돌이 있습니다" 라는 줄이 뜨고 합치기 버튼이 잠기는 것이 보통 첫 신호입니다.

리베이스로 기록을 옮겨 붙일 때도 납니다. 이쪽은 성격이 조금 다릅니다. 합치기는 한 번에 끝나는데 옮겨 붙이기는 기록 하나하나를 차례로 얹기 때문에, 같은 파일을 계속 건드린 기록이 열 개라면 비슷한 충돌을 열 번 풀게 됩니다.

파일 종류로 보면 모두가 손대는 파일에서 자주 납니다. 설정 파일, 외부 라이브러리 목록, 화면 목록처럼 기능을 하나 추가할 때마다 끝에 한 줄씩 붙는 파일이 대표적입니다. 두 사람이 각자 마지막 줄에 한 줄씩 더하면 위치가 정확히 겹칩니다. 사람이 직접 쓰지 않고 도구가 자동으로 만드는 파일도 마찬가지인데, 이런 파일은 손으로 고르는 대신 다시 생성해 버리는 쪽이 안전합니다.

충돌이 날 확률은 팀의 작업 방식이 정합니다. 본류에 하루에도 여러 번 합치는 트렁크 기반 개발에서는 겹치는 줄이 두세 개짜리 충돌이 자주 나고 5분이면 끝납니다. 브랜치를 3주씩 두는 팀에서는 한 달에 한 번 나는 대신 한 번에 파일 열 개가 걸립니다. 총량은 뒤쪽이 훨씬 큽니다.

실무 용례

"이 브랜치 충돌 났네요. 본류 한 번 받아서 풀고 다시 올려 주세요."

합치기 버튼이 잠겼으니 올린 사람이 자기 쪽에서 정리해 오라는 요청입니다.

"이 줄 누가 고쳤는지 아세요? 충돌 푸는데 제가 판단할 게 아닌 것 같아서요."

어느 쪽을 남길지가 기술 문제가 아니라 결정 문제라 원래 고친 사람을 찾는 말입니다.

"충돌 난다고 무조건 제 것으로 덮지 마세요."

상대 변경을 통째로 버리면 그 기능이 조용히 사라진다는 경고입니다.

페이지덱에서 태오가 댓글 알림 브랜치를 올렸을 때 충돌이 세 군데 났습니다. 두 군데는 다른 사람이 같은 목록 파일 끝에 줄을 더해 놓은 것이라 양쪽을 나란히 두는 것으로 끝났습니다. 남은 한 군데가 알림 문구였습니다. 태오가 고친 문구와 본류에 들어와 있던 문구가 서로 달랐고, 태오는 어느 쪽이 맞는지 혼자 정하지 않고 그 문구를 정한 민서에게 물었습니다. 답은 둘 다 아니었고 셋째 문구로 정리됐습니다.

이 장면에서 실제로 시간이 걸린 것은 표시를 지우는 일이 아니라 문구를 정하는 일이었습니다. 충돌을 푸는 시간의 대부분이 이렇게 흘러갑니다.

흔한 오해

충돌을 푸는 일을 기계를 달래는 기술 작업으로 읽는 경우가 많습니다. 화면에 낯선 표식이 뜨고 명령어를 몇 개 쳐야 넘어가니 그렇게 보입니다. 하지만 도구가 사람을 부른 이유는 기술적으로 막혀서가 아니라 무엇이 맞는지 몰라서입니다. 그래서 잘 푸는 사람은 명령어를 많이 아는 사람이 아니라 그 코드가 왜 그렇게 쓰였는지 아는 사람입니다. 이것을 기술 문제로 보면 그 줄을 쓰지도 않은 사람이 대신 풀게 되고, 대신 푸는 사람은 판단할 근거가 없어 대개 한쪽을 통째로 고릅니다.

충돌 없이 합쳐졌으니 안전하다고 읽는 것도 흔합니다. 표시가 안 떴으니 문제가 없다고 느껴집니다. 도구가 본 것은 줄이 겹쳤는지뿐입니다. 태오가 함수 이름을 바꾸고 동료가 같은 함수를 다른 파일에서 새로 불렀다면, 두 변경은 줄이 겹치지 않아 조용히 합쳐지고 합쳐진 결과는 돌지 않습니다. 이런 어긋남은 충돌 표시가 아니라 테스트나 코드 리뷰에서 걸립니다. 합치기가 조용히 끝난 뒤에도 검증 절차가 남아 있는 이유입니다.

같이 보면 좋은 페이지

  • 버전 관리

    충돌이 어느 체계 안에서 생기는 일인지 먼저 봅니다

  • Git

    충돌을 표시하고 멈춰 세우는 도구 쪽을 봅니다

마지막 업데이트 2026-09-16