본문 바로가기

파일 형식 백과사전

같은 표를 저장했는데 파일 크기가 다릅니다, 줄 끝에 숨은 1바이트

같은 데이터를 두 사람이 각자 CSV로 저장해 비교해 보면 크기가 미묘하게 다를 때가 있습니다. 내용은 글자 하나까지 같은데 바이트 수가 안 맞습니다.

범인은 눈에 보이지 않는 자리, 줄이 끝나는 지점입니다. 줄바꿈을 표시하는 방식이 운영체제마다 달라서, 줄 하나마다 1바이트씩 차이가 쌓입니다. 같은 내용을 방식만 바꿔 저장하고 바이트를 직접 읽어 확인했습니다.

 

줄바꿈 방식별 실측 표. CRLF는 줄 끝에 0D 0A 두 바이트를 넣어 5줄 파일이 141바이트, LF는 0A 한 바이트로 136바이트, CR은 0D 한 바이트로 136바이트다. LF만 찾는 코드로 세면 CRLF와 LF는 5줄이지만 CR 파일은 0줄로 통째로 한 줄이 된다. 100만 줄이면 CRLF와 LF의 차이가 정확히 1,000,000바이트다

 

 

줄바꿈이 두 종류가 된 이유

타자기 시절에는 종이를 한 줄 올리는 동작과 활자 위치를 맨 왼쪽으로 되돌리는 동작이 따로 있었습니다. 초기 컴퓨터는 이 두 동작을 그대로 문자로 만들었습니다. CR(맨 앞으로 되돌리기, 0D)과 LF(한 줄 내리기, 0A)입니다.

이후 진영이 갈렸습니다. 윈도우는 두 개를 다 쓰고, 맥과 리눅스는 LF 하나만 씁니다. 파일에 적히는 바이트는 이렇게 달라집니다.

2026-01-15 로 끝나는 첫 줄의 끝부분

CRLF : 31 2D 31 35 0D 0A  (윈도우)
LF   : 31 2D 31 35 0A     (맥, 리눅스)
CR   : 31 2D 31 35 0D     (아주 오래된 맥)

글자가 아니라서 화면에는 안 보이지만, 파일에는 분명히 자리를 차지하고 있습니다.


다섯 줄에 5바이트, 100만 줄에 1MB

같은 다섯 줄짜리 표를 세 방식으로 저장했습니다. CRLF만 줄마다 1바이트를 더 씁니다.

줄바꿈 파일 크기 내용
CRLF 141 B 완전히 같음
LF 136 B 완전히 같음
CR 136 B 완전히 같음

다섯 줄이니 5바이트 차이입니다. 여기까지는 신경 쓸 일이 아닙니다. 그런데 같은 줄을 100만 줄 담아 재 보니 이렇게 나왔습니다.

LF   : 46,000,000 B
CRLF : 47,000,000 B
차이  : 1,000,000 B  (0.95 MB)

줄 수만큼 정확히 1바이트씩, 100만 줄이면 1MB가 됩니다. 로그 파일이나 수백만 행짜리 데이터를 다루면 무시하기 어려운 크기가 됩니다.

한 줄로 붙어 보이는 건 이 경우입니다

더 성가신 쪽은 크기가 아니라 읽기입니다. 같은 세 파일을 여러 방식으로 읽어 줄 수를 세 봤습니다. 실제 줄 수는 다섯입니다.

읽는 방식 CRLF LF CR
파이썬 기본 읽기 5줄 5줄 5줄
PowerShell Get-Content 5줄 5줄 5줄
LF만 찾아 자르는 코드 5줄 5줄 0줄

요즘 도구는 세 방식을 다 알아서 처리합니다. 문제는 줄바꿈을 LF 하나로만 가정하고 만든 프로그램입니다. CR로만 끝난 파일을 만나면 자를 지점을 하나도 못 찾아 파일 전체를 한 줄로 취급합니다. 파일을 열었는데 모든 내용이 한 줄에 늘어서 있다면 이 상황입니다.

반대 방향도 있습니다. LF만 줄바꿈으로 보는 리눅스 도구가 윈도우에서 만든 CRLF 파일을 읽으면, 남은 CR이 줄 끝마다 ^M이라는 이상한 표시로 붙어 보입니다.


