Yunseon Hong

archive / / #개발

좋은 코드와 지속 가능한 소프트웨어 - 스타트업 세 곳을 지나며

egg · 3분 읽기

MVP 단계에서는 클린 코드보다 출시 속도가 먼저였다. AI가 구현까지 하는 지금도 사람이 읽기 쉬운 코드가 필요하다고 보는 이유와, 처음부터 테스트 전략을 정해야 한다고 생각하게 된 이유를 남긴다.

스타트업 세 곳을 거치면서 ‘좋은 코드’와 ‘지속 가능한 소프트웨어’에 관해 생각할 때가 종종 있다. 정답을 찾았다기보다는 해보면서 느낀 걸 정리해두고 싶어서 글을 남긴다.

MVP 단계의 현실

사실 아이디어를 구현하는 단계에서는 디자인 패턴이나 클린 코드 같은, 소위 말하는 좋은 코드를 지향하기 어려웠다. 기획이나 정책이 수시로 바뀌고 팀도 많아야 서너 명인 상황에 조금은 과한 느낌이 들었다.

그래서 정한 건 최소한의 코딩 컨벤션 정도였다.

  • Linter와 Formatter 설정
  • 네이밍 컨벤션
  • 디렉터리 구조

나머지는 구현에 급급했다. 지금 돌아보면 그 판단이 틀렸다고는 생각하지 않는다. 다만 그때 같이 정했어야 했던 게 하나 빠져 있었다. 이건 뒤에서.

AI가 구현하는 시대에도 사람이 읽어야 할까

요즘은 AI가 코드를 직접 짜고 고치기까지 한다. 이런 상황에서 사람이 읽기 쉬운 코드가 여전히 좋은 코드인가 하는 의문이 들긴 한다. 읽는 주체가 사람이 아니라 모델이라면 기준이 달라져야 하는 것 아닌가 싶다.

그럼에도 방향을 정하고 최종적으로 머지할지 말지 결정하는 건 결국 사람이다(물론 그마저도 AI에게 많은 부분을 맡기기는 하지만). 그 판단을 하려면 사람이 코드를 읽고, 이 코드가 왜 이렇게 동작하는지 설명할 수 있어야 한다.

그런 관점에서 좋은 코드는 비즈니스 로직의 흐름이 한눈에 따라가지는 코드인 것 같다. 함수를 너무 잘게 쪼개면 흐름을 따라가려고 여러 파일을 오가야 하고, 반대로 함수 하나에 모든 걸 몰아넣으면 God function(모든 일을 떠안은 거대한 함수)이 된다. 단일 책임 원칙을 지키면서도 추상화 수준을 적당히 맞추는 지점이 어딘가에 있다. 그 지점이 팀마다, 도메인마다 다르다는 게 문제지만..

오류를 삼키고 정상처럼 동작하거나 애매한 입력을 짐작해서 처리하는 코드도 같은 이유로 피하고 싶다. 왜 그 결과가 나왔는지 설명할 수가 없고, 문제도 가장 늦게 드러난다.

결국 테스트

지속 가능한 소프트웨어는 이 코드가 왜 이렇게 동작하는지가 사람이 바뀌어도 남아 있는 상태인 것 같다. 그걸 남길 방법을 고민하다 보면 테스트로 돌아온다. 앞에서 빠졌다고 한 게 이거다.

처음에는 TDD(테스트 주도 개발)를 해야 한다고 생각했는데, 정리해보니 내가 말하고 싶은 건 테스트를 먼저 쓰는 개발 방식 자체보다는 테스트 자동화에 가깝다. MVP라도 핵심 사용자 흐름, 다시 말해 크리티컬 패스마다 최소한의 E2E 테스트는 있어야 한다.

물론 처음에는 개발 속도가 느려진다. 결국 기능이 바뀌면서 버려지는 테스트도 생기고 유지보수 비용도 붙는다. 하지만 테스트 없이 릴리스하는 쪽의 위험이 훨씬 클 것이다.

테스트 자동화 없이 가면 무엇이 깨지면 안 되는지가 사람 머릿속에만 남고, 어느 순간 개발보다 수동 회귀 테스트에 드는 시간이 더 길어진다. 사람이 손으로 확인하다 보면 빠뜨리는 케이스가 생기고 그게 회귀 버그로 운영 환경에 나간다. 초반에 수없이 겪었다.

그래서 테스트 전략은 프로젝트 초기에 코딩 컨벤션을 정할 때 같이 정해야 한다고 생각한다. 어떤 흐름을 E2E로 묶을지, CI에서 무엇이 깨지면 배포를 막을지 정도만이라도.

AI가 테스트 비용을 낮춰준다

다행히 이 비용은 예전보다 많이 줄었다. 반복적인 테스트 케이스는 AI가 꽤 잘 만들어주고 경계값이나 예외 케이스까지 웬만큼 커버한다.

다만 무엇을 검증해야 하는지, 즉 기대 동작을 정하는 건 여전히 사람 몫. 테스트 코드를 AI가 쓰더라도 어떤 흐름이 깨지면 안 되는지는 사람이 알고 있어야 한다. 그러고 보면 앞의 이야기, 사람이 읽을 수 있는 코드가 필요하다는 것과 같은 얘기인 듯 싶다.

OpenSpec

그래서 요즘은 OpenSpec으로 스펙을 먼저 적고 구현을 맡긴다.

사실 거창할 건 없다. 바꾸려는 동작을 요구사항과 시나리오로 적어두기만 하면, 그게 AI가 구현할 기준이 되고 테스트 케이스의 뼈대가 된다. 몇 달 뒤 왜 이렇게 동작하는지를 코드가 아니라 문서에서 찾을 수 있다는 것도 생각보다 컸다.

테스트에 기대 동작이, 스펙에 그 이유가 남아 있으면 AI가 코드를 다시 써도 소프트웨어는 계속 고쳐 나갈 수 있다.

이제는 무엇을 시작하든 컨벤션과 테스트 전략, 스펙 문서를 같이 깔고 들어간다. 솔직히 아직은 테스트 쓰는 시간이 아깝게 느껴지는 날이 더 많다. 그래도 릴리스 전날 손으로 회귀 테스트를 돌리던 때를 떠올리면..

shareXFacebookLinkedIn

keep reading

datepostcategory
RedactCheck를 6주 만에 접었다#개발
Claude Code auto 모드 - 하루에 여덟 번 막혔다#개발
Claude Code 세션 간 메시징 정리#개발