9.8.2. 함수 길이, 중첩 깊이(Nesting Depth) 등 물리적 지표 제한
앞선 그래프 이론 기반의 9.8.1절 순환 복잡도(Cyclomatic Complexity)가 코드의 내부적인 논리가 얼마나 징그럽게 꼬여있는지를 철저히 측정한다면, 린터(Linter) 기반의 **물리적 지표(Physical Metrics)**는 코드가 개발자의 텍스트 에디터(IDE) 모니터 인터페이스 위에서 렌더링될 때, 인간의 나약한 시각과 워킹 메모리(Working Memory) 안에서 얼마나 혐오스럽게 보이는지를 직관적으로 측정한다.
거대 언어 모델(LLM)은 모니터 화면의 스크롤 제약을 받지 않는 무한한 컨텍스트 윈도우 위에서 살아가는 순수 연산의 기계다. 따라서 AI는 하나의 거대한 클래스 메서드 안에 500줄의 스파게티 구문을 한꺼번에 떡 지어 채워 넣거나, 코딩 테스트 초보자처럼 자바스크립트의 콜백(Callback) 지옥과 같이 if 블록을 5단계, 6단계씩 파고 들어가는 V자 형태의 추악한 화살표 안티 패턴(Arrow Anti-pattern) 코드를 작성하는 데 전혀 미적 거부감이나 피로도를 느끼지 않는다.
하지만 운영(Ops)을 책임지는 인간 주니어/시니어 개발자는 대개 27인치 모니터 한 화면에 들어오는 40~50줄을 넘어가거나, IDE 탭(Tab) 들여쓰기가 3번 이상 중첩되면 코드를 한눈에 파악하기 위한 인지 부하 오버플로우(Cognitive Overload)를 겪으며 워킹 메모리가 완전히 마비된다.
결국 지속 가능한 엔터프라이즈의 오라클 시스템은, 기계의 그 무한하고 흉측한 텍스트 컨텍스트 생성 능력을 철저히 통제하여 인간 개발자의 물리적이고 시각적인 인지 한계치에 맞추어 강제로 하향 평준화(Downward Leveling)시키는 가혹한 시각적 규제를 CI/CD 단에서 가해야만 한다.
1. 하드코어 물리적 지표의 종류와 측정 도구 연동
클린 코드(Clean Code) 철학을 주입받은 정적 분석 파이프라인(예: 파이썬의 Black/Pylint, 자바의 Checkstyle, 노드의 ESLint, 고 언어의 Golint)은 AST(추상 구문 트리)를 빠르게 순회하면서, 0초 만에 다음과 같은 물리적인 오프셋(Offset) 지표들을 무자비하게 수집하고 설정된 임계치(Threshold) 폭발 여부를 감시한다.
- [함수 수직 길이 (Line of Code, LOC)]: 함수 혹은 메서드 하나가 텍스트 버퍼에서 차지하는 총 수직 라인 수. 엔터프라이즈의 엄격한 오라클은 보통 **최대 40~50줄(Max Lines: 50)**을 절대적인 한계치로 설정한다. (조금 더 정밀한 오라클 시스템은 의미 없는 공백과 멍청한 주석을 제외한 실제 동작 코드 슬록인 Source Lines of Code, SLOC를 기준으로 삼아 AI의 주석 변명을 차단한다).
- [수평 중첩 깊이 (Nesting Depth)]:
if,for,while,try-catch등의 제어류 블록이 우측 탭 방향으로 내부를 파고들어 가는 인덴테이션(Indentation)의 최대 깊이. 깊이가 4 이상이 되면 코드는 거대한 V자 형태 화살표 장벽이 되며 가독성이 수직으로 하락하여 이른바 ‘운명의 피라미드(Pyramid of Doom)’ 안티 패턴에 빠진다. 오라클은 통상적으로 **Max Depth: 3**으로 철저히 틀어막는다. - [파라미터 개수 오버로드 (Number of Parameters)]: 단일 함수 시그니처가 받아내는 선언 인자(Argument)의 개수. 4개를 초과(Max Params: 4)하면 클린 코드(Clean Code) 원칙에 정면으로 위배되는 인자 폭발(Parameter Explosion)로 간주한다.
2. 조기 반환(Early Return) 패턴의 활성화를 통한 Nesting 철퇴
이 물리적 통제 중에서도 특히 수평 들여쓰기인 중첩 깊이(Nesting Depth) 오라클 규제는, 엉망진창인 AI의 코드 생성 퀄리티를 전문가 수준으로 비약적으로 상승시키는 마법의 채찍이다.
만약 LLM이 5단계의 깊숙하고 더러운 중첩 if 블록을 가진 인증 코드를 PR로 제출하여, 파이프라인 정적 분석 오라클의 Nesting Depth Limit(Max: 3) 에러(Fail)를 유발했다고 가정하자. 오라클 미들웨어가 봇(Bot)을 통해 발송하는 분노어린 수정 프롬프트는 다음과 같이 구체적으로 구성되어 날아간다.
“[Readability Oracle Reject - Depth Constraint Exceeded] 당신이 작성한
validateUserProfile함수의 탭 중첩 깊이가 5단계에 달하여, 사내 가독성 코드 컨벤션(Max Depth 3 제한)을 정면으로 위반했습니다.Early Return(Guard Clauses)패턴을 즉시 사용하여, 논리적 조건이 부정(False)일 때 들여쓰기를 하며 내부로 중첩해 기어들어가는 대신, 1단계 뎁스에서 즉시 에러를 반환(return error)하거나 함수를 탈출하도록 거대한 V자 구조를 일자로 평탄화(Flattening)하십시오.”
이 강력한 족쇄 제약(Constraint)을 채워서 모델을 다시 돌리는 순간, AI는 자신이 뱉었던 다음과 같은 가장 멍청한 레거시 주니어 방식의 코드를:
# [AI의 최초 생성 코드 - V자 폭발 패턴]
if user_exists:
if password_match:
if is_active:
if has_permission:
execute_core_business_logic()
단숨에 아래와 같은 모던(Modern)하고 우아하며 선형적인 방어적 프로그래밍(Defensive Programming / Guard Clause) 1차원 패턴으로 스스로 뜯어고쳐(Refactoring) 메인스트림 커밋으로 복구시킨다.
# [오라클 교정 후 코드 - 평탄화 패턴]
if not user_exists: return False, "User not found"
if not password_match: return False, "Invalid password"
if not is_active: return False, "Account suspended"
if not has_permission: return False, "Unauthorized access"
execute_core_business_logic() # 깊이 0에서 안전하게 로직 실행
3. 물리적 크기 제한이 가져오는 ’아키텍처 모듈성(Modularity)’의 강제적 진화
함수의 수직 길이를 강제로 50줄 이내로 제한(Max 50 Lines Oracle)하는 린터 룰셋은 겉보기에는 화면을 예쁘게 스크롤하기 위한 단순한 시각물처럼 보이지만, 아키텍처 관점 깊은 곳에서는 무지성 LLM 에이전트에게 엄청나고 파괴적인 진화를 강요하는 트리거(Trigger)다.
자신이 짜낸 메인 로직이 50줄 이내에 물리적으로 들어가지 못해 계속해서 CI 파이프라인에서 수차례 Reject 당하며 페널티를 받는 LLM은 딜레마에 빠진다. 결국 목표 태스크를 달성하기 위해 어쩔 수 없이, 500줄짜리 뚱뚱한 메인 파싱 로직 덩어리를 parseHeaders(), validateDbConnection(), savePayloadToDisk() 등 여러 개의 작고 우아한 보조 단위 함수(Sub-routines)들로 “추출(Extract Method)” 디자인 패턴을 발동시켜 자가 분열을 시작하게 된다.
파라미터 개수가 4개를 넘길 때 에러를 뿜는 제약 또한 마찬가지다. 넘쳐나는 변수들을 함수로 옮기지 못해 쩔쩔매던 AI는 스스로 이 5개의 흩어진 원시 타입(Primitive Type) 변수들을 하나의 UserRegistrationDTOPayload라는 단일 클래스 객체(Struct) 박스 안에 묶어 조립하도록 강제된다.
즉, 결정론적 오라클이 코드의 **물리적 볼륨(Volume)을 물리 지표로 억압하는 그 단순한 행위 하나만으로도, AI는 기능의 응집도(Cohesion)를 스스로 극대화시키고 모듈 간 결합도(Coupling)를 느슨하게 낮추는 아름다운 방향으로 자신의 생성 코드를 객체지향적으로 모듈화(Modularization)**하게 되는 마법이 일어나는 것이다.
형식적이고 물리적인 인프라 한계(Boundaries) 설정은, 곧 가장 복잡한 아키텍처의 논리적 해방을 이끌어내기 위한 오라클 세계관의 가장 강력한 정적 훈련 도구이자 조련의 채찍이다.