AI가 우리에게 좋은 코드를 쓰도록 강요하고 있다
(bits.logic.inc)- AI 에이전트가 코드 작성의 중심에 들어오면서, 테스트, 문서화, 정적 타이핑 등 기존의 ‘선택적’ 모범 사례들이 이제 필수 요소로 변함
- 100% 코드 커버리지를 요구해, 모든 코드 라인이 실제로 검증되고 실행 예제로 뒷받침되도록 함
- 디렉터리 구조와 파일 네이밍을 명확히 하여 LLM이 코드베이스를 탐색하기 쉽게 만들고, 작은 단위의 파일 구성을 권장
- 빠르고 일시적이며 동시 실행 가능한 개발 환경을 구축해, 여러 에이전트가 병렬로 작업할 수 있도록 함
- 정적 타입 시스템과 자동화된 품질 관리 도구를 통해 AI가 신뢰할 수 있는 코드 생태계를 유지하는 것이 핵심임
AI와 ‘좋은 코드’의 필수성
- 오랜 기간 개발자들은 테스트, 문서화, 작은 모듈, 정적 타이핑 등을 좋은 코드의 기준으로 인식했지만, 현실에서는 종종 생략됨
- 그러나 AI 에이전트는 스스로 코드 정리를 잘 하지 못하므로, 이러한 모범 사례가 반드시 필요함
- 에이전트가 잘못된 방향으로 작동하지 않도록 명확한 가드레일 설정과 강제 실행이 필수
- 견고한 가드레일이 있으면 LLM은 올바른 경로로만 수렴하며, 불완전한 환경에서는 문제를 증폭시킴
100% 코드 커버리지
- 팀은 100% 코드 커버리지를 의무화하고 있으며, 이는 단순한 버그 방지가 아니라 에이전트가 작성한 모든 코드의 동작을 검증하기 위함
- 95%나 99.99% 커버리지에서는 테스트되지 않은 코드의 출처가 불분명하지만, 100%에서는 모든 미검증 라인이 명확히 식별 가능
- 커버리지 리포트는 테스트해야 할 목록으로 활용되며, LLM이 코드 변경 시 반드시 실행 가능한 예제를 제시해야 함
- 이 접근은 도달 불가능한 코드 제거, 엣지 케이스 명시, 코드 리뷰 효율 향상 등의 부수 효과를 가짐
네임스페이스와 파일 구조
- 에이전트는 파일 시스템을 통해 코드베이스를 탐색하므로, 디렉터리 구조와 파일 이름이 중요한 인터페이스 역할을 함
- ./billing/invoices/compute.ts 같은 명확한 경로는 ./utils/helpers.ts보다 훨씬 많은 정보를 전달
- 작고 잘 정의된 파일 단위를 선호해야 하며, 이는 LLM이 파일 전체를 문맥에 로드할 수 있게 해 성능 저하를 방지함
- 이러한 구조화는 에이전트의 탐색 속도와 정확도 향상으로 이어짐
빠르고 일시적이며 동시 실행 가능한 개발 환경
- 기존의 단일 개발 환경 대신, 에이전트 기반 개발에서는 여러 프로세스를 병렬로 관리하는 형태로 전환됨
-
Fast: 테스트와 검증 절차가 빠르게 실행되어야 하며, 팀은 10,000개 이상의 어서션을 1분 내에 완료하도록 최적화
- 고도 병렬화, 강한 격리, 서드파티 호출 캐싱 레이어를 통해 속도 확보
-
Ephemeral:
new-feature <name>명령으로 1~2초 내 새 환경 생성, 자동 설정 및 에이전트 실행- 수동 설정이 필요하면 사용 빈도가 급감하므로, 완전 자동화가 핵심
-
Concurrent: 여러 개발 환경을 동시에 실행할 수 있도록 포트, DB, 캐시 등 충돌 방지 설정 필요
- Docker를 활용하거나 환경 변수 기반으로 격리 구성
엔드투엔드 타입 시스템과 자동화된 품질 관리
- 가능한 많은 모범 사례를 자동화해 LLM의 자유도를 줄이고, 일관된 품질을 유지
- 자동 린터와 포매터를 엄격히 설정해, LLM이 작업을 마칠 때마다 자동 수정 적용
-
정적 타입 언어 사용을 권장하며, 특히 TypeScript를 중심으로 강력한 타입 시스템을 활용
-
UserId,WorkspaceSlug,SignedWebhookPayload같은 의미 있는 타입명을 통해 코드 의도를 명확히 표현
-
- OpenAPI를 통해 프론트엔드와 백엔드 간 타입 일치 유지
- Postgres의 타입 시스템과 트리거를 활용해 데이터 무결성 확보, Kysely로 타입 안전한 클라이언트 생성
- 모든 서드파티 클라이언트도 정확한 타입 정의를 갖추거나 래핑하여 사용
결론: AI 시대의 코드 품질 재정의
- 에이전트는 피로하지 않고 뛰어난 코더지만, 그 성능은 환경의 품질에 의존
- ‘좋은 코드’는 더 이상 선택이 아니라 AI가 제대로 작동하기 위한 전제 조건
- 초기 세팅은 부담처럼 느껴지지만, 이는 오랫동안 미뤄온 필수 투자
- 개발 리더십의 지원 아래, AI 친화적 코드베이스 구축을 목표로 해야 함
Hacker News 의견들
-
100% 커버리지를 달성할 때의 함정은, 코드와 테스트를 같은 에이전트가 작성하면 자기모순적 검증에 빠질 수 있다는 점임
에이전트가 잘못된 로직을 만들고 그걸 검증하는 테스트도 잘못 작성하면, 테스트는 통과하지만 실제로는 오류가 있는 코드가 됨
이런 커버리지는 코드보다 테스트가 먼저 작성되거나, 사람이 엄격히 검증할 때만 의미가 있음
그렇지 않으면 단지 환상의 신뢰성을 만들어내는 것에 불과함- 네 말이 맞지만, 해결책은 단순히 “사람이 하자”나 “코드 전에 테스트를 쓰자”가 아님
여러 다른 사고방식의 사람들이 서로의 맹점을 검증하는 게 핵심임
AI 모델이 여러 개라도 결국 하나의 ‘마음’으로 취급해야 함
사람 코드에 AI 테스트, AI 코드에 사람 테스트, 혹은 서로 코드 리뷰하는 식이 좋음
다만 인간 사이에서도 권력 관계 때문에 한 사람의 의견만 반영되는 경우가 있어, AI가 그걸 막아주진 않음 - 그래서 테스트를 테스트하는 것이 필요함
일부러 버그를 넣고 실패하는지 확인해야 함
이건 AI만의 문제가 아니라 사람도 마찬가지임
그래도 AI 덕분에 많은 개발자들이 제대로 된 엔지니어링 원칙을 배우게 된 건 좋은 일임 - 100% 커버리지가 아니라 100% MC/DC 커버리지에서 변화가 일어나는 것 같음
SQLite나 항공 소프트웨어가 이런 수준을 목표로 함
다만 이건 아직 학술적으로 검증된 가설은 아님 - 사람 손으로 쓴 단위 테스트도 같은 문제를 가짐
그래서 통합 테스트나 UI 자동화 테스트로 실제 사용자 시나리오를 검증해야 함
운영 환경에서 가져온 데이터나 그림자 환경에서의 테스트도 도움이 됨 - 이미 BDD나 Acceptance Test 같은 좋은 코드 기반 해결책이 있음
LLM 이전에는 설정이 번거로웠지만 지금은 ROI가 좋아졌음
Uncle Bob이 강조했듯 테스트 구조화에 투자하는 게 중요함
LLM은 반복적인 테스트를 쓰지만, 요청하면 DRY 원칙이나 팩토리 패턴도 잘 적용함
- 네 말이 맞지만, 해결책은 단순히 “사람이 하자”나 “코드 전에 테스트를 쓰자”가 아님
-
어제부터 시도 중인 방법인데, TLA+/PlusCal로 스펙을 먼저 작성하고 Codex에게 그 스펙을 그대로 구현하게 함
창의성 없이 스펙에만 충실하게 하라고 지시함
결과 코드는 못생겼지만 정확함, 그리고 직접 번역하는 것보다 훨씬 빠름
다만 최적화가 부족하거나 너무 지저분할 때는 일부 수정함
특히 락 없는 자료구조를 실험 중인데, Codex는 여전히 락을 쓰려 해서 직접 교정해야 함
결국 나는 수학적 논리에 집중하고, AI는 구현 세부를 맡는 식으로 일함
이게 바로 “명세 먼저, 코드 나중”의 이상적인 흐름임- 나도 비슷하게 개발하고 있음
Martin Kleppmann의 글에 공감함 - 최근 Haskell이나 Prolog로 반복을 시도해봤는데, LLM과 모델링/검증을 함께 연구할 그룹이 있으면 좋겠음
- LLM이 스펙 작성에도 참여하게 하면 효과가 커짐
최신 모델에서는 이게 실제로 잘 작동하고, 비용 효율성도 10~100배 좋아졌음
- 나도 비슷하게 개발하고 있음
-
이건 환각이거나 세일즈 피치 같음
실제 운영 버그와 유지보수 부담이 좋은 코드를 강제하지 못한다면, AI도 못함
지금 수준의 AI는 오히려 코드를 더 나쁘게 만들 가능성이 큼- “좋은 코드가 뭔지 모두 알고 있다”는 전제가 문제임
메서드 길이조차 합의가 안 된 상황에서 보편적 품질 기준은 존재하지 않음
테스트 커버리지 같은 지표도 쉽게 조작 가능하고, 잘못 적용하면 오히려 해로움 - 테스트 커버리지는 좋은 코드의 대체재가 아님
특히 AI가 테스트를 작성할 때는 거짓된 자신감을 줄 수 있음 - 원글 작성자가 AI 회사 CEO라서 편향이 있을 수도 있음 /s
- “좋은 코드가 뭔지 모두 알고 있다”는 전제가 문제임
-
나는 소프트웨어 개발이 LLM의 유일한 실질적 응용 분야일 수 있다고 생각함
다른 분야보다 피드백 루프를 빠르게 만들 수 있음
LLM과 계획을 세우고 몇 시간 후 실패를 확인하면, LLM이 “그래서 그렇게 하면 안 된다”고 말함
마치 미국식 전기 규격으로 집을 짓다가 캐나다식 식기세척기를 설치할 때 문제를 발견하는 것과 같음- 그래서 다른 공학 분야는 엄격한 규칙과 자격 제도가 있음
소프트웨어는 상대적으로 안전해서 익명 개발이 가능했지만, 이제 책임 있는 서명 문화가 생기고 있음
앞으로는 고위험·혁신적 코드를 짜는 사람만 높은 보수를 받을지도 모름 - 그런데 왜 그런 경험이 LLM이 유용하다는 결론으로 이어지는지 모르겠음
AI가 계속 엉뚱한 코드를 내고, 우리가 디버깅하고, 또 다른 엉뚱한 걸 내는 무한 루프에 빠질 뿐임 - 캐나다식 식기세척기도 설치는 가능함
다만 전류 규격만 맞추면 안전함 - 시뮬레이터나 디지털 트윈을 생각하면 현실 구축 없이도 피드백 루프를 만들 수 있음
그래도 나는 단위 테스트로 현실 접점을 확인하는 게 다행이라 생각함 - “소프트웨어 외엔 실질적 응용이 없다”는 건 오만한 주장임
나는 LLM으로 RLC 회로와 inerter를 공부하고 있음
- 그래서 다른 공학 분야는 엄격한 규칙과 자격 제도가 있음
-
많은 사람이 LLM이 빠르게 코드를 생성하는 걸 보고 놀라지만, 속도나 양은 품질의 병목이 아님
AI가 인간보다 정확한 코드를 만들 때 진짜 혁신이 일어날 것임- LLM을 쓰면 엔지니어가 시스템의 실제 구현 이해에서 멀어짐
진짜 가치는 코드가 어떻게 작동하는지 아는 것에서 나옴
회의 중에 추측만 하던 엔지니어들 사이에서, 한 명이 실제 코드를 열어 보여주는 순간이 가장 가치 있음
- LLM을 쓰면 엔지니어가 시스템의 실제 구현 이해에서 멀어짐
-
‘좋은 코드’란 어쩌면 인간의 한정된 작업 기억에 맞춰 최적화된 코드일지도 모름
모델은 모든 문맥을 한 번에 볼 수 있으니 그런 제약이 없음
컨텍스트 윈도우가 100배 커지면 이런 논의가 덜 중요해질 수도 있음 -
LLM에게 100% 커버리지를 요구하면 잘못된 가정이 고착화될까 걱정됨
그래도 사람의 리뷰가 있다면 “이건 틀렸으니 테스트를 지우고 다시 작성하자”고 할 수 있겠지?- 맞음, 여전히 사람이 테스트 케이스를 검토함
LLM이 인터뷰하듯 PRD를 함께 작성해서 범위와 기대치를 명확히 함 - 실제로 LLM은 “1=1인가?” 같은 무의미한 테스트를 많이 만듦
- 맞음, 여전히 사람이 테스트 케이스를 검토함
-
“베스트 프랙티스”는 기술 환경에 따라 달라짐
코드 작성이 쉬워진 지금은 100% 커버리지가 LLM에게 더 유용할 수 있음
테스트는 LLM에게 명확한 목표를 주고, 이후 상호작용을 더 안전하게 만듦- 코드가 장기간 진화하는 시스템에서는 테스트가 생명선임
각 테스트가 과거 버그 티켓을 참조하며, 수정이 유지되는 걸 보장함 - “베스트 프랙티스”는 구현이 달라도 패턴이 유사함
LLM에게 시나리오를 주면 대부분 비슷한 품질의 코드를 생성함
창의적 예술과 달리, 소프트웨어는 자동화에 특화된 산업임
- 코드가 장기간 진화하는 시스템에서는 테스트가 생명선임
-
글을 보고 “AI가 효과적이려면 우리가 좋은 코드를 써야 한다”는 내용일 줄 알았음
실제로 Claude는 불명확한 변수명이나 비논리적 코드에서 자주 실수함
변수명이 “iteration_count”인데 합계를 담고 있으면 AI가 속음
결국 깔끔한 코드가 AI와 인간 모두에게 도움이 됨- AI 덕분에 팀이 문서화와 주석 관리에 신경을 쓰게 됨
AI가 내부 문서를 학습 자원으로 쓰기 때문에, 이제 업데이트된 문서가 필수로 여겨짐
예전엔 우선순위가 낮았지만, 지금은 모델 품질에 직접 영향을 주기 때문임 - 인간은 한 번 본 코드의 맥락을 기억하지만, AI는 세션마다 새로 학습해야 함
다만 시간이 지나면 이 부분도 개선될 것임 - 효과적인 방법은 메서드 시그니처와 주석으로 의도와 로직을 명확히 적는 것임
그러면 LLM이 한 번에 정확히 구현할 확률이 높음
- AI 덕분에 팀이 문서화와 주석 관리에 신경을 쓰게 됨
-
이 글은 프롬프트 회사들의 얕은 엔지니어링 이해를 드러냄
100% 커버리지는 모든 입력 조합을 검증하지 못함
단지 몇 가지 예시로 모든 라인을 실행했을 뿐임
결국 형식적 증명이 필요한데, 그건 비용이 천문학적이고 LLM은 쓸모없음- 그럼 해결책은 뭔가? 시니어가 PR 보고 “LGTM” 하는 건 감정 테스트에 불과함
오히려 테스트로 반응형 개발 환경을 만드는 게 새로운 황금기를 열 수 있음
커버리지에 문제가 생기면 나중에 확장하면 됨
처음부터 가능한 한 철저히 테스트를 세팅하는 게 좋음 - LLM이 형식 검증에 쓸모없다는 건 과한 주장임
이미 proof assistant와 연결해 쓰는 시도가 많음
사양에 약간의 오류가 있어도 대부분 쓸 만한 결과를 냄
- 그럼 해결책은 뭔가? 시니어가 PR 보고 “LGTM” 하는 건 감정 테스트에 불과함