# Source code quality in the AI era > AI 시대에도 소스 코드의 품질은 여전히 중요하다고 생각한다. 단기적인 이유와 장기적인 이유가 있다. [AI](https://wiki.g15e.com/pages/Artificial%20intelligence.txt) 시대에도 소스 코드의 품질은 여전히 중요하다고 생각한다. 단기적인 이유와 장기적인 이유가 있다. ## 단기적인 이유 - 아직은 AI가 인간을 모방하고 있는 상황이기 때문에 인간이 잘 다루는 코드를 AI도 잘 다룰 것이다. 따라서 코드 품질은 여전히 중요할 것. ([Welcome to the Era of Experience](https://wiki.g15e.com/pages/Welcome%20to%20the%20Era%20of%20Experience.txt)의 구분에 따르면 아직은 "인간 데이터의 시대"이기 때문) - 코드 품질이 낮아지면(긴 코드, 순환 참조, 높은 결합도 등) [LLM](https://wiki.g15e.com/pages/Large%20language%20model.txt)의 컨텍스트에 올릴 토큰 수가 많아진다. LLM이 지원하는 컨텍스트 크기는 꾸준히 늘고 있지만 컨텍스트가 길어지면 LLM이 엉뚱한 짓을 하는 현상(context rot)이 벌어진다. (상대적으로 사소한 문제이지만, 토큰을 많이 쓰면 비용도 더 들고 시간도 더 걸린다) - AI가 코드를 빠르게 생산하기 시작하면서 병목이 코딩에서 리뷰로 옮겨지고 있다. 이 병목을 해소하려면 AI가 더 큰 단위의 작업을 붙들고 오래 일하고 결과물이 인간이 검토하기 좋은 형태로 나와야 한다. 토큰과 시간(AI의 시간)을 더 쓰더라도 품질 좋은(따라서 검토하기 좋은) 코드가 만들어지도록 유도하는 게 좋다. ## 장기적인 이유 장기적으로는 AI가 굳이 인간을 모방할 필요가 없으니 인간 기준의 "품질 좋은 코드"가 의미 없다고 생각할 수도 있다. 굳이 텍스트 기반의 "<소스 코드>"를 만들고 이걸 기계 코드로 바꾸는 과정이 불필요해질 수도 있다. 하지만 이런 상황이 된다고 하더라도 여전히 품질 좋은 코드는 중요할거라고 본다. 두 가지 이유가 있다. - 첫째, 재귀적 분해와 조합, 모듈 간 격리 등의 특성은 인간의 이해가능성과 무관하게 그 자체로 좋은 속성이다. 이건 추측인데 인간의 마음이 재귀적 분해와 조합에 익숙하게끔 [진화](https://wiki.g15e.com/pages/Evolution.txt)한 이유도 애초에 세상과 의미있는 상호작용을 하려면 그런 능력이 필요하기 때문일 것. 즉, 재귀적 분해와 조립은 인간 마음에 국한된 특성이 아니라고 생각한다. 다만 인간의 이해가능성과 호환되지 않는 모듈 간 위계, 모듈 간 인터페이스의 형태 등도 존재할 것. - 둘째, 어차피 미래에도 인간이 (AI의 도움을 받아) 소프트웨어 감사를 하긴 해야할텐데(법적/윤리적 책임 관점에서) 이를 위해서는 인간이 이해가능한 코드가 여전히 필요하다. 다만 이런 맥락에서 "코드의 품질"이 무엇을 의미하는지에 대한 세세한 기준은 바뀔 수 있겠다. 예를 들면 "읽기가 얼마나 용이한가"가 "수정이 얼마나 용이한가"에 비해 (지금보다 훨씬 더) 중요해진다거나. ## AI가 생성한 코드의 품질을 강제하기 [에이전트 기반 코딩](https://wiki.g15e.com/pages/Agentic%20coding.txt)을 하거나 [바이브 코딩](https://wiki.g15e.com/pages/Vibe%20coding.txt)을 하는 경우 코드 품질이 크게 낮아지는 경우가 있다. 하지만 소스 코드의 품질을 정량적으로 평가하거나 특정 설계를 강제할 수 있는 도구들이 제법 있으니 이런 것들을 잘 활용하면 품질을 일정 수준 이상으로 관리할 수 있다. AI 모델이 얼마나 똑똑해지는지도 중요하지만, 모델에게 적절한 도구들을 제공하여 모델이 일을 잘 할 수 있는 [인지적 적소를 구축해주는 일](https://wiki.g15e.com/pages/Cognitive%20niche%20construction.txt) 또한 매우 중요하다. 다음은 내가 사용해본 제법 괜찮은 조합. 토큰과 AI 시간을 더 쓰더라도 인간이 리뷰하기 좋은 코드를 만드는 게 중요(인간의 리뷰가 전체 프로세스의 병목이므로)하다는 가정 하에 괜찮았다. [자바스크립트](https://wiki.g15e.com/pages/JavaScript.txt) 기준이지만 다른 언어를 쓰는 경우에도 대체로 유사한 도구가 있다. - **기본적인 정적 타입 검사**: `tsc --noEmit` - **린터를 이용한 추가 제약**: - `typescript-eslint`는 `recommended` 말고 `strictTypeChecked`를 사용 - 파일 최대 길이, 함수 최대 길이, 함수 최대 문장 수 제약 - [인지복잡도](https://wiki.g15e.com/pages/Cognitive%20complexity.txt) 제약(`eslint-plugin-sonarcode`) - `switch` 문에서 모든 분기 검사(`@typescript/switch-exhaustiveness-check`), 매직 넘버 금지(`@typescript-eslint/no-magic-numbers`, 일부 예외 허용) 등 - **의존 관계 강제**: - 비즈니스 로직이 렌더링 관련 코드에 의존하지 못하도록 하기(`dependency-cruiser`) - Feature-Sliced Design을 하는 경우 각 feature가 독립적으게 강제하기(`dependency-cruiser`) - 각 모듈이 너무 많은 모듈에 의존하지 못하게 하기(`eslint-plugin-import`) - 그 밖에 내가 원한 설계 기준을 벗어나지 못하도록 강제 - **코드 중복 검사**: `jscpd` 등으로 구조적으로 동일한 코드 덩어리가 있으면 에러가 발생하도록 강제. 덩어리의 크기는 적당히 설정. - **테스트 커버리지**: 단위 테스트와 인수 테스트와 테스트 커버리지 측정(`vitest` 등)하고 특정 기준 미만이면 오류를 내기 - **죽은 코드 검사**: 의도적으로 그렇게 훈련시킨 것 같은데, 코딩 에이전트를 코드를 지우는 일을 좀처럼 하지 않는다. 안쓰는 코드를 자동으로 검사해서 지우도록 할 필요가 있다. `knip` 등 사용 - **테스트-프로덕션 코드 비율 강제**. AI에게 단위 테스트를 만들어달라고 시키면 같은 경로를 반복적으로 지나고 동일한 로직을 중복해서 검사하는 테스트를 너무 많이 만드는 경향이 있다. 테스트 대 프로덕션 코드 비율이 특정 수준(예: 150%, 인수 테스트를 포함하는 경우 180%)을 넘지 않도록 강제하면 이런 문제를 막을 수 있다. (`tokei` 등) 여러 도구를 잘 조합하는 게 중요하다. 원래도 있던 문제지만 AI 에이전트를 쓰는 경우 문제가 더 극단적으로 발생하는 경향이 있다. 예시: - 테스트-프로덕션 코드 비율을 강제하지 않으면서 테스트 커버리지만 검사하면 테스트 갯수가 한없이 늘어나는 문제가 있다. - [인지복잡도](https://wiki.g15e.com/pages/Cognitive%20complexity.txt)를 측정하지 않으면서 중복만 계속 제거하라고 하면 로직이 한없이 복잡해진다.