아카이브(arXiv.org)에서 흥미로운 논문을 읽었고 내용을 정리해봅니다.
소프트웨어 엔지니어링 역사에서 “가독성”은 성역과도 같은 가치였습니다. 코드는 컴퓨터가 실행하기 위해 작성되지만, 인간이 읽기 위해서도 작성된다는 이야기가 많았지요. 그래서 개발자들은 들여쓰기 규칙을 놓고 탭과 스페이스 논쟁을 벌이기도 했답니다. 이러한 것들은 결국 “인간의 인지 부하”를 줄이기 위함이었지요.
그러나 LLM이 주도하는 AI기반 코딩의 시대가 도래하면서 예상치 못했던 상황들이 발생하고 있습니다. “우리가 주변 동료를 위해 넣어둔 그 많은 공백과 줄바꿈이 과연 AI에게도 유용한가?”라는 질문에 답을 해야하는 시점입니다. 제가 읽은 논문은 이 질문에 대해 충격적인 답을 내놓습니다. 우리가 코드 가독성을 높이기 위해 사용하는 포맷팅 요소들이, LLM의 관점에서는 아무런 의미 정보가 없는 “노이즈”일 뿐이고, 막대한 토큰 비용을 발생시키고, 추론 속도를 저하시키는 주범이라는 것입니다.

