TwoWorlds

주니어 개발자들을 위한 패턴 언어 - 문제 공간과 해결 공간을 분리하여 올바른 문제를 해결하는 방법

The Story: The Wrong Solution

한 주니어 개발자가 2주 동안 열심히 코딩했다. 사용자가 주문 내역을 필터링할 수 있는 복잡한 검색 기능을 만들었다. 날짜 범위, 상품 카테고리, 가격 범위, 배송 상태... 10개가 넘는 필터 옵션을 구현했다.

데모 날, 프로덕트 매니저가 말했다. "좋아 보이는데... 그런데 사용자들이 실제로 원했던 건 '지난 주문 다시 하기' 버튼이었어요."

주니어는 당황했다. "하지만 요구사항에 '주문 내역을 쉽게 찾을 수 있어야 한다'고 적혀있었어요!"

시니어 개발자가 끼어들었다. "맞아. 하지만 찾고 싶어하는지 물어봤어?"

"아니요... 바로 구현을 시작했어요. 검색 기능이 필요하다고 생각했거든요."

시니어가 고개를 끄덕였다. "이게 우리가 자주 하는 실수야. 문제를 이해하기 전에 해결책부터 생각하는 거지. 두 세계는 다른 거야."

Context

당신은 새로운 기능을 개발하고 있다. 요구사항을 받았고, 머릿속에 이미 구현 방법이 떠오른다. 코드를 어떻게 짜야 할지, 어떤 라이브러리를 쓸지, 어떤 알고리즘을 적용할지...

일상적인 상황:

당신은 해결책에 대해 생각하고 있지만, 문제를 충분히 이해하지 못했다.

Problem

많은 프로그래밍 오류는 사고 과정에서 두 관심사를 너무 일찍 섞는 데서 비롯된다:

The Premature Solution

문제를 듣자마자 해결책이 떠오른다. 이것은 경험의 표시처럼 느껴진다. "나는 이걸 어떻게 만들지 알아!" 하지만 이것은 함정이다.

요구사항: "사용자가 주문 내역을 쉽게 찾을 수 있어야 한다"

즉각적 사고:
→ 검색 기능이 필요하다
→ 필터링이 필요하다
→ 정렬이 필요하다
→ 페이징이 필요하다
→ (2주 후) 잘못된 기능 완성

Gerald Weinberg는 "Are Your Lights On?"에서 말한다: 문제가 무엇인지 정의하지 않고는, 문제를 해결할 수 없다. 하지만 우리는 정의하기 전에 해결하려 한다.

The Cost of Wrong Problems

잘못된 문제를 해결하는 것은 자원의 엄청난 낭비다:

더 나쁜 것은, 이런 일이 자주 일어난다는 것이다. 왜? 우리가 두 세계를 섞기 때문이다.

Two Worlds Confused

문제 공간 (Problem Space): 무엇을 해결할 것인가?

해결 공간 (Solution Space): 어떻게 구현할 것인가?

이 두 세계는 다른 사고 방식을 요구한다. 하지만 우리는 이것들을 섞는다:

"사용자가 주문을 찾고 싶어한다" (문제)
→ "검색 기능을 만들자" (해결책)
→ "Elasticsearch를 쓰자" (구현)
→ "어떻게 인덱싱하지?" (세부사항)

문제 공간을 떠나기가 너무 빨랐다!

Solution

문제 공간을 충분히 탐색하라. 그다음에 해결 공간으로 이동하라. 두 세계를 의식적으로 분리하면, 더 나은 해결책을 찾고, 종종 더 간단한 해결책을 찾는다.

Principle 1: Stay in Problem Space Longer

해결책을 생각하고 싶은 충동을 억제하라. 문제 공간에 머물면서 깊이 탐색하라.

질문하라 - George Polya의 접근:

예시:

요구사항: "주문 내역을 쉽게 찾을 수 있어야 한다"

문제 공간 탐색:
Q: 사용자가 왜 주문 내역을 찾는가?
A: 같은 것을 다시 주문하고 싶어서

