
AI 시대이기 때문에 더욱 사양과 설계가 필요하다고 생각한다
요약
AI로 인해 구현 비용이 낮아지면서 사양과 설계의 중요성이 간과되고 있습니다. 하지만 설계 없는 개발은 시스템의 복잡도를 높이고 유지보수를 불가능하게 만듭니다. '동작하는 것'과 '올바른 것'의 차이를 이해하고 사양과 설계를 정의해야 합니다.
핵심 포인트
- AI 시대에도 사양과 설계는 시스템의 올바름을 보증하는 필수 요소임
- 구현 비용 하락이 설계 생략의 정당성을 부여하지 않음
- 사양은 외부와의 계약이며, 설계는 사양을 만족하기 위한 구조와 기준임
- 설계가 없으면 시스템의 영향 범위를 파악할 수 없고 기능이 난립함
AI를 사용하면, 모호한 지시로부터도 동작하는 코드를 얻을 수 있다.
이것은 사실이며, 개발 속도는 확실히 올라갔다.
하지만, 어떤 현장에서의 경험이 머릿속을 떠나지 않는다.
사용자의 요구를 충실히 구현해 온 결과, 시스템은 비대해지고, 기능이 난립하며, 최종적으로 "이것은 올바르게 동작하고 있는가"를 아무도 판단할 수 없게 되었다.
코드는 동작하고 있다.
테스트도 통과하고 있다.
하지만, 무엇을 달성하려고 했는지 보이지 않는다.
원인은 AI가 아니라, 사양 (Specification)이 없었다는 것이다.
이 기사는, AI 시대에도 사양과 설계는 필요하다는 개인적인 생각을 정리한 것이다.
전제로, 개발의 비용 구조가 바뀌고 있다.
기존의 개발에서는 구현 비용이 높았다.
그렇기에 사전에 요구사항이나 설계를 굳히는 것에는 경제적인 합리성이 있었다.
- 요구사항을 굳힌다
- 사양을 결정한다
- 설계를 다듬는다
- 구현한다
- 시험한다
이 순서는 단순한 형식이 아니다.
재작업 (rework) 비용이 크기 때문에, 전 공정에 투자했던 것이다.
AI의 등장으로, 이 전제는 상당히 바뀌었다.
시행착오의 비용이 낮아져, "우선 만들어 보고, 동작하는 것을 보면서 고친다"라는 진행 방식이 성립하기 쉬워졌다.
결과적으로, 사양이나 설계를 사전에 정의하는 것이 "상대적으로 비용이 높은 행위"로 보이게 되었다.
다만, 여기서 한 가지 혼동이 일어나고 있다.
"생략하기 쉬워졌다"와 "생략해도 괜찮아졌다"는 별개의 문제다.
사용자로부터 "이런 기능이 필요하다"라는 요구가 온다.
AI로 코드를 생성하고, 동작하므로 릴리스한다.
다음 요구가 온다.
다시 구현한다.
이를 반복한다.
깨달았을 때는, 다음과 같은 상태가 된다.
- 파일 I/O, DB, API의 거동을 코드에서 추적하지 않으면 파악할 수 없다
- 개수를 수정하려고 하면, 영향 범위(impact range)를 알 수 없다
- "이 시스템은 외부에서 어떻게 보이는가"를 아무도 설명할 수 없다
이것은, 외부와의 계약인 사양이 코드에 매몰되어 있는 상태라고 생각한다.
문서를 업데이트하는 것보다, 코드를 고치는 것이 빠르다.
그 판단이 쌓이면, 사양은 코드 속에만 존재하게 된다.
읽으면 알 수 있을 것이다, 아마도.
하지만, 아무도 전체를 파악하고 있지 않다.
서두의 실패담의 본질은, 여기에 있었다.
사용자의 요구를 글자 그대로 실현해 왔다.
요구는 모두 정당했다.
구현도 되었다.
하지만, 시스템 전체로서 무엇을 달성해야 하는지에 대한 구조가 누구의 머릿속에도 없었다.
결과적으로 일어난 것은, 다음과 같은 일이었다.
- 목적이 중복된 기능이 난립한다
- "이것은 사양대로인가"를 판단하는 기준이 사라진다
- 테스트가 포괄적인지 아무도 보증할 수 없다
코드는 동작하고 있다.
하지만 평가할 수 없다.
"동작한다"와 "올바르다"는 별개의 질문이다.
설계가 없다면, 후자에 답할 수 없다.
나는, 사양과 설계를 다음과 같이 나누어 생각하고 있다.
| 개념 | 무엇을 쓰는 것인가 |
|---|---|
| 요구사항 (Requirements) | 무엇을 실현하고 싶은가, 왜 필요한가 |
| ... |
사양은, 외부와의 계약을 쓰는 것이라고 생각한다.
누가 무엇을 위해 사용하는지, 무엇을 입력하고, 무엇을 출력하며, 어떤 동작을 보증하는지를 쓴다.
설계는, 그 사양을 만족하기 위한 구조와 평가 기준을 쓰는 것이라고 생각한다.
어떤 책임 (responsibility)을 어디에 둘 것인지, 데이터가 어떻게 흐르는지, 무엇을 테스트해야 올바르다고 말할 수 있는지를 쓴다.
한편으로, 내부 로직을 일일이 써 내려갈 필요는 없다.
구체적인 라이브러리 사용법이나 세세한 처리 절차는, 코드에 맡기는 편이 좋을 때도 많다.
세세한 내부 로직을 쓰지 않으면 개발할 수 없다면, 책임의 분리가 모호하거나, 불필요한 기능을 앞질러 설계하고 있을 가능성이 있다.
나는, 다음과 같은 상태라면 "사양이 없다"라고 판단한다.
- 무엇을 실현하고 싶은지가 명확하지 않다
- 누가 무엇을 위해 사용하는지가 명확하지 않다
- 무엇을 입력으로 필요로 하는지가 명확하지 않다
- 무엇을 출력하는지가 명확하지 않다
- 무엇이 정상계 (happy path)인지 미정의, 또는 모호함
- 이상계 (edge case/error case)를 상정하고 있지 않음
- 성능이나 보안 등의 제약이 미확정
사양이 없는 상태에서는, 외부에서 본 거동을 설명할 수 없다.
즉, 이용자나 타 시스템에 대해 무엇을 약속하고 있는지를 알 수 없다.
이 상태에서 구현만 진행되면, 나중에 "이것은 올바른 거동인가"를 판단할 수 없게 된다.
나는, 다음과 같은 상태라면 "설계가 없다"라고 판단한다.
- 기능, DB, 파일, 외부 API와의 입출력 형식이 미정의
- 데이터의 흐름이 미정의
- 책임의 경계가 모호함
- 상태 (state)를 어디서 가질 것인지 정해지지 않음
- 무엇을 테스트해야 올바르다고 말할 수 있는지 알 수 없음
설계가 없는 상태에서는 시스템의 내부 구조를 설명할 수 없다.
즉, 사양 (specification)을 어떻게 충족하고 있는지 알 수 없다.
그 결과, 변경 시의 영향 범위 (impact scope)를 예측할 수 없게 된다.
실제로 시스템이 무너졌을 때, 가장 곤란했던 것도 바로 이 점이었다.
영향 범위를 정확히 파악할 수 없다는 것이 재작업 (rework)을 크게 만들었다.
이 부분이 핵심이라고 생각한다.
AI는 설계를 불필요하게 만든 것이 아니다.
설계를 암묵화했다.
기존에 인간이 명시적으로 수행하던 프로세스, 즉 분해 (decomposition), 추상화 (abstraction), 구조의 선택을 AI가 일부 대체하기 시작했다.
하지만 그것이 설계가 사라졌음을 의미하지는 않는다.
- 이전: 설계서나 논의 속에 설계가 기술되어 있었다
- 현재: 프롬프트 (prompt), 생성된 코드, 모델의 출력 경향에 설계가 분산되어 있다
이 변화로 인해 어떤 일이 벌어지는가.
설계 책임자가 보이지 않게 된다.
설계서가 있다면, "이 부분은 왜 이렇게 되어 있는가"라고 물을 수 있다.
하지만 프롬프트나 생성된 코드 속에 설계가 매몰되어 있다면, 그 질문을 어디로 향해야 하는가.
AI에게 "적당히 잘 만들어줘"라고 부탁할 때, "적당히 잘"의 정의는 누가 가지고 있는가.
그것이 명문화되어 있지 않다면 평가할 수 없다.
평가할 수 없다면 개선도 할 수 없다.
AI에게 맡겨도 좋은 부분은 있다.
오히려 그 부분은 적극적으로 맡겨도 된다고 생각한다.
예를 들어, 다음과 같은 부분들이다.
- 설계를 구체적인 코드로 구현하기
- 기존 코드에 맞춘 구현 안 제시하기
- 테스트 케이스 (test case)의 초안 만들기
- 모호한 요구사항에 대해 요구사항 정의를 위한 질문 던지기
특히 AI에게 질문을 받으면서 요구사항을 명확히 하는 방식은 매우 유효하다고 생각한다.
인간이 주체가 되어 AI를 벽치기 (wall-hitting, 아이디어 검증) 상대로 사용하는 형태다.
반면, 맡겨서는 안 되는 부분도 있다.
- 무엇을 만들 것인가에 대한 결정
- 어떤 품질을 보장할 것인가에 대한 결정
- 어떤 제약 사항을 우선할 것인가에 대한 판단
- 모호한 요구사항을 그대로 설계 단계까지 상세화하는 것
AI는 선택지를 제시할 수 있다.
하지만 어떤 선택지가 이 시스템에 올바른 것인지를 결정하는 것은 인간의 책임이라고 생각한다.
치밀한 사양서나 상세 설계서를 모든 공정에서 만들라는 뜻은 아니다.
다만, 최소한 이것만큼은 남겨두어야 한다고 생각한다.
-
무엇을 목적으로 하는가
-
누가 무엇을 위해 사용하는가
-
입력 (input)은 무엇인가
-
출력 (output)은 무엇인가
-
정상계 (happy path)의 동작
-
이상계 (error path)의 동작
-
외부 API, DB, 파일과의 계약 (contract)
-
성능, 가용성, 보안 등의 필수 제약 사항
-
사양을 충족하기 위해 필요한 구성 요소
-
각 구성 요소의 책임 (responsibility)
-
데이터의 흐름 (data flow)
-
상태 (state)를 어디서 가질 것인가
-
변경 시 영향을 받는 범위
-
테스트에서 무엇을 보장할 것인가
-
의도적으로 하지 않을 것
중요한 것은 사양이나 설계를 테스트로 옮길 수 있는 형태로 만드는 것이라고 생각한다.
"무엇을 목적으로 하고 있으며, 그것을 실현하기 위해 무엇이 필요한가"\n
"그 실현을 어떻게 확인할 것인가"
이 두 가지가 연결되어 있다면, 적어도 "동작은 하지만 올바른지 알 수 없는" 상태는 피하기 쉽다.
무엇이든 다 적어야 한다는 뜻은 아니다.
나는 다음과 같은 것들까지 설계서에 자세히 적을 필요는 적다고 생각한다.
- 구체적인 처리 내부의 세부 로직
- 라이브러리의 세부적인 사용법
- 구현 시점에만 의미를 갖는 코딩 방법
- 코드를 읽으면 바로 알 수 있는 국소적인 분기
이러한 것들은 구현 중에 바뀌기 쉽다.
바뀌기 쉬운 것을 너무 상세하게 적으면 문서가 금방 낡아버린다.
사양이나 설계에 남겨야 할 것은 코드보다 오래 살아남는 '판단'이라고 생각한다.
이토 모토시게 씨의 『경제를 보는 세 가지 눈』에는 "새의 눈, 벌레의 눈, 물고기의 눈"이라는 개념이 있다.1
- 새의 눈: 전체를 조망하는 관점
- 벌레의 눈: 현장의 세부를 보는 관점
- 물고기의 눈: 흐름이나 변화를 읽는 관점
이는 경제를 보기 위한 사고방식으로 소개된 것이지만, 나는 시스템 설계에도 상당히 유사한 면이 있다고 생각한다.
새의 눈은 시스템 전체를 조망하는 관점이다.
- 이 시스템은 무엇을 달성하기 위한 것인가
- 어떤 서브시스템 (subsystem)이 어떤 책임을 갖는가
- 서브시스템끼리는 어떻게 연결되는가
- 외부에서 보았을 때 무엇을 약속하고 있는가
사양이나 설계 없이 구현을 쌓아 올리면 이 관점을 잃기 쉽다.
개별 기능은 올바르게 동작하더라도, 전체적으로 무엇을 만들고 있는지 설명할 수 없게 된다.
서두에 쓴 실패도 바로 새의 눈을 잃은 상태였다.
벌레의 눈은 개별 기능이나 구현상의 제약을 보는 관점이다.
- 이 기능은 무엇을 입력으로 받는가
- 무엇을 출력하는가
- DB, 파일, 외부 API와의 경계는 어떻게 되어 있는가
- 어떤 이상계를 다룰 필요가 있는가
- 어떤 테스트로 올바름을 확인할 것인가
AI로 코드를 작성하면, 이러한 '벌레의 눈 (虫の目, 미시적 관점)'은 오히려 강화되는 경우가 많다.
국소적인 구현, 테스트, 리팩터링 (Refactoring)은 빨라진다.
하지만 벌레의 눈으로만 진행하면 국소 최적화 (Local Optimization)에 빠지게 된다.
세부 사항은 잘 만들어져 있는데, 전체적인 목적에서 벗어나게 된다.
'물고기의 눈 (魚の目, 흐름을 보는 관점)'은 흐름이나 변화를 보는 시점이다.
- 요구사항은 어느 방향으로 변할 것인가
- 어떤 사양 (Specification)은 고정해야 하고, 어떤 사양은 변할 것을 전제로 해야 하는가
- 어떤 기술 선정 (Technology Selection)이 미래의 제약 사항이 될 것인가
- 지금의 설계 (Design)는 다음 변경을 견딜 수 있는가
AI 시대에는 이 시점이 특히 중요하다고 생각한다.
구현이 빨라지면 요구사항이나 요청이 즉시 코드로 반영된다.
그 자체는 좋은 일이지만, 변화의 흐름을 읽지 않고 쌓아 올리면 어느샌가 시스템 전체가 왜곡된다.
'현재 있는 요구에 답하는 것'뿐만 아니라, '어느 방향으로 변할 것인가'를 보고 있지 않으면 설계는 금방 낡아버린다.
나에게 사양과 설계는 이 세 가지 관점을 오가기 위한 도구이기도 하다.
새의 눈 (鳥の目, 거시적 관점)으로 전체를 본다.
벌레의 눈으로 세부를 본다.
물고기의 눈으로 변화를 본다.
그중 어느 하나만으로는 시스템을 올바르게 파악할 수 없다.
현실적으로 처음부터 완전한 사양이나 설계를 만드는 것은 어렵다.
그래서 나는 다음과 같이 진행하는 것이 좋다고 생각한다.
- 대역적으로 요구사항·사양·설계를 배치한다
- 국소적으로 제약·요청·구현상의 발견을 수집한다
- 그 사이를 왕복하며 공고히 한다
위에서 '무엇을 만들어야 하는가'를 정의한다.
밑에서 '지금 보이는 제약이나 요청'을 끌어올린다.
그 사이를 AI도 사용하며 왕복한다.
한쪽만으로는 방향이 흔들린다.
요구사항이나 설계만 공고히 해도 구현상의 제약을 무시하면 탁상공론이 된다.
반대로 국소적인 요청이나 제약만을 쌓아 올려도 전체적으로 무엇을 만들고 있는지 알 수 없게 된다.
AI 시대의 개발에서는 이 왕복의 속도가 올라갔다.
그렇기에 더욱 왕복의 축이 되는 사양과 설계가 필요하다고 생각한다.
AI는 강력한 도구다.
시행착오의 비용을 낮추고, 구현 속도를 높이며, 개인의 생산성을 끌어올린다.
그 자체를 부정할 생각은 없다.
하지만, AI는 '무엇을 만들어야 하는가'를 가르쳐주지 않는다.
요구를 언어로 만드는 것.
구조를 선택하는 것.
품질을 정의하는 것.
그것은 인간이 담당해야 할 판단이라고 생각한다.
사양이 없는 시스템은 부패한다.
AI는 그 부패를 보기 어렵게 만든 채로 가속화할 때가 있다.
물어야 할 것은 '사양이 필요한가'가 아니다.
'나는 지금 무엇을 만들고 있는지 설명할 수 있는가'
그 질문에 답할 수 있도록 하기 위해, AI 시대이기 때문에 더욱 사양과 설계가 필요하다고 생각한다.
이토 모토시게(伊藤元重) 씨의 『경제를 보는 세 가지 눈』에서는 경제를 보는 관점으로 '새의 눈', '벌레의 눈', '물고기의 눈'이 소개되어 있다. 게이오 MCC의 강연 리포트에서도 이 사고방식이 소개되어 있다. https://www.keiomcc.com/magazine/report139/ ↩
AI 자동 생성 콘텐츠
본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기