
AI가 우리에게 '진짜 엔지니어링'을 강요하고 있습니다
AI 에이전트 도입으로 인해 그동안 미뤄왔던 테스트 커버리지, 명확한 파일 구조, 독립적 개발 환경 등 기본 엔지니어링의 중요성이 생존의 문제가 된 변화를 공유합니다.
송찬영
CTO

안녕하세요. 풀링포레스트 CTO 송찬영입니다.
솔직히 고백하자면, 우리 개발자들은 모두 알고 있었습니다. 무엇이 '좋은 코드'인지 말이죠. 철저한 테스트, 명확한 문서화, 잘게 쪼개진 모듈, 완벽한 타입 정의, 그리고 언제든 버튼 하나로 띄울 수 있는 개발 환경 같은 것들입니다. 하지만 현실이라는 핑계로, 혹은 시간 압박이라는 이유로 우리는 이 원칙들과 타협하곤 했습니다. "이건 나중에 고치자", "테스트는 핵심 로직만 짜자"라며 넘어갔던 적, 저 역시 셀 수 없이 많습니다.
하지만 AI 에이전트(Agent)들을 본격적으로 실무에 도입하면서 상황이 완전히 달라졌습니다. 저는 최근 팀원들에게 농담 반 진담 반으로 이렇게 말합니다. "AI는 우리가 미뤄뒀던 엔지니어링 숙제를 검사하러 온 선생님 같다"고요.
AI 모델, 특히 코드를 작성하는 에이전트들은 자비가 없습니다. 이들은 우리가 설정해 둔 가드레일이 부실하면, 마치 오물을 밟은 채 집안 여기저기를 돌아다니는 로봇 청소기처럼 코드베이스 전체를 엉망으로 만들어버립니다. 반대로 가드레일이 단단하다면, 이들은 지치지 않고 올바른 답을 찾을 때까지 시도하는 든든한 동료가 됩니다.
풀링포레스트 팀이 AI와 공존하기 위해 '강제로' 수행해야 했던, 그리고 이제는 우리의 강력한 무기가 된 몇 가지 기술적 결정들을 공유하려 합니다.
첫 번째 충격적인 변화는 100% 코드 커버리지(Code Coverage)의 도입이었습니다.
과거에 저는 100%라는 숫자가 허상이라고 생각했습니다. 단순한 보여주기식 지표라고 여겼죠. 하지만 AI와 함께 일할 때는 이야기가 다릅니다. 커버리지가 95%라면, 나머지 5%의 불확실한 영역에서 AI가 어떤 실수를 저지를지 우리는 알 수 없습니다. 100%라는 숫자는 모호함을 없애줍니다. AI가 코드를 한 줄이라도 작성했다면, 그 코드가 의도대로 동작한다는 것을 증명하는 테스트 코드도 반드시 함께 작성해야 합니다.
이것은 버그를 박멸하겠다는 단순한 목표가 아닙니다. AI가 "이럴 것 같아요"라고 추측하는 것을 막고, 실행 가능한 예제로 자신의 코드를 증명하게 강제하는 수단입니다. 덕분에 코드 리뷰 시간도 획기적으로 줄었습니다. 리뷰어는 AI가 짠 로직뿐만 아니라, 그 로직이 어떻게 동작하는지 보여주는 테스트 케이스를 함께 볼 수 있으니까요.
두 번째는 파일 시스템을 AI를 위한 UI로 바라보는 관점입니다.
사람 개발자는 전체 구조를 머릿속에 그릴 수 있지만, LLM은 파일명과 디렉토리 구조를 통해 문맥을 파악합니다. utils/helpers.ts 같은 모호한 이름은 이제 금물입니다. 설령 내부 코드가 같더라도 billing/invoices/compute.ts처럼 구체적인 경로와 이름을 가져야 합니다. 또한, 파일은 가능한 작아야 합니다. 그래야 AI가 전체 파일을 컨텍스트 윈도우(Context Window)에 한 번에 올리고 이해할 수 있습니다. 파일 구조를 잘게 쪼개고 이름을 명확히 짓는 것, 예전엔 '깔끔한 정리' 정도의 의미였지만 이제는 'AI 성능 최적화'의 필수 조건이 되었습니다.
세 번째는 빠르고 독립적인 일회성(Ephemeral) 개발 환경입니다.
AI 에이전트에게 작업을 시키다 보면, 한 번에 여러 개의 기능을 동시에 개발하게 됩니다. 마치 양봉업자가 수많은 벌들을 관리하는 것과 비슷합니다. 이를 위해서는 new-feature 같은 명령어 하나로, 즉시 독립적인 개발 환경이 생성되어야 합니다. 데이터베이스, 포트, 캐시가 서로 충돌하지 않도록 격리되어야 하며, 무엇보다 테스트 속도가 빨라야 합니다.
저희 팀은 1만 개 이상의 Assertion이 포함된 테스트를 1분 내외로 끝내도록 최적화했습니다. 만약 테스트가 20분씩 걸린다면, AI 에이전트의 피드백 루프가 끊어지고 생산성은 곤두박질칩니다. 캐싱 레이어를 적극적으로 활용하고 동시성을 보장하는 환경 구축은 이제 선택이 아닌 생존의 문제입니다.
마지막으로 타입 시스템(TypeScript)을 통한 의사소통입니다.
AI에게 string 타입의 변수를 던져주는 것은 너무 광범위한 자유를 주는 것입니다. UserId, WorkspaceSlug처럼 의미가 담긴 타입 별칭(Type Alias)을 사용해야 합니다. 이는 AI에게 "이 데이터는 어디서 왔고, 어떻게 쓰여야 한다"는 명확한 가이드를 제공합니다. 타입 시스템과 린터(Linter)가 엄격할수록, AI가 탐색해야 할 불필요한 공간이 줄어들고 정답에 도달할 확률이 높아집니다.
결국 AI 시대는 우리에게 더 게을러질 기회를 주는 것이 아니라, 더 철저한 엔지니어가 되기를 요구하고 있습니다. 역설적이게도 AI를 잘 활용하려면, 인간이 기계보다 더 논리적이고 체계적인 구조를 먼저 닦아놓아야 합니다.
처음에는 이 모든 과정이 번거롭고 막막하게 느껴졌습니다. 하지만 이제는 확신합니다. AI가 강요한 이 '좋은 습관'들이, 결국 우리 팀의 소프트웨어 품질을 근본적으로 끌어올렸다는 것을요. 지금 여러분의 코드베이스는 AI를 맞이할 준비가 되어 있나요? 기본기로 돌아가기에, 지금보다 더 좋은 타이밍은 없습니다.