내 파일이 어느 쪽인지 확인하고 바꾸기

파일을 바이트로 열어 CR과 LF가 각각 몇 개인지 세면 바로 판별됩니다.

raw = open("data.csv", "rb").read()
print("CR :", raw.count(b"\r"))
print("LF :", raw.count(b"\n"))

# CR 과 LF 가 같은 수  -> CRLF
# CR 이 0             -> LF
# LF 가 0             -> CR

바꾸는 것도 간단합니다. 읽을 때 줄만 뽑아내고 저장할 때 원하는 방식으로 다시 붙이면 됩니다. newline 옵션이 줄 끝에 무엇을 넣을지 정합니다.

with open("data.csv", encoding="utf-8") as f:
    text = f.read()                      # 세 방식 모두 알아서 처리

with open("data_lf.csv", "w", encoding="utf-8", newline="\n") as f:
    f.write(text)                        # LF 로 통일해 저장

서버나 협업 도구로 넘길 파일은 LF, 윈도우에서만 쓰는 파일은 그냥 두면 됩니다. 굳이 통일하지 않아도 요즘 프로그램은 대부분 알아서 읽습니다.

자주 묻는 질문

Q. 내용이 같은데 파일이 바뀐 것으로 표시됩니다.
줄바꿈이 다르면 바이트가 다르고, 바이트가 다르면 파일의 SHA-256 값도 달라집니다. 도구 입장에서는 다른 파일이라 바뀐 것으로 잡습니다. 내용 비교 기능으로 보면 차이가 없다고 나오는 이유가 여기 있습니다.

Q. 줄바꿈을 바꾸면 한글이 깨지나요?
줄바꿈과 글자 인코딩은 별개입니다. 한글이 깨지는 것은 파일을 어떤 인코딩으로 저장했는지의 문제입니다.

Q. CSV 값 안에 줄바꿈이 들어 있으면요?
큰따옴표로 감싼 값 안의 줄바꿈은 줄을 나누는 신호가 아닙니다. 제대로 만든 CSV 도구는 이것을 구분해 읽습니다.

Q. 어느 쪽이 더 좋은가요?
우열은 없습니다. 받는 쪽 환경에 맞추는 것이 기준입니다.

 

눈에 안 보이는 바이트가 파일을 갈라놓는다는 점에서, 압축 파일의 한글 이름이 깨지는 문제도 성격이 같습니다. 그쪽은 이름을 어떤 규칙으로 읽느냐가 갈리는 경우입니다.

 

위 크기와 줄 수는 윈도우 11에서 파이썬 3.14.3으로 같은 내용을 세 방식으로 저장한 뒤 다시 읽어 얻은 값이고, Get-Content 결과는 같은 파일을 PowerShell로 읽어 센 것입니다.

 

 

 

 

큰 CSV를 엑셀 대신 SQL로 다루기, SQLite에 불러와 조회하는 방법

수천 행짜리 CSV에서 도시별 매출 합계나 특정 조건의 주문만 뽑아내려면, 엑셀에서는 피벗 테이블과 필터를 여러 번 거쳐야 합니다. 이럴 때 CSV를 SQLite라는 가벼운 데이터베이스에 한 번 넣어

richyeon.com

 

 

커진 CSV를 gzip으로 압축하기, 얼마나 줄고 압축한 채로 바로 읽을 수 있을까?

로그나 내역 데이터를 CSV로 쌓다 보면 파일이 수십 메가바이트까지 불어납니다.텍스트라 압축이 잘 먹는데, 그렇다고 매번 압축을 풀었다 다시 읽자니 번거롭습니다. 그래서 두 가지가 궁금해

richyeon.com

 

 

투명 배경 PNG를 JPG로 저장했더니 배경이 새까맣게, 원인과 깔끔한 해결법

배경이 투명한 로고나 아이콘 PNG를 JPG로 바꿨더니, 투명하던 부분이 온통 검은색으로채워져 나오는 경우가 있습니다. 어떤 프로그램에서는 아예 저장이 안 되고 오류만 뜨기도 합니다. 파일이

richyeon.com