DirectPath

주니어 개발자들을 위한 패턴 언어 - 복잡한 미로를 걷어내고 문제와 해결책 사이의 최단 거리를 찾는 법

The Story 1: The Maze of Indirection (Programming)

두 명의 개발자, 민수와 하나가 '사용자 이름 조회' 기능을 구현하고 있다.

민수의 설계 (The Maze): 민수는 "확장성"을 중요하게 생각했다. 그는 UserDTO를 정의하고, IUserRepository 인터페이스와 구현체, IUserService 인터페이스와 구현체를 각각 만들었다. 단순히 DB에서 이름 하나 가져오는데 5개의 파일과 10개의 메서드 호출이 얽혀 있었다. 나중에 버그가 생겼을 때, 민수는 데이터가 어디서 어떻게 변하는지 찾기 위해 수많은 파일을 넘나들며 길을 잃었다.

하나의 설계 (The Straight Line): 하나는 "명확함"을 선택했다. "지금은 복잡한 추상화가 필요 없어. 그냥 컨트롤러에서 필요한 데이터를 바로 가져오자." 하나는 불필요한 인터페이스와 추상 레이어를 걷어냈다. 입력(Request)이 들어오면 바로 데이터(DB)에 접근하여 결과(Response)를 내보내는 직선 경로를 만들었다. 코드는 단 몇 줄뿐이었고, 누가 읽어도 흐름이 한눈에 보였다. 하나는 나중에 정말로 확장이 필요할 때 레이어를 나누기로 했다.

The Story 2: The Shortcut Home (Ordinary Life)

민수와 하나는 낯선 도시에서 숙소를 찾아가고 있다.

민수의 경로 (The Official Route): 민수는 내비게이션이 알려주는 대로만 가려 한다. 내비게이션은 일방통행로와 큰 교차로를 거쳐 길게 돌아가는 경로를 안내했다. "규칙대로 가야 안전해." 민수는 수많은 신호등에 걸리고 복잡한 일방통행 표시를 확인하느라 진을 다 뺐다. 분명 바로 눈앞에 숙소 건물이 보이는데도, 민수는 차를 돌려 멀리 우회해야만 했다.

하나의 경로 (The Direct Path): 하나는 차를 세우고 지도를 직접 살폈다. "저기 골목길 하나만 지나면 바로 숙소 주차장이 나오는데?" 하나는 복잡한 우회로 대신 보행자 통로와 연결된 짧은 지름길을 택했다. 불필요한 신호 대기 없이 하나는 2분 만에 숙소에 도착했다. 목적지가 눈앞에 보일 때는 복잡한 절차보다 직선의 경로가 가장 강력한 지혜임을 하나는 알고 있었다.

Context

StrongCenter를 중심으로 기능을 구현하고 있다. CleanIsolation을 위해 의존성을 관리하려고 노력 중이다. 하지만 어느 순간부터 코드가 너무 많은 레이어와 "위임(Delegation)"으로 가득 차기 시작한다.

일상적인 상황:

당신은 지금 미래의 유령과 싸우느라, 현재의 명확함을 희생하고 있다.

Problem

과도한 간접성(Indirection)과 레이어는 시스템의 흐름을 가리고 인지 부하를 높인다.

Solution

입력에서 출력에 이르는 경로를 가리는 불필요한 레이어를 제거하고, 가능한 한 직접적으로 표현하라.

추상화는 공짜가 아니다. 그 비용을 지불할 가치가 있을 때만 도입하라.

Principle 1: Eliminate Empty Layers (깡통 레이어 제거)

단순히 다음 단계로 넘겨주기만 하는 클래스나 서비스는 과감히 삭제하라.

Principle 2: Value Clarity over "Best Practices" (관행보다 명확성)

"레이어드 아키텍처는 반드시 n계층이어야 한다"는 교과서적 원칙에 얽매이지 마라.

Principle 3: Short Feedback Path (짧은 피드백 경로)

코드의 경로가 짧을수록 TightLoop가 쉬워진다. 확인해야 할 파일이 적을수록 실수를 더 빨리 발견할 수 있다.

Principle 4: Flatten the Abstraction (추상화 납작하게 만들기)

너무 깊은 상속 구조나 중첩된 함수 호출을 경계하라. 호출이 3단계 이상 깊어진다면 그것을 하나로 합칠 수 없는지 검토하라.

Real Examples

Example 1: Implementation-only Interface

구현체가 하나뿐인데 인터페이스를 만드는 관행을 깨고, 직접 클래스를 사용한다. 나중에 정말 필요할 때 인터페이스를 추출한다.

Example 2: Data Transformation Hell

Entity를 DTO로, 다시 VO로 매번 복사하는 대신, 꼭 필요한 경우에만 최소한의 변환을 수행하여 경로를 단순화한다.

Common Pitfalls

"But I need to hide implementation!"

구현을 숨기는 목적은 변경의 영향을 줄이기 위해서다. 그런데 레이어를 너무 많이 만들어 오히려 모든 레이어를 다 고쳐야 한다면, 그것은 설계 실패다.

Fear of "Dirty" Controller

"컨트롤러에 로직이 있으면 안 돼!"라는 강박 때문에 5줄짜리 로직을 위해 새로운 서비스를 만드는 것은 과도한 간접성이다.

Connection to Other Patterns

Signs of Success

The Ultimate Insight

가장 완벽한 설계는 더 보태 것이 없을 때가 아니라, 더 뺄 것이 없을 때 완성된다. (생텍쥐페리)

추상화라는 미로를 만드느라 에너지를 낭비하지 마십시오. 문제와 해결책을 잇는 가장 짧고 투명한 길을 만드십시오. 그 길 위에서 코드는 가장 강력한 힘을 발휘합니다.


CategoryPatternLanguage CategoryProgramming CategoryDesign CategorySimplicity