위 그림은 포맷팅된 자바 코드와 포맷팅되지 않은 자바 코드 조각을 비교한 것입니다. 같은 배경색으로 표시된 문자는 동일한 토큰을 나타냅니다. 포맷팅되지 않은 코드는 구문의 정확성을 유지하면서 들여쓰기, 공백 및 줄 바꿈을 제거하여 생성됩니다.
그럼 한번 내용을 상세하게 파헤쳐볼까요?
문제의 정의: 토큰 경제와 공백 문자
현대 개발은 IDE에서 코드를 작성할 때 자동 포맷터를 사용하여 코드를 예쁘게 정렬합니다. 함수 인자가 길어지면 줄을 바꾸고, 블록 사이에서는 빈 줄을 넣어 가독성을 확보합니다. 이런 시각적 구조화는 인간의 뇌가 코드를 패턴으로 인식하는데 필수적입니다.
그러나 LLM은 코드를 2차원 구조가 아닌 1차원 방식으로 인식합니다. LLM에게는 개행이나 공백은 토큰일 뿐입니다. 문제는 이것이 전체 코드의 상당 부분을 차지하고 있다는 점입니다.
LLM의 비용은 토큰 수에 비례합니다. 토큰 수가 늘어날수록 아래와 같은 현상이 발생합니다.
- 비용 증가: 불필요한 공백처리에도 비용을 지불해야 합니다.
- 지연 시간 증가: 모델이 처리하고 생성해야 할 토큰이 많아지기에 응답 속도가 느려집니다.
- 컨텍스트 윈도우 낭비: 제한된 컨텍스트에 더 많은 유효 코드를 담지 못하고 공백으로 채우게 되어, 코드 분석 시 성능 저하를 유발합니다.
이 비효율성의 원인은 BPE(Byte Pair Encoding)와 같은 Tokenizer의 작동 방식에 있습니다. Tokenizer는 자주 등장하는 문자열 패턴을 하나의 토큰으로 압축하려 시도합니다. 하지만 코드의 공백 패턴을 매우 다양하고 불규칙하기에 효율적인 압축이 어렵습니다.
일반적으로 int a = 1; 에 대한 토큰화는 [int], [ a], [ =], [ 1], [;] 이렇게 수행됩니다. 만약에 개행이 있으면 [\n], [\n] 으로 토큰화됩니다.
연구에 따르면, 소스 코드에서 포맷팅 요소를 제거하는 것만으로도 전체 토큰의 약 24.5%를 줄일 수 있다고 합니다. 이는 우리가 LLM에 지불하는 비용의 1/4이 단지 코드를 예쁘게 만들기 위한 포맷팅 처리에 쓰이고 있음을 시사합니다.
연구 분석
논문의 연구팀은 아래의 가설을 검증하기 위해 실증 연구를 수행했습니다. 연구의 핵심 가설은 세 가지 입니다.
- RQ1: 포맷팅 제거가 LLM의 성능과 효율성(토큰 감소)에 어떤 영향을 미치는가?
- RQ2: 어떤 포맷팅 요소(개행, 들여쓰기)가 가장 큰 영향을 미치는가?
- RQ3: LLM이 비정형 코드를 생성하도록 최적화 할 수 있는가?
연구팀은 공정한 평가를 위해 아래의 실험 환경을 구축했습니다.
- 대상 언어: Java, Python, C++, C#
- 실험 상용 모델: GPT-4o, Gemini-1.5-pro, Claude-3.5-Sonnet
- 실험 오픈 모델: DeepSeek-Coder-V2, StarCoder2, CodeLiama
- 평가 방식: 코드의 중간 부분을 비워두고 LLM이 이를 채우게 하여, 문맥 이해도와 생성 능력을 평가
- 데이터셋: 각 언어별 대규모 리포지토리 데이터
실험은 원본 코드와 구문적 정확성은 유지하되 모든 시각적 포맷팅을 제거한 코드를 각각 모델에 입력하여 비교하는 방식으로 진행되었습니다.
RQ1: 성능 저하 없는 효율성 증대
실험 결과는 시각적 포맷팅을 제거한 코드를 사용했을 때, LLM의 코드 생성 성능은 떨어지지 않거나, 일부 케이스에서는 향상되었습니다.
- 토큰 감소 효과: 4개 언어 평균 24.5%의 입력 토큰 감소가 확인되었습니다. 이는 별도의 알고리즘적 압축 없이, 단순히 텍스트 전처리만으로 얻을 수 있는 수치입니다.
- 성능 유지: GPT-4o나 Gemini-1.5와 같은 모델들은 포맷팅이 없는 코드(한줄로 이어진 코드)를 입력받아도, 그 의미를 완벽하게 파악하고 올바른 코드를 생성했습니다.
위 결과는 LLM에게 코드는 텍스트라기보다 논리적 심볼의 연속이라는 가설을 뒷받침해줍니다. 인간에게는 가독성이 인지적 윤활유 역할을 했지만, LLM에게는 방해물이 될 수 있다는 것입니다.
RQ2: 토큰 낭비의 주범은 개행
연구팀은 어떤 포맷팅 요소가 가장 많은 토큰을 낭비하는지 요소별 제거 실험을 수행했습니다.
- 개행(Newlines): 토큰 증가의 가장 큰 원인입니다. 특히 함수 선언부, 긴 인자 리스트, 블록 구분을 위한 빈 줄 등이 누적되어 막대한 토큰을 소모합니다.
- 들여쓰기(Indentation): 토큰 증가 영향도는 높음입니다. 중첩된 루프나 조건문이 많은 코드에서 급격히 증가합니다. Python과 같이 들여쓰기가 강제되는 언어에서는 제거가 제한적일 수 있습니다.
- 연산자 공백: 토큰 증가 영향도는 낮습니다. a = b + c를 a=b+c로 줄이는 것은 토큰 수에 큰 영향을 주지 않았습니다. 대부분의 Tokenizer가 이를 효율적으로 처리하기 때문입니다.
위의 결과를 보면 개행 문자 제거가 가장 드라마틱한 효과를 보였습니다. 예를 들어 C++ 코드에서 개행을 모두 제거했을 때, Claude 모델에서는 입력 토큰이 약 18.7% 감소했습니다. 이는 코드 스타일 가이드가 권장하는 한 줄에 하나의 명령문 규칙이 LLM 시대에는 비용 효율성을 저해하는 요인이 됨을 시사합니다.
RQ3: 입력뿐만 아니라 출력도 줄일 수 있는가?
입력 토큰을 줄이는 것은 이미 작성된 코드를 전처리하면 되기에 비교적 쉽습니다. 연구팀은 LLM이 생성하는 코드도 포맷팅을 제거하여 비용을 아낄 수 있는지에 대해 두 가지 테스트를 했습니다.
테스트 1: 프롬프트 엔지니어링
프롬프트에 “불필요한 공백이나 줄바꿈을 넣지 말고, 한 줄로 코드를 작성해줘”라고 지시하는 방식입니다. 이는 모델별 편차가 컸고 GPT-4o가 지시를 잘 따르며 토큰을 줄였다고 합니다. Gemini-1.5의 경우, C++ 코드 생성 시 포맷팅을 제거하라는 지시를 과도하게 해석하여 문법적으로 잘못된 코드를 생성했습니다. 이는 프롬프트만으로는 복잡한 문법 규칙을 유지하면서 포맷팅만 제거하는 미묘한 제어를 하기 어렵다는 것을 보여줍니다.
테스트 2: 파인 튜닝
적은양의 비정형 코드 데이터셋으로 모델을 추가 학습 시키는 방식입니다. 결과는 성공적이었고, 단 50개의 비정형 코드 샘플만으로 파인 튜닝을 해도, Gemini-1.5와 GPT-4o 모두 성능 저하없이 출력 토큰을 각각 35.9%, 24.8%를 줄였습니다. 이는 LLM이 코드의 “형태”가 아닌 “의미”를 학습할 수 있는 유연성을 가졌음을 의미합니다. 자체 코딩 모델을 구축할 때, 학습 데이터에서 포맷팅을 제거하는 전처리를 수행하면 추론 속도와 비용면에서 훨씬 유리한 모델을 만들 수 있다는 결론에 도달 합니다.
양방향 코드 변환 도구
본 논문의 결과를 현장에 적용하기 위해서 연구팀은 양방향 코드 변환 도구를 개발하여 공개했습니다. 이 도구는 가독성과 효율성이라는 상충하는 가치를 조화시키는 가교 역할을 합니다.
본 도구는 사람이 읽기 쉽고 형식이 잘 갖춰진 코드와 LLM이 사용하기 편리한 간결한 코드 간의 양방향 변환을 지원합니다.