Q: 모든 주문을 검색해야 하는가?
A: 아니, 주로 최근 3개월 내 주문만

Q: 어떤 정보로 찾는가?
A: 대부분 "지난번에 뭘 샀더라?"

진짜 문제: 반복 주문을 쉽게 하고 싶다
→ 복잡한 검색 기능이 아니라 "다시 주문하기" 버튼!

깊은 탐색은 눈을 뜬다. 원래 생각했던 것보다 훨씬 간단한 해결책으로 이어질 수 있다.

Principle 2: Define Before Solving

Weinberg의 교훈: 문제 정의가 해결의 절반이다.

명확한 문제 정의:

// 애매한 정의
"검색 기능이 필요하다"

// 명확한 정의
현재: 사용자가 자주 주문하는 상품을 다시 찾기 어려움
원하는: 이전 주문을 2클릭 이내에 재주문 가능
간격: 주문 이력 탐색과 재주문의 마찰
중요성: 반복 구매가 매출의 40%

명확한 정의는 해결책을 자연스럽게 제안한다.

Principle 3: Separate Thinking Modes

의식적으로 두 모드 사이를 전환하라:

문제 모드 (Why & What):

해결 모드 (How):

중요: 한 번에 하나의 모드만 사용하라. 섞지 마라.

// ❌ BAD: 두 모드가 섞임
"사용자가 주문을 찾고 싶어한다 (문제)
 → 검색을 구현하려면 (해결)
 → 근데 왜 찾지? (문제)
 → Elasticsearch가 좋을까? (해결)"

// ✅ GOOD: 분리된 사고
[문제 모드]
"왜 주문을 찾는가? → 재주문
 어떤 주문? → 최근 주문
 진짜 필요: 빠른 재주문"

[전환]

[해결 모드]
"최근 주문 리스트 + 재주문 버튼
 API: GET /recent-orders
 UI: 간단한 목록 + 버튼"

Principle 4: Maximize Work Not Done

Agile 원칙: 단순함은 본질적이다 - 하지 않아도 되는 일을 최대화하라.

문제 공간을 깊이 탐색하면, 종종 발견한다:

원래 계획:
- 복잡한 검색 UI (3일)
- 필터링 로직 (2일)
- 정렬 기능 (1일)
- 페이징 (1일)
- 검색 최적화 (2일)
총: 9일

문제 탐색 후:
- "다시 주문하기" 버튼
- 최근 5개 주문 목록
총: 0.5일

'''8.5일의 일을 하지 않았다!'''

이것이 진정한 효율이다: 올바른 문제를 해결하는 것.

Practical Patterns

Pattern 1: The Five Whys

Toyota의 기법: 문제의 근본 원인을 찾기 위해 "왜?"를 5번 물어라.

문제: 배포가 자주 실패한다

왜? → 테스트가 깨진다
왜? → 환경 설정이 다르다
왜? → 개발 환경과 운영 환경의 설정이 다르다
왜? → 설정을 수동으로 관리한다
왜? → 설정 관리 도구가 없다

진짜 문제: 설정 관리
해결책: 복잡한 배포 파이프라인이 아니라, 설정 관리 도구!

Pattern 2: Problem Statement Template

명확한 문제 정의를 위한 템플릿:

[누가]의 [어떤 상황]에서
[현재 문제]가 발생한다.
이것은 [어떤 영향]을 미친다.
[원하는 결과]를 달성하고 싶다.

예시:

자주 구매하는 고객의 재주문 상황에서
이전 주문을 찾기 위해 주문 이력을 스크롤해야 하는 문제가 발생한다.
이것은 재주문 포기와 불만을 미친다.
2클릭 이내에 재주문을 완료하고 싶다.

이제 해결책이 명확하다: 빠른 재주문 버튼!

Pattern 3: Solution Space Exploration

문제를 이해한 후, 해결 공간에서 여러 옵션을 탐색하라:

