줄바꿈 CRLF와 LF 차이: 같은 글인데 파일 비교가 달라질 때

문서 편집기나 터미널 화면으로 파일을 열어 보면 텍스트 내용과 줄 수가 완전히 일치하는데, 파일 크기가 몇 바이트씩 차이 나거나 파일 비교 도구에서 모든 줄이 변경된 것으로 나타나는 경우가 있습니다. 이는 글자 자체가 깨진 UTF-8 인코딩 오류나 쉼표 처리로 인한 CSV 열 밀림과는 전혀 다른 문제입니다. 바로 줄바꿈을 기록하는 바이트 표현 방식이 다르기 때문에 발생합니다.

화면 속 텍스트는 같은데 바이너리 비교가 실패하는 이유

컴퓨터에서 텍스트 파일의 줄바꿈은 눈에 보이지 않는 특수 제어 문자로 표현됩니다. 대표적으로 두 가지 방식이 널리 쓰입니다.

  • LF (Line Feed): 바이트 \n(16진수 0x0A) 하나로 줄바꿈을 나타냅니다. 주로 유닉스 계열 환경에서 표준으로 사용됩니다.
  • CRLF (Carriage Return + Line Feed): 바이트 \r\n(16진수 0x0D 0x0A) 두 바이트 연속 조합으로 한 줄을 넘깁니다. 주로 전통적인 Windows 환경 문서에서 사용됩니다.

텍스트 에디터나 웹 브라우저는 두 방식을 모두 인식하여 줄을 바꿔 표시하므로 사람이 눈으로 볼 때는 차이를 감지하기 어렵습니다. 그러나 파일 단위로 바이트를 직접 대조하거나 SHA-256 해시로 파일을 비교하면 줄마다 1바이트씩 차이가 누적되어 전혀 다른 파일로 처리됩니다.

바이트 단위 검증 예제

두 줄로 구성된 동일한 텍스트 A와 B를 각각 CRLF 방식과 LF 방식으로 저장했을 때의 물리적 바이트 차이를 비교한 결과입니다.

CRLF: b'A\r\nB\r\n' (6 bytes)
LF: b'A\nB\n' (4 bytes)
바이트 비교: 다름
줄 단위 분리 결과: 같음

위 검증 데이터에서 알 수 있듯, 문자열을 줄 단위로 쪼개어(split lines) 문자 데이터만 대조하면 완전히 일치(true)합니다. 그러나 파일의 실제 바이트 크기는 2줄 기준으로 CRLF가 6바이트, LF가 4바이트로 다르며, 원시 바이트 비교(bytes equal)는 불일치(false)로 판정됩니다. 줄 수가 수만 줄에 달하는 대용량 로그나 데이터 파일이라면 수십 킬로바이트 이상 차이가 벌어집니다.

소프트웨어와 스트림의 newline 처리 방식

Python TextIOWrapper 공식 문서에 명시된 동작 방식을 살펴보면 텍스트 스트림과 줄바꿈 처리의 원리를 명확하게 이해할 수 있습니다.

텍스트 스트림을 읽을 때 newline=None으로 설정된 유니버설 줄바꿈 모드(universal newlines mode)에서는 입력에 포함된 \n, \r, \r\n을 모두 읽어 들여 프로그램 내부에서는 표준 \n으로 변환해 반환합니다. 반면 newline=''을 지정하면 유니버설 모드가 켜지되 원본에 기록된 줄 끝 제어 문자를 변환하지 않고 그대로 반환합니다. 쓸 때(writing) 역시 newline=None이면 작성 중인 \n 문자를 시스템 기본 줄 구분자(예: Windows 환경의 CRLF)로 자동 변환하고, newline=''이나 \n으로 지정하면 별도의 치환 없이 있는 그대로 기록합니다.

이처럼 많은 개발 언어와 도구가 읽을 때 줄바꿈을 하나로 합쳐서(추상화하여) 다루기 때문에, 파일을 읽고 쓰는 과정에서 의도치 않게 LF가 CRLF로 늘어나거나 반대로 줄어드는 현상이 생깁니다.

구분LF (Line Feed)CRLF (CR + LF)
바이트 표현\n (1바이트)\r\n (2바이트)
줄당 추가 용량기준 (1바이트)줄마다 1바이트씩 추가
문자열 줄 비교일치 판정일치 판정
해시·바이트 비교CRLF와 불일치LF와 불일치

줄바꿈 불일치 확인과 안전한 변환 순서

협업 시스템이나 배포 스크립트에서 줄바꿈 차이로 인해 오류가 생겼다면 다음 순서로 원인을 확인하고 안전하게 정리합니다.

  1. 원본 보존 및 사본 생성: 줄바꿈 문자를 치환하기 전에 원본 파일의 백업 사본을 먼저 만듭니다.
  2. 편집기 상태 표시줄 점검: 사용 중인 편집기(VS Code, Notepad++, IntelliJ 등)의 하단 상태 표시줄에서 현재 파일의 줄바꿈 모드가 CRLF인지 LF인지 확인합니다.
  3. 보이지 않는 문자(제어 문자) 표시 켜기: 편집기 설정에서 공백 및 줄바꿈 기호 표시 옵션을 켜서 각 줄 끝에 CR LF가 찍혀 있는지, 단독 LF만 있는지 눈으로 직접 확인합니다.
  4. 마지막 줄바꿈(EOF) 확인: 파일의 가장 마지막 줄 끝에 줄바꿈이 누락되었거나 불필요한 빈 줄이 포함되어 크기 차이가 나는지 점검합니다.
  5. 사본에서 통일 변환: 상태 표시줄의 줄바꿈 단추를 누르거나 변환 기능을 통해 프로젝트 표준(보통 Git 기반 협업에서는 LF 권장)으로 사본을 변경한 뒤 저장합니다.
  6. 바이너리 및 해시 검증: 사본의 용량 변화를 확인하고, 비교 도구에서 줄바꿈 무시 옵션을 끄더라도 차이가 사라졌는지 최종 확인합니다.

주의할 점과 이 방법의 한계

줄바꿈 방식을 통일할 때 주의해야 할 예외 사항과 한계가 있습니다.

첫째, 바이너리 데이터 혼입 여부입니다. 일반 텍스트 파일이 아니라 이미지, 바이너리 포맷, 또는 텍스트 내부에 고유한 바이트 규격이 정해진 데이터 파일의 경우 무작정 줄바꿈 변환 도구를 적용하면 데이터가 손상될 수 있습니다. 순수한 텍스트 스트림인지 먼저 파악해야 합니다.

둘째, 줄바꿈 제어 문자를 치환하더라도 문자 인코딩 차이나 공백 문제는 해결되지 않습니다. 예를 들어 BOM(Byte Order Mark)이 붙어 있거나 줄 끝 공백(trailing whitespace)이 섞여 있는 문제는 줄바꿈 형태를 LF로 맞춘다고 해서 자동으로 정리되지 않으므로, 줄바꿈 점검과 별개의 검사 항목으로 나누어 다루어야 합니다.

참고 자료와 확인 범위

아래 자료는 형식·기능의 정의를 확인하는 데 사용했습니다. 본문의 예제와 설명은 이 사이트의 작업 상황에 맞춰 구성했습니다. 제품 메뉴는 버전과 언어에 따라 다를 수 있습니다.

확인일: 2026-10-17 · 오류를 발견하면 이 글의 오류 신고로 알려주세요.