위 그림에서 볼 수 있듯이, 도구를 사용하면 이중 변환 추론 워크플로우를 구축할 수 있습니다. 이를 통해 LLM은 효율적이고 간결한 코드의 이점을 누리는 동시에 개발자는 익숙한 포맷팅의 코드를 사용할 수 있습니다. 입력 코드에서 서식 요소를 제거하여 LLM이 이해하는데 필요한 토큰 사용량을 줄입니다. 출력에서는 LLM이 생성한 코드의 서식을 복원하여 사람이 읽기 쉽도록 합니다.
연구팀은 MCEval(Massively Multilingual Code Evaluation, 대규모 다국어 코드 평가) 데이터셋을 활용해 도구의 안정성을 검증했습니다.
- 무결성 검증: 변환 전후 코드의 AST(Abstract Syntax Tree)가 동일함을 100% 검증했습니다. 즉, 로직이 변질될 위험이 없습니다.
- 처리 속도: 평균 76ms의 지연 시간을 기록했습니다. LLM의 네트워크 왕복 시간이나 추론 시간에 비하면 무시할 수 있는 수준입니다.
시사점
이 연구 결과는 LLM처리에서 코드 가독성의 숨겨진 비용을 밝히고, “인간에게 좋은 것이 반드시 AI에게도 좋은 것은 아니다.”라는 시사점을 줍니다.
- 가독성의 비용 인식: 코드의 공백과 줄바꿈은 LLM 예산의 약 1/4을 낭비하고 있습니다. 이를 인지하고 관리해야 합니다.
- 안전한 제거: 최신 LLM은 포맷팅이 없어도 코드의 로직을 완벽하게 이해합니다. 두려움 없이 압축해도 됩니다.
- 도구의 도입: 양방향 변환 도구를 개발 파이프라인에 통합하는 것을 고려해야 합니다.
우리는 오랫동안 코드를 “인간이 읽기 위한 문학”처럼 다루어 왔습니다. 하지만 AI와 협업하는 시대에 코드는 “AI가 처리할 데이터”의 성격도 동시에 가지게 됩니다. 이제 개발자들은 두 가지 모드를 유연하게 오가야 합니다. 코드를 작성하고 리뷰할 때는 최대한 가독성을 높여야 하지만, 이를 AI에게 넘길 때는 과감하게 군더더기를 덜어내야 합니다.
참고: