|
Size: 14202
Comment:
|
← Revision 6 as of 2025-12-30 09:06:26 ⇥
Size: 9174
Comment:
|
| Deletions are marked like this. | Additions are marked like this. |
| Line 10: | Line 10: |
| == The Story: The Wrong Solution == | == The Story 1: The Wrong Search Engine (Programming) == |
| Line 12: | Line 12: |
| 한 주니어 개발자가 2주 동안 열심히 코딩했다. 사용자가 주문 내역을 필터링할 수 있는 복잡한 검색 기능을 만들었다. 날짜 범위, 상품 카테고리, 가격 범위, 배송 상태... 10개가 넘는 필터 옵션을 구현했다. | 두 명의 개발자, 민수와 하나가 '주문 내역 조회' 기능을 개발하고 있다. |
| Line 14: | Line 14: |
| 데모 날, 프로덕트 매니저가 말했다. "좋아 보이는데... 그런데 사용자들이 실제로 원했던 건 '지난 주문 다시 하기' 버튼이었어요." | '''민수의 접근 (The Premature Solution):''' 민수는 요구사항을 듣자마자 구현을 시작했다. "주문 내역을 쉽게 찾아야 하니까 강력한 검색 엔진이 필요해." 그는 2주 동안 엘라스틱서치(Elasticsearch)를 연동하고 10개가 넘는 복잡한 필터링 옵션을 구현했다. 하지만 데모 날, 사용자의 피드백은 예상 밖이었다. "우리는 복잡한 검색을 원한 게 아니라, 그냥 '지난번 샀던 거 다시 주문하기' 버튼 하나가 필요했어요." 민수는 해결 공간에 너무 빨리 뛰어든 나머지, 잘못된 문제를 해결하고 말았다. |
| Line 16: | Line 17: |
| 주니어는 당황했다. "하지만 요구사항에 '주문 내역을 쉽게 찾을 수 있어야 한다'고 적혀있었어요!" | '''하나의 접근 (The Problem Explorer):''' 하나는 코딩 전에 사용자에게 물었다. "왜 주문 내역을 찾고 싶어 하시나요?" (문제 공간 탐색) "대부분 지난번에 샀던 비품을 다시 주문하려는데, 품목 이름을 잊어버려서 그래요." 하나는 진짜 문제를 발견했다. 그녀는 복잡한 검색 기능을 만드는 대신, '최근 주문 목록'과 '재주문 버튼'을 만들었다. 하나는 단 하루 만에 사용자를 만족시켰다. 문제 공간을 충분히 이해하는 것이 가장 빠른 해결책임을 하나는 알고 있었다. |
| Line 18: | Line 20: |
| 시니어 개발자가 끼어들었다. "맞아. 하지만 '''왜''' 찾고 싶어하는지 물어봤어?" | |
| Line 20: | Line 21: |
| "아니요... 바로 구현을 시작했어요. 검색 기능이 필요하다고 생각했거든요." | == The Story 2: The Travel Plan (Ordinary Life) == |
| Line 22: | Line 23: |
| 시니어가 고개를 끄덕였다. "이게 우리가 자주 하는 실수야. '''문제'''를 이해하기 전에 '''해결책'''부터 생각하는 거지. 두 세계는 다른 거야." | 민수와 하나는 이번 여름 휴가 계획을 세우고 있다. '''민수의 계획 (The How First):''' 민수는 비행기 티켓 예매 사이트부터 열었다. "지금 삿포로행 비행기가 제일 싸네! 일단 이거부터 예약하자." 민수는 '어떻게(How)' 이동할지에 매몰되어 티켓을 끊었다. 하지만 나중에 보니 하나는 이번 휴가 때 따뜻한 바다에서 서핑을 하고 싶어 했다. 민수가 예약한 삿포로는 하나가 원하던 '무엇(What)'과 전혀 맞지 않았고, 결국 수수료를 내고 티켓을 취소해야 했다. '''하나의 계획 (The What First):''' 하나는 민수에게 먼저 물었다. "이번 휴가 때 우리가 진짜 하고 싶은 게 뭐야? 휴식이야, 아니면 액티비티야?" 두 사람은 충분한 대화 끝에 '따뜻한 나라에서 스쿠버다이빙 하기'라는 목적지를 정했다. 목적(Problem Space)이 명확해지자, 비행기 노선과 숙소(Solution Space)는 자연스럽게 결정되었다. 무엇을 원하는지 결정하는 세계와 어떻게 달성할지 결정하는 세계는 분리되어야 함을 하나는 알고 있었다. |
| Line 30: | Line 37: |
| * 요구사항 문서를 받자마자 코딩을 시작한다 * "이건 간단해, 그냥 X를 추가하면 돼"라고 생각한다 * 구현하다가 요구사항이 애매해서 추측으로 진행한다 * 완성 후 "이게 아니었는데..."라는 피드백을 받는다 |
* 요구사항 문서를 받자마자 코딩을 시작한다. * "이건 간단해, 그냥 X를 추가하면 돼"라고 생각한다. * 구현하다가 요구사항이 애매해서 추측으로 진행한다. * 완성 후 "이게 아니었는데..."라는 피드백을 받는다. |
| Line 40: | Line 47: |
| 많은 프로그래밍 오류는 사고 과정에서 '''두 관심사를 너무 일찍 섞는''' 데서 비롯된다: | '''많은 프로그래밍 오류는 사고 과정에서 "문제 공간"과 "해결 공간"을 너무 일찍 섞는 데서 비롯된다.''' |
| Line 43: | Line 50: |
문제를 듣자마자 해결책이 떠오른다. 이것은 경험의 표시처럼 느껴진다. "나는 이걸 어떻게 만들지 알아!" 하지만 이것은 함정이다. {{{ 요구사항: "사용자가 주문 내역을 쉽게 찾을 수 있어야 한다" 즉각적 사고: → 검색 기능이 필요하다 → 필터링이 필요하다 → 정렬이 필요하다 → 페이징이 필요하다 → (2주 후) 잘못된 기능 완성 }}} Gerald Weinberg는 "Are Your Lights On?"에서 말한다: '''문제가 무엇인지 정의하지 않고는, 문제를 해결할 수 없다.''' 하지만 우리는 정의하기 전에 해결하려 한다. |
문제를 듣자마자 해결책이 떠오른다. 이것은 경험의 표시처럼 느껴진다. "나는 이걸 어떻게 만들지 알아!" 하지만 이것은 함정이다. Gerald Weinberg는 "Are Your Lights On?"에서 말한다: '''문제가 무엇인지 정의하지 않고는, 문제를 해결할 수 없다.''' 하지만 우리는 정의하기 전에 해결하려 한다. |
| Line 60: | Line 53: |
잘못된 문제를 해결하는 것은 '''자원의 엄청난 낭비'''다: * 2주간의 개발 시간 * 복잡한 코드 작성과 테스트 * 리뷰와 QA 시간 * 그리고 결국... 다시 만들어야 함 더 나쁜 것은, 이런 일이 '''자주 일어난다'''는 것이다. 왜? 우리가 두 세계를 섞기 때문이다. |
잘못된 문제를 해결하는 것은 '''자원의 엄청난 낭비'''다. 2주간 개발한 기능이 무용지물이 되는 것은 단순히 시간의 손실을 넘어 팀의 사기와 신뢰에 타격을 줍니다. |
| Line 71: | Line 56: |
'''문제 공간 (Problem Space):''' 무엇을 해결할 것인가? * 사용자가 진짜 원하는 것은 무엇인가? * 왜 이것이 필요한가? * 진짜 목표는 무엇인가? * 어떤 상황에서 이것을 사용하는가? '''해결 공간 (Solution Space):''' 어떻게 구현할 것인가? * 어떤 데이터 구조를 쓸 것인가? * 어떤 알고리즘을 적용할 것인가? * 어떤 라이브러리를 사용할 것인가? * 성능은 어떻게 최적화할 것인가? 이 두 세계는 '''다른 사고 방식'''을 요구한다. 하지만 우리는 이것들을 섞는다: {{{ "사용자가 주문을 찾고 싶어한다" (문제) → "검색 기능을 만들자" (해결책) → "Elasticsearch를 쓰자" (구현) → "어떻게 인덱싱하지?" (세부사항) 문제 공간을 떠나기가 너무 빨랐다! }}} |
* '''문제 공간 (Problem Space):''' 무엇을 해결할 것인가? (사용자가 진짜 원하는 것, 목표, 사용 상황) * '''해결 공간 (Solution Space):''' 어떻게 구현할 것인가? (데이터 구조, 알고리즘, 라이브러리, 성능 최적화) 이 두 세계는 '''다른 사고 방식'''을 요구한다. 하지만 우리는 이것들을 너무 쉽게 섞어버린다. |
| Line 98: | Line 63: |
| '''문제 공간을 충분히 탐색하라. 그다음에 해결 공간으로 이동하라.''' 두 세계를 의식적으로 분리하면, 더 나은 해결책을 찾고, 종종 더 간단한 해결책을 찾는다. | '''문제 공간을 충분히 탐색하라. 그다음에 해결 공간으로 이동하라.''' 두 세계를 의식적으로 분리하면, 더 나은 해결책을 찾고, 종종 훨씬 더 간단한 해결책을 찾게 됩니다. |
| Line 101: | Line 66: |
해결책을 생각하고 싶은 충동을 억제하라. 문제 공간에 머물면서 깊이 탐색하라. '''질문하라 - George Polya의 접근:''' * 문제를 다른 말로 표현할 수 있는가? * 핵심 요소는 무엇인가? * 이미 알고 있는 것은 무엇인가? * 모르는 것은 무엇인가? * 제약사항은 무엇인가? '''예시:''' {{{ 요구사항: "주문 내역을 쉽게 찾을 수 있어야 한다" 문제 공간 탐색: Q: 사용자가 왜 주문 내역을 찾는가? A: 같은 것을 다시 주문하고 싶어서 Q: 모든 주문을 검색해야 하는가? A: 아니, 주로 최근 3개월 내 주문만 Q: 어떤 정보로 찾는가? A: 대부분 "지난번에 뭘 샀더라?" 진짜 문제: 반복 주문을 쉽게 하고 싶다 → 복잡한 검색 기능이 아니라 "다시 주문하기" 버튼! }}} 깊은 탐색은 '''눈을 뜬다'''. 원래 생각했던 것보다 훨씬 간단한 해결책으로 이어질 수 있다. |
해결책을 제안하고 싶은 충동을 억제하십시오. 문제 공간에 머물면서 깊이 탐색하십시오. * 문제를 다른 말로 표현해 보십시오. * 핵심 요소와 제약 사항이 무엇인지 파악하십시오. * George Polya의 접근처럼, 모르는 것이 무엇인지 명확히 하십시오. |
| Line 132: | Line 72: |
| Line 134: | Line 73: |
명확한 문제 정의: * 무엇이 현재 상태인가? * 무엇이 원하는 상태인가? * 그 사이의 간격은 무엇인가? * 왜 그 간격이 중요한가? {{{ // 애매한 정의 "검색 기능이 필요하다" // 명확한 정의 현재: 사용자가 자주 주문하는 상품을 다시 찾기 어려움 원하는: 이전 주문을 2클릭 이내에 재주문 가능 간격: 주문 이력 탐색과 재주문의 마찰 중요성: 반복 구매가 매출의 40% }}} 명확한 정의는 해결책을 '''자연스럽게 제안'''한다. |
* 무엇이 현재 상태(Current)인가? * 무엇이 원하는 상태(Desired)인가? * 그 사이의 간격(Gap)은 무엇이며, 왜 그 간격이 중요한가? |
| Line 155: | Line 78: |
의식적으로 두 모드 사이를 전환하라: '''문제 모드 (Why & What):''' * "왜 이것이 문제인가?" * "진짜 목표는 무엇인가?" * "다른 방식으로 표현하면?" * 해결책 제안을 '''의도적으로 지연''' '''해결 모드 (How):''' * "어떻게 구현할 것인가?" * "어떤 기술을 사용할 것인가?" * "어떻게 최적화할 것인가?" * 문제 정의는 이미 '''확정'''되었음 중요: '''한 번에 하나의 모드만''' 사용하라. 섞지 마라. {{{ // ❌ BAD: 두 모드가 섞임 "사용자가 주문을 찾고 싶어한다 (문제) → 검색을 구현하려면 (해결) → 근데 왜 찾지? (문제) → Elasticsearch가 좋을까? (해결)" // ✅ GOOD: 분리된 사고 [문제 모드] "왜 주문을 찾는가? → 재주문 어떤 주문? → 최근 주문 진짜 필요: 빠른 재주문" [전환] [해결 모드] "최근 주문 리스트 + 재주문 버튼 API: GET /recent-orders UI: 간단한 목록 + 버튼" }}} |
의식적으로 두 모드 사이를 전환하십시오. 한 번에 하나의 모드만 사용하십시오. * '''문제 모드 (Why & What):''' "왜 이것이 문제인가?", "진짜 목표는 무엇인가?" * '''해결 모드 (How):''' "어떻게 구현할 것인가?", "어떤 기술을 사용할 것인가?" |
| Line 194: | Line 83: |
| Line 196: | Line 84: |
문제 공간을 깊이 탐색하면, 종종 발견한다: * 구현할 필요가 없는 기능 * 훨씬 간단한 해결책 * 이미 존재하는 해결책 {{{ 원래 계획: - 복잡한 검색 UI (3일) - 필터링 로직 (2일) - 정렬 기능 (1일) - 페이징 (1일) - 검색 최적화 (2일) 총: 9일 문제 탐색 후: - "다시 주문하기" 버튼 - 최근 5개 주문 목록 총: 0.5일 '''8.5일의 일을 하지 않았다!''' }}} 이것이 진정한 효율이다: '''올바른 문제를 해결하는 것.''' |
문제 공간을 깊이 탐색하면, 종종 구현할 필요가 없는 기능을 발견하거나 훨씬 간단한 대안을 찾게 됩니다. |
| Line 225: | Line 90: |
Toyota의 기법: 문제의 근본 원인을 찾기 위해 "왜?"를 5번 물어라. {{{ 문제: 배포가 자주 실패한다 왜? → 테스트가 깨진다 왜? → 환경 설정이 다르다 왜? → 개발 환경과 운영 환경의 설정이 다르다 왜? → 설정을 수동으로 관리한다 왜? → 설정 관리 도구가 없다 진짜 문제: 설정 관리 해결책: 복잡한 배포 파이프라인이 아니라, 설정 관리 도구! }}} |
도요타의 기법: 문제의 근본 원인을 찾기 위해 "왜?"를 5번 물으십시오. |
| Line 242: | Line 93: |
명확한 문제 정의를 위한 템플릿: {{{ [누가]의 [어떤 상황]에서 [현재 문제]가 발생한다. 이것은 [어떤 영향]을 미친다. [원하는 결과]를 달성하고 싶다. }}} '''예시:''' {{{ 자주 구매하는 고객의 재주문 상황에서 이전 주문을 찾기 위해 주문 이력을 스크롤해야 하는 문제가 발생한다. 이것은 재주문 포기와 불만을 미친다. 2클릭 이내에 재주문을 완료하고 싶다. }}} 이제 해결책이 명확하다: 빠른 재주문 버튼! |
"[누가]의 [어떤 상황]에서 [현재 문제]가 발생한다. 이것은 [어떤 영향]을 미친다. [원하는 결과]를 달성하고 싶다." |
| Line 263: | Line 96: |
문제를 이해한 후, 해결 공간에서 여러 옵션을 탐색하라: {{{ 문제 정의: 빠른 재주문 (확정) 해결 옵션들: 1. 최근 주문 + 재주문 버튼 (간단, 빠름) 2. 자주 구매한 상품 추천 (복잡, 머신러닝) 3. 원클릭 재주문 (간단, 하지만 실수 위험) 4. 장바구니에 담기 (기존 플로우 활용) 각 옵션의 트레이드오프를 고려하여 선택 }}} 문제가 명확하면, '''올바른 해결책을 비교'''할 수 있다. |
문제를 이해한 후, 해결 공간에서 여러 옵션을 탐색하고 트레이드오프를 비교하십시오. |
| Line 284: | Line 102: |
경험이 많아질수록, 패턴을 빨리 인식한다. 이것은 좋지만, 함정이기도 하다. 당신이 해결책을 "안다"고 생각할 때, '''정말 문제를 이해했는가?''' 5분만 투자해서 문제를 확인하라. 가끔은 당신이 생각한 것과 다른 문제다. |
경험이 많아질수록 패턴을 빨리 인식하지만, 이것이 함정이 될 수 있습니다. 5분만 더 투자해서 문제를 확인하십시오. |
| Line 292: | Line 105: |
"빨리 만들어야 해!" - 그래서 문제 탐색을 건너뛴다. 하지만 잘못된 것을 빨리 만드는 것은 '''더 느리다''': * 2주 개발 + 2주 재개발 = 4주 * vs. 1일 문제 탐색 + 1주 개발 = 8일 '''올바른 방향으로 천천히 가는 것이 잘못된 방향으로 빨리 가는 것보다 빠르다.''' === "The Requirements Are Clear!" === 요구사항 문서가 명확해 보인다. 하지만: * 명확하게 '''쓰여진''' 것과 * 진짜 '''이해한''' 것은 다르다 문서가 있어도, 대화하라. 질문하라. 확인하라. |
잘못된 것을 빨리 만드는 것은 결국 더 느린 길입니다. 올바른 방향으로 천천히 가는 것이 더 빠릅니다. |
| Line 312: | Line 110: |
| '''[[WorkingFirst]]''' - 문제를 이해한 후, 가장 간단한 작동하는 해결책부터 시작하라. 완벽한 해결책을 설계하려 하지 마라. ''순차 관계'' '''[[StrongCenter]]''' - 문제의 핵심을 파악하는 것은 시스템의 강한 중심을 찾는 것과 같다. 주변부가 아닌 핵심부터. ''같은 원리'' '''[[DataAsFoundation]]''' - 문제 공간을 탐색하면, 종종 올바른 데이터 구조가 보인다. 문제가 명확하면 데이터 설계도 명확해진다. ''자연스러운 발전'' '''[[PatternHunting]]''' - 문제의 본질을 이해하면, 유사한 문제의 패턴을 인식할 수 있다. ''기반'' '''[[DetectiveWork]]''' - 버그도 문제다. 표면적 증상 대신 근본 원인을 찾는 것은 문제 공간 탐색이다. ''같은 사고방식'' '''[[TinyExperiment]]''' - 문제가 불명확하면, 작은 실험으로 문제를 명확히 하라. ''문제 탐색 도구'' '''[[CognitiveMicroscope]]''' - 자신이 문제 공간에 있는지 해결 공간에 있는지 관찰하라. 두 모드를 의식적으로 전환하는 것도 메타인지다. ''인지적 도구'' '''[[MetaphorThinking]]''' - 은유는 문제 공간과 해결 공간을 연결하는 다리다. ''연결'' '''[[The95PercentRule]]''' - 문제 공간(비용 절감)을 생각하면 95%가 답이다. 해결 공간에 갇히면 100%에 집착한다. ''가치 판단'' |
* '''[[WorkingFirst]]''' - 문제를 이해한 후, 가장 간단한 작동하는 해결책부터 시작하십시오. ''순서'' * '''[[StrongCenter]]''' - 문제의 핵심을 파악하는 것은 시스템의 강한 중심을 찾는 것과 같습니다. ''본질'' * '''[[DataAsFoundation]]''' - 문제 공간을 탐색하면 종종 올바른 데이터 구조가 보입니다. ''발전'' * '''[[DetectiveWork]]''' - 버그 조사도 문제 공간을 탐색하는 과정입니다. ''사고방식'' * '''[[TinyExperiment]]''' - 문제가 불명확하면 작은 실험으로 문제를 명확히 하십시오. ''탐색'' |
| Line 333: | Line 118: |
| TwoWorlds를 효과적으로 사용하고 있다는 신호: * '''질문이 많다''' - 코딩 전에 "왜?"를 여러 번 물어본다 * '''더 간단해진다''' - 문제를 이해할수록 해결책이 단순해진다 * '''재작업이 줄어든다''' - "이게 아니었어"가 거의 없다 * '''빠른 합의''' - 문제 정의가 명확하면 팀이 빠르게 동의한다 * '''작은 PR''' - 올바른 문제는 종종 작은 해결책을 만든다 * '''확신이 있다''' - 당신은 올바른 것을 만들고 있다고 확신한다 |
* 코딩 전에 질문이 많아진다. * 결과적으로 만들어지는 코드가 이전보다 훨씬 단순해진다. * 팀원들과 문제 정의에 대해 빠르게 합의에 도달한다. * 재작업(Rework) 비율이 현저히 줄어든다. |
| Line 345: | Line 125: |
| 주니어가 바로 구현을 시작하려 할 때: '''멈추게 하라:''' "잠깐, 코딩 전에... 이 문제를 설명해줄 수 있어?" '''질문하라:''' * "왜 사용자가 이것을 원할까?" * "이것이 해결하는 진짜 문제는 뭐지?" * "다른 방식으로 같은 목표를 달성할 수 있을까?" '''구분하게 하라:''' "지금 우리가 문제에 대해 이야기하는 건지, 해결책에 대해 이야기하는 건지 구분해보자." '''연습하라:''' 매 작업마다, 문제 공간과 해결 공간을 명시적으로 구분하는 습관을 만들어라. |
주니어가 바로 구현을 시작하려 할 때 "잠깐, 코딩 전에 이 문제를 설명해 줄 수 있어?"라고 멈추게 하십시오. "왜 사용자가 이것을 원할까?", "다른 방식으로 같은 목표를 달성할 수 있을까?"를 질문하여 두 세계를 구분하게 하십시오. |
| Line 364: | Line 130: |
| Polya가 말했다: '''문제를 이해하는 것이 절반이다.''' | '''문제 공간에서 시간을 쓰는 것은 투자이며, 해결 공간에서 잘못된 것을 만드는 것은 낭비입니다.''' |
| Line 366: | Line 132: |
| Weinberg가 말했다: '''올바른 문제를 정의하지 않으면, 올바른 해결책을 찾을 수 없다.''' Agile이 말한다: '''단순함은 본질적이다 - 하지 않아도 되는 일을 최대화하라.''' 이 모든 지혜는 같은 진리를 가리킨다: {{{ 문제 공간에서 시간을 쓰는 것은 투자다. 해결 공간에서 잘못된 것을 만드는 것은 낭비다. }}} '''두 세계를 분리하라.''' 문제를 충분히 탐색하고, 그다음에 해결책을 만들어라. 이것은 단순히 시간을 절약하는 것이 아니다. '''올바른 것을 만드는 것'''이다. 그리고 올바른 것을 만드는 것이 프로그래밍의 본질이다. |
두 세계를 분리하십시오. 문제를 충분히 탐색하고, 그 다음에 해결책을 만드십시오. 그것이 단순히 시간을 아끼는 것을 넘어, '올바른 것'을 만드는 유일한 길입니다. 그리고 올바른 것을 만드는 것이 프로그래밍의 본질입니다. |
TwoWorlds
주니어 개발자들을 위한 패턴 언어 - 문제 공간과 해결 공간을 분리하여 올바른 문제를 해결하는 방법
Contents
The Story 1: The Wrong Search Engine (Programming)
두 명의 개발자, 민수와 하나가 '주문 내역 조회' 기능을 개발하고 있다.
민수의 접근 (The Premature Solution): 민수는 요구사항을 듣자마자 구현을 시작했다. "주문 내역을 쉽게 찾아야 하니까 강력한 검색 엔진이 필요해." 그는 2주 동안 엘라스틱서치(Elasticsearch)를 연동하고 10개가 넘는 복잡한 필터링 옵션을 구현했다. 하지만 데모 날, 사용자의 피드백은 예상 밖이었다. "우리는 복잡한 검색을 원한 게 아니라, 그냥 '지난번 샀던 거 다시 주문하기' 버튼 하나가 필요했어요." 민수는 해결 공간에 너무 빨리 뛰어든 나머지, 잘못된 문제를 해결하고 말았다.
하나의 접근 (The Problem Explorer): 하나는 코딩 전에 사용자에게 물었다. "왜 주문 내역을 찾고 싶어 하시나요?" (문제 공간 탐색) "대부분 지난번에 샀던 비품을 다시 주문하려는데, 품목 이름을 잊어버려서 그래요." 하나는 진짜 문제를 발견했다. 그녀는 복잡한 검색 기능을 만드는 대신, '최근 주문 목록'과 '재주문 버튼'을 만들었다. 하나는 단 하루 만에 사용자를 만족시켰다. 문제 공간을 충분히 이해하는 것이 가장 빠른 해결책임을 하나는 알고 있었다.
The Story 2: The Travel Plan (Ordinary Life)
민수와 하나는 이번 여름 휴가 계획을 세우고 있다.
민수의 계획 (The How First): 민수는 비행기 티켓 예매 사이트부터 열었다. "지금 삿포로행 비행기가 제일 싸네! 일단 이거부터 예약하자." 민수는 '어떻게(How)' 이동할지에 매몰되어 티켓을 끊었다. 하지만 나중에 보니 하나는 이번 휴가 때 따뜻한 바다에서 서핑을 하고 싶어 했다. 민수가 예약한 삿포로는 하나가 원하던 '무엇(What)'과 전혀 맞지 않았고, 결국 수수료를 내고 티켓을 취소해야 했다.
하나의 계획 (The What First): 하나는 민수에게 먼저 물었다. "이번 휴가 때 우리가 진짜 하고 싶은 게 뭐야? 휴식이야, 아니면 액티비티야?" 두 사람은 충분한 대화 끝에 '따뜻한 나라에서 스쿠버다이빙 하기'라는 목적지를 정했다. 목적(Problem Space)이 명확해지자, 비행기 노선과 숙소(Solution Space)는 자연스럽게 결정되었다. 무엇을 원하는지 결정하는 세계와 어떻게 달성할지 결정하는 세계는 분리되어야 함을 하나는 알고 있었다.
Context
당신은 새로운 기능을 개발하고 있다. 요구사항을 받았고, 머릿속에 이미 구현 방법이 떠오른다. 코드를 어떻게 짜야 할지, 어떤 라이브러리를 쓸지, 어떤 알고리즘을 적용할지...
일상적인 상황:
- 요구사항 문서를 받자마자 코딩을 시작한다.
- "이건 간단해, 그냥 X를 추가하면 돼"라고 생각한다.
- 구현하다가 요구사항이 애매해서 추측으로 진행한다.
- 완성 후 "이게 아니었는데..."라는 피드백을 받는다.
당신은 해결책에 대해 생각하고 있지만, 문제를 충분히 이해하지 못했다.
Problem
많은 프로그래밍 오류는 사고 과정에서 "문제 공간"과 "해결 공간"을 너무 일찍 섞는 데서 비롯된다.
The Premature Solution
문제를 듣자마자 해결책이 떠오른다. 이것은 경험의 표시처럼 느껴진다. "나는 이걸 어떻게 만들지 알아!" 하지만 이것은 함정이다. Gerald Weinberg는 "Are Your Lights On?"에서 말한다: 문제가 무엇인지 정의하지 않고는, 문제를 해결할 수 없다. 하지만 우리는 정의하기 전에 해결하려 한다.
The Cost of Wrong Problems
잘못된 문제를 해결하는 것은 자원의 엄청난 낭비다. 2주간 개발한 기능이 무용지물이 되는 것은 단순히 시간의 손실을 넘어 팀의 사기와 신뢰에 타격을 줍니다.
Two Worlds Confused
* 문제 공간 (Problem Space): 무엇을 해결할 것인가? (사용자가 진짜 원하는 것, 목표, 사용 상황) * 해결 공간 (Solution Space): 어떻게 구현할 것인가? (데이터 구조, 알고리즘, 라이브러리, 성능 최적화) 이 두 세계는 다른 사고 방식을 요구한다. 하지만 우리는 이것들을 너무 쉽게 섞어버린다.
Solution
문제 공간을 충분히 탐색하라. 그다음에 해결 공간으로 이동하라. 두 세계를 의식적으로 분리하면, 더 나은 해결책을 찾고, 종종 훨씬 더 간단한 해결책을 찾게 됩니다.
Principle 1: Stay in Problem Space Longer
해결책을 제안하고 싶은 충동을 억제하십시오. 문제 공간에 머물면서 깊이 탐색하십시오. * 문제를 다른 말로 표현해 보십시오. * 핵심 요소와 제약 사항이 무엇인지 파악하십시오. * George Polya의 접근처럼, 모르는 것이 무엇인지 명확히 하십시오.
Principle 2: Define Before Solving
Weinberg의 교훈: 문제 정의가 해결의 절반이다. * 무엇이 현재 상태(Current)인가? * 무엇이 원하는 상태(Desired)인가? * 그 사이의 간격(Gap)은 무엇이며, 왜 그 간격이 중요한가?
Principle 3: Separate Thinking Modes
의식적으로 두 모드 사이를 전환하십시오. 한 번에 하나의 모드만 사용하십시오. * 문제 모드 (Why & What): "왜 이것이 문제인가?", "진짜 목표는 무엇인가?" * 해결 모드 (How): "어떻게 구현할 것인가?", "어떤 기술을 사용할 것인가?"
Principle 4: Maximize Work Not Done
Agile 원칙: 단순함은 본질적이다 - 하지 않아도 되는 일을 최대화하라. 문제 공간을 깊이 탐색하면, 종종 구현할 필요가 없는 기능을 발견하거나 훨씬 간단한 대안을 찾게 됩니다.
Practical Patterns
Pattern 1: The Five Whys
도요타의 기법: 문제의 근본 원인을 찾기 위해 "왜?"를 5번 물으십시오.
Pattern 2: Problem Statement Template
"[누가]의 [어떤 상황]에서 [현재 문제]가 발생한다. 이것은 [어떤 영향]을 미친다. [원하는 결과]를 달성하고 싶다."
Pattern 3: Solution Space Exploration
문제를 이해한 후, 해결 공간에서 여러 옵션을 탐색하고 트레이드오프를 비교하십시오.
Common Pitfalls
"But I Know the Solution!"
경험이 많아질수록 패턴을 빨리 인식하지만, 이것이 함정이 될 수 있습니다. 5분만 더 투자해서 문제를 확인하십시오.
"We Need to Move Fast!"
잘못된 것을 빨리 만드는 것은 결국 더 느린 길입니다. 올바른 방향으로 천천히 가는 것이 더 빠릅니다.
Connection to Other Patterns
WorkingFirst - 문제를 이해한 후, 가장 간단한 작동하는 해결책부터 시작하십시오. 순서
StrongCenter - 문제의 핵심을 파악하는 것은 시스템의 강한 중심을 찾는 것과 같습니다. 본질
DataAsFoundation - 문제 공간을 탐색하면 종종 올바른 데이터 구조가 보입니다. 발전
DetectiveWork - 버그 조사도 문제 공간을 탐색하는 과정입니다. 사고방식
TinyExperiment - 문제가 불명확하면 작은 실험으로 문제를 명확히 하십시오. 탐색
Signs of Success
- 코딩 전에 질문이 많아진다.
- 결과적으로 만들어지는 코드가 이전보다 훨씬 단순해진다.
- 팀원들과 문제 정의에 대해 빠르게 합의에 도달한다.
- 재작업(Rework) 비율이 현저히 줄어든다.
For Teachers and Mentors
주니어가 바로 구현을 시작하려 할 때 "잠깐, 코딩 전에 이 문제를 설명해 줄 수 있어?"라고 멈추게 하십시오. "왜 사용자가 이것을 원할까?", "다른 방식으로 같은 목표를 달성할 수 있을까?"를 질문하여 두 세계를 구분하게 하십시오.
The Ultimate Insight
문제 공간에서 시간을 쓰는 것은 투자이며, 해결 공간에서 잘못된 것을 만드는 것은 낭비입니다.
두 세계를 분리하십시오. 문제를 충분히 탐색하고, 그 다음에 해결책을 만드십시오. 그것이 단순히 시간을 아끼는 것을 넘어, '올바른 것'을 만드는 유일한 길입니다. 그리고 올바른 것을 만드는 것이 프로그래밍의 본질입니다.
CategoryPatternLanguage CategoryProgramming CategoryProblemSolving CategoryDesign