문제 정의: 빠른 재주문 (확정)

해결 옵션들:
1. 최근 주문 + 재주문 버튼 (간단, 빠름)
2. 자주 구매한 상품 추천 (복잡, 머신러닝)
3. 원클릭 재주문 (간단, 하지만 실수 위험)
4. 장바구니에 담기 (기존 플로우 활용)

각 옵션의 트레이드오프를 고려하여 선택

문제가 명확하면, 올바른 해결책을 비교할 수 있다.

Common Pitfalls

"But I Know the Solution!"

경험이 많아질수록, 패턴을 빨리 인식한다. 이것은 좋지만, 함정이기도 하다.

당신이 해결책을 "안다"고 생각할 때, 정말 문제를 이해했는가?

5분만 투자해서 문제를 확인하라. 가끔은 당신이 생각한 것과 다른 문제다.

"We Need to Move Fast!"

"빨리 만들어야 해!" - 그래서 문제 탐색을 건너뛴다.

하지만 잘못된 것을 빨리 만드는 것은 더 느리다:

올바른 방향으로 천천히 가는 것이 잘못된 방향으로 빨리 가는 것보다 빠르다.

"The Requirements Are Clear!"

요구사항 문서가 명확해 보인다. 하지만:

문서가 있어도, 대화하라. 질문하라. 확인하라.

Connection to Other Patterns

WorkingFirst - 문제를 이해한 후, 가장 간단한 작동하는 해결책부터 시작하라. 완벽한 해결책을 설계하려 하지 마라. 순차 관계

StrongCenter - 문제의 핵심을 파악하는 것은 시스템의 강한 중심을 찾는 것과 같다. 주변부가 아닌 핵심부터. 같은 원리

DataAsFoundation - 문제 공간을 탐색하면, 종종 올바른 데이터 구조가 보인다. 문제가 명확하면 데이터 설계도 명확해진다. 자연스러운 발전

PatternHunting - 문제의 본질을 이해하면, 유사한 문제의 패턴을 인식할 수 있다. 기반

DetectiveWork - 버그도 문제다. 표면적 증상 대신 근본 원인을 찾는 것은 문제 공간 탐색이다. 같은 사고방식

TinyExperiment - 문제가 불명확하면, 작은 실험으로 문제를 명확히 하라. 문제 탐색 도구

CognitiveMicroscope - 자신이 문제 공간에 있는지 해결 공간에 있는지 관찰하라. 두 모드를 의식적으로 전환하는 것도 메타인지다. 인지적 도구

Signs of Success

TwoWorlds를 효과적으로 사용하고 있다는 신호:

For Teachers and Mentors

주니어가 바로 구현을 시작하려 할 때:

멈추게 하라: "잠깐, 코딩 전에... 이 문제를 설명해줄 수 있어?"

질문하라:

구분하게 하라: "지금 우리가 문제에 대해 이야기하는 건지, 해결책에 대해 이야기하는 건지 구분해보자."

연습하라: 매 작업마다, 문제 공간과 해결 공간을 명시적으로 구분하는 습관을 만들어라.

The Ultimate Insight

Polya가 말했다: 문제를 이해하는 것이 절반이다.

Weinberg가 말했다: 올바른 문제를 정의하지 않으면, 올바른 해결책을 찾을 수 없다.

Agile이 말한다: 단순함은 본질적이다 - 하지 않아도 되는 일을 최대화하라.

이 모든 지혜는 같은 진리를 가리킨다:

문제 공간에서 시간을 쓰는 것은 투자다.
해결 공간에서 잘못된 것을 만드는 것은 낭비다.

두 세계를 분리하라. 문제를 충분히 탐색하고, 그다음에 해결책을 만들어라. 이것은 단순히 시간을 절약하는 것이 아니다. 올바른 것을 만드는 것이다.

그리고 올바른 것을 만드는 것이 프로그래밍의 본질이다.


CategoryPatternLanguage CategoryProgramming CategoryProblemSolving CategoryDesign