Retrieved content for WorkingFirst #acl +All:read

WorkingFirst

주니어 개발자들을 위한 패턴 언어 - 먼저 작동하게 만들고, 이해한 다음, 올바르게 만드는 방법

The Story: Two Weeks of Perfect Design

주니어 개발자 민수는 사용자 인증 시스템을 구축하는 임무를 받았다. 그는 첫날, 노트북을 열고 생각에 잠겼다.

"완벽하게 만들어야 해. 어떤 암호화 알고리즘을 써야 할까? bcrypt? Argon2? 토큰은 어떻게 관리하지? JWT? Session? 세션 저장소는 Redis? Memcached? 확장성은 어떻게 보장하지? 마이크로서비스 아키텍처가 필요할까?"

2주가 지났다. 민수는 수많은 기술 문서를 읽었다. 아키텍처 다이어그램을 그렸다. 보안 베스트 프랙티스를 연구했다. 하지만 한 줄의 코드도 작성하지 않았다.

"아직 완벽한 설계를 찾지 못했어요," 민수가 말했다. "뭔가 놓친 게 있을 것 같아서... 시작할 수가 없어요."

시니어 개발자 지혜는 같은 문제를 다르게 접근했다. 첫날 오전, 그녀는 20줄짜리 코드를 작성했다:

def login(username, password):
    if username == "admin" and password == "secret":
        return {"token": "simple_token"}
    return None

"이건 틀렸어요!" 민수가 말했다. "보안도 없고, 확장성도 없고, 데이터베이스도 없어요!"

지혜가 미소 지었다. "맞아. 하지만 작동하지. 이제 우리는 세 가지를 확인했어:"

"이제부터 점진적으로 개선하면 돼."

다음 이틀 동안, 지혜는 그 작동하는 코드를 단계별로 개선했다:

# Day 1 오후: 하드코딩을 데이터베이스로
def login(username, password):
    user = db.get_user(username)
    if user and user.password == password:
        return {"token": generate_token(user)}
    return None

# Day 2: 암호화 추가
def login(username, password):
    user = db.get_user(username)
    if user and verify_password(password, user.password_hash):
        return {"token": generate_secure_token(user)}
    return None

# Day 3: 세션 관리
def login(username, password):
    user = db.get_user(username)
    if user and verify_password(password, user.password_hash):
        session = create_session(user)
        return {"token": session.token, "expires": session.expires_at}
    return None

일주일 후, 시스템은 production-ready였다. 각 단계마다 코드는 작동했다. 테스트할 수 있었고, 검증할 수 있었고, 개선할 수 있었다.

민수는 여전히 완벽한 설계를 찾고 있었다.

Context

당신은 새로운 기능을 구현하거나 복잡한 문제를 해결해야 한다. 여러 가지 방법이 가능해 보이고, 어떤 접근이 "올바른지" 확신할 수 없다. 시간은 제한되어 있고, 요구사항은 완전히 명확하지 않을 수 있다.

당신은 TwoWorlds를 통해 문제와 해결책을 분리하는 법을 배웠고, DataAsFoundation을 통해 데이터 구조의 중요성을 이해하고 있다. 이제 어떻게 만들 것인가의 단계에 있다.

일상적인 상황:

Problem

초보 프로그래머는 실행하기 전에 완벽하게 설계하려는 경향이 있다. 그들은 도전적인 과제를 만들 수 있을지 두려워하여 너무 신중하게, 너무 많이 설계한다. 실행 없이 설계만 한다.

The Fear of Starting

주니어 개발자의 내면의 목소리:

이 두려움은 분석 마비(Analysis Paralysis)로 이어진다. 결정을 내리지 못하고, 계속 더 많은 정보를 찾고, 더 많은 대안을 고려하고, 결국 아무것도 만들지 못한다.

The Premature Optimization Trap

Donald Knuth가 말했다: "Premature optimization is the root of all evil." 하지만 주니어는 종종 이것을 무시한다.

작동하기도 전에:

# ❌ 작동도 안 하는데 최적화부터
def process_data(items):
    # 캐싱 레이어?
    # 병렬 처리?
    # 메모리 최적화?
    # 아직 한 줄도 작성 안 함...
    pass

YAGNI and KISS Violations

두 가지 기본 원칙을 위반한다:

YAGNI (You Aren't Gonna Need It)

KISS (Keep It Simple, Stupid)

# ❌ YAGNI 위반
class UserAuthenticator:
    def __init__(self, strategy_factory, token_manager,
                 session_store, cache_layer, audit_logger):
        # 5개의 의존성... 정말 다 필요한가?
        pass

# ✅ KISS: 필요한 것만
def authenticate(username, password):
    user = get_user(username)
    return user and check_password(password, user.password_hash)

The Wrong Priority

초기 단계에서 우선순위가 뒤바뀐다:

주니어의 우선순위:

  1. 완벽한 아키텍처
  2. 최적화된 성능
  3. 모든 엣지 케이스 처리
  4. 확장 가능한 설계
  5. ...그리고 작동하는지?

시니어의 우선순위:

  1. 작동하는가? ← 가장 먼저

  2. 올바른가?
  3. 깔끔한가?
  4. 빠른가?

Kent Beck이 표현했듯: "Make it work, make it right, make it fast." 순서가 중요하다.

The Epistemological Problem

더 근본적인 문제가 있다: 만들어보기 전에는 알 수 없다.

ChrisArgyris가 말했듯이, 의사결정은 과정(process)이다. 우리는 해결책을 탐색하고 실험해야 한다. 올바른 방법을 미리 아는 것은 불가능하다.

특히 초기 단계에서:

계획: "인증 시스템은 OAuth2를 사용하고, JWT 토큰을 발급하고..."

실제로 만들어보니:
- OAuth2는 우리 use case에 과도했다
- 간단한 세션 기반 인증으로 충분했다
- 요구사항을 잘못 이해하고 있었다

The Cost of Wrong Starting Point

완벽한 설계부터 시작하면:

작동하는 것부터 시작하면:

4.5주의 차이. 이것이 WorkingFirst의 가치다.

Solution

먼저 작동하게 만들어라. 우아하거나 효율적으로 만들기 전에.

작동하는 해결책은 문제의 진정한 본질을 드러내고 더 나은 설계 결정을 안내한다. 이것은 단순한 기법이 아니라 탐색의 철학이다.

Principle 1: Reachable Working State ASAP

가능한 한 빨리 작동 상태에 도달하라(Reach to Working State ASAP).

이것은 세 가지를 확인한다:

  1. 가능하다 - 이것은 만들 수 있다

  2. 어떻게 - 기본 구조와 접근법

  3. 무엇이 - 진짜 어려운 부분이 무엇인지

# Day 1 목표: "작동"
def api_call(endpoint):
    response = requests.get(f"https://api.example.com/{endpoint}")
    return response.json()

# 이제 확인했다:
# ✓ API가 작동한다
# ✓ 인증이 필요하다 (에러를 통해 발견)
# ✓ rate limit이 있다 (에러를 통해 발견)
# ✓ 응답 형식이 문서와 다르다 (실행을 통해 발견)

작동하는 코드는 학습 도구다. 이론이 아닌 실제를 가르쳐준다.

Principle 2: Use Familiar Tools First (익숙한 도구로 뚫기)

새로운 기술 스택이나 과제 조건에 얽매여 전진을 멈추지 마라.

Principle 3: Make It Work, Make It Right, Make It Fast

Kent Beck의 3단계 접근:

Phase 1: Make It Work (작동하게)

Phase 2: Make It Right (올바르게)

Phase 3: Make It Fast (빠르게)

# Phase 1: Work
def calculate_total(items):
    total = 0
    for item in items:
        total += item['price'] * item['quantity']
    return total

# Phase 2: Right
def calculate_total(items):
    return sum(item.price * item.quantity for item in items)

# Phase 3: Fast (필요한 경우만)
@lru_cache(maxsize=128)
def calculate_total(items_tuple):
    return sum(item.price * item.quantity
               for item in items_tuple)

대부분의 경우, Phase 2까지만 필요하다. Phase 3는 측정된 성능 문제가 있을 때만.

Principle 3: Exploration First, Optimization Later

올바른 방법은 여러 가지다. WorkingFirst는 그 중 하나에 빠르게 도달하게 돕는다.

George Polya의 "How to Solve It"에서:

  1. 문제 이해 - 작동하는 것을 만들면서 진짜 문제 이해

  2. 계획 수립 - 첫 작동 버전이 더 나은 계획의 기초

  3. 계획 실행 - 작동 → 개선의 반복

  4. 되돌아보기 - 작동하는 것에서 패턴 발견

문제: "사용자 데이터를 캐싱해야 한다"

탐색적 접근:
1. 먼저 캐싱 없이 작동하게 (Day 1)
2. 성능 측정 (Day 1)
3. 병목이 확인되면 단순 dict 캐싱 (Day 2)
4. 필요하면 Redis로 (Day 3)

설계 우선 접근:
1. Redis 아키텍처 연구 (Week 1)
2. 캐시 무효화 전략 설계 (Week 1)
3. 구현 시작 (Week 2)
4. 실제로는 단순 캐싱으로 충분했다는 것을 발견 (Week 2)
5. 1.5주 낭비

Principle 4: Prototype as Learning Tool

초기 프로토타입은 버릴 것을 전제로 만들어라.

Fred Brooks는 "The Mythical Man-Month"에서 말했다: "Plan to throw one away; you will, anyhow."

프로토타입의 목적:

프로토타입은 실패해도 된다. 그것이 목적이다.

# Prototype (버릴 것)
def quick_search(text):
    return [item for item in all_items if text in item['name']]

# 배운 것:
# - 대소문자 구분 필요
# - 부분 매칭 필요
# - 성능 문제 (all_items가 크면)
# - 정렬 필요

# 실제 구현 (배운 것 기반)
def search(text, options=None):
    text = text.lower()
    results = [item for item in indexed_items
               if text in item.name.lower()]
    return sorted(results, key=lambda x: x.relevance)

프로토타입을 만들고 나면, 어떻게 제대로 만들어야 할지 안다.

Principle 5: Working State as Safe Refuge

GreenRefuge와 연결: 작동하는 상태는 안전한 피난처다.

각 단계에서 "작동하는" 상태를 유지하면:

# 나쁜 흐름
Week 1: 50% 구현, 작동 안 함
Week 2: 80% 구현, 작동 안 함
Week 3: 100% 구현, 버그 투성이
Week 4: 디버깅...

# 좋은 흐름 (WorkingFirst)
Day 1: 작동 (기본 기능)
Day 3: 작동 (개선된 기능)
Day 5: 작동 (더 개선됨)
Day 7: 작동 (production-ready)

작동하는 상태 → 작동하는 상태 → 작동하는 상태. 이것이 BabySteps다.

Principle 6: Snowballing Growth

시니어는 작은 작동하는 것을 만들고, 거기서부터 눈덩이처럼 굴려간다(snowballing).

# Snowballing 과정
V1 (1시간):   단순 로그인 체크
V2 (2시간):   + 데이터베이스 연결
V3 (1시간):   + 암호화
V4 (2시간):   + 세션 관리
V5 (1시간):   + 토큰 발급
V6 (2시간):   + 권한 체크
V7 (1시간):   + 로깅
V8 (1시간):   + 에러 처리

총 11시간, 8개의 작동하는 버전

각 버전은 이전 버전 위에 유기적으로 성장한다. OrganicGrowth.

Real Examples

Example 1: API Integration

주니어 접근 (3일):

Day 1-2: API 문서 연구, 에러 처리 설계, 재시도 로직 계획
Day 3: 구현 시작... 하지만 API가 문서와 다르게 작동

시니어 접근 (3시간):

# 15분: 가장 단순한 호출
import requests
response = requests.get("https://api.example.com/users/1")
print(response.json())
# → 작동 확인!

# 30분: 함수로 추출
def get_user(user_id):
    response = requests.get(f"https://api.example.com/users/{user_id}")
    return response.json()

# 1시간: 에러 처리 추가 (실제 에러를 본 후)
def get_user(user_id):
    try:
        response = requests.get(
            f"https://api.example.com/users/{user_id}",
            timeout=5
        )
        response.raise_for_status()
        return response.json()
    except requests.RequestException as e:
        logger.error(f"API call failed: {e}")
        return None

# 2시간: 재시도 로직 (필요하다고 판단한 후)
@retry(max_attempts=3, backoff=2)
def get_user(user_id):
    # ...

# 3시간: production-ready

차이점:

Example 2: Data Transformation

주니어 접근:

# 완벽한 클래스 계층을 설계하려고 시도
class DataTransformer:
    def __init__(self, config, validators, formatters):
        # 어떤 변환이 필요한지도 아직 모름
        self.config = config
        self.validators = validators
        self.formatters = formatters

    def transform(self, data):
        # TODO: 구현...
        pass

시니어 접근:

# Phase 1: Work (30분)
def transform_user_data(raw_data):
    return {
        'name': raw_data['user_name'],
        'age': int(raw_data['user_age']),
        'email': raw_data['email'].lower()
    }

# 사용하면서 패턴 발견...

# Phase 2: Right (1시간)
def transform_user_data(raw_data):
    return {
        'name': extract_name(raw_data),
        'age': parse_age(raw_data),
        'email': normalize_email(raw_data)
    }

def extract_name(data):
    return data.get('user_name', data.get('name', 'Unknown'))

def parse_age(data):
    age_str = data.get('user_age', data.get('age', '0'))
    return int(age_str) if age_str.isdigit() else 0

def normalize_email(data):
    email = data.get('email', '')
    return email.lower().strip()

# 필요하면 나중에 클래스로

Example 3: Search Feature

주니어 접근 (2주):

Week 1: Elasticsearch 연구, 인덱싱 전략 설계
Week 2: 구현 시작
결과: 실제로는 간단한 SQL LIKE로 충분했음

시니어 접근 (2일):

# Day 1 아침: 작동하는 것
def search(query):
    return [item for item in items if query.lower() in item.name.lower()]

# Day 1 오후: DB로 이동
def search(query):
    return db.query(Item).filter(
        Item.name.ilike(f'%{query}%')
    ).all()

# Day 2: 성능 측정 후 인덱스 추가
# 인덱스로 충분함을 확인
# Elasticsearch 불필요

# 2주 대신 2일, Elasticsearch 대신 PostgreSQL 인덱스

차이: 작동하는 것부터 만들면서 실제 요구사항을 발견했다.

Example 4: Real Story - File Upload

실제 경험한 사례:

요구사항: "파일 업로드 기능이 필요합니다"

주니어의 계획:

시니어의 접근:

# Day 1: 로컬 파일 시스템에 저장
@app.route('/upload', methods=['POST'])
def upload():
    file = request.files['file']
    filename = secure_filename(file.filename)
    file.save(os.path.join('/uploads', filename))
    return {'file': filename}

# 작동 확인!
# 사용자 테스트...

놀라운 발견:

최종 솔루션 (Day 2):

이것이 WorkingFirst의 힘이다: 실제 요구사항을 발견한다.

Example 5: Authentication Evolution

앞의 스토리를 코드로:

# Day 1 오전: Work (20줄, 30분)
users = {"admin": "secret"}

def login(username, password):
    if users.get(username) == password:
        return {"token": username}  # 극도로 단순
    return None

# Day 1 오후: Database (30줄, 1시간)
def login(username, password):
    user = db.query(User).filter_by(username=username).first()
    if user and user.password == password:
        return {"token": generate_token(user.id)}
    return None

# Day 2: Hashing (40줄, 1시간)
def login(username, password):
    user = db.query(User).filter_by(username=username).first()
    if user and check_password_hash(user.password_hash, password):
        return {"token": generate_token(user.id)}
    return None

# Day 3: Sessions (60줄, 2시간)
def login(username, password):
    user = db.query(User).filter_by(username=username).first()
    if user and check_password_hash(user.password_hash, password):
        session = Session.create(user.id, expires_in=3600)
        return {"token": session.token, "expires": session.expires_at}
    return None

# Day 4: Error handling, logging, rate limiting...
# Day 5: Production-ready

# 5일, 각 단계마다 작동했음

Common Pitfalls

Pitfall 1: "Working" Becomes "Done"

가장 위험한 함정: 작동하면 끝이라고 생각하는 것.

# ❌ "작동하니까 됐어!"
def process_payment(amount):
    # 작동하지만... 에러 처리 없음, 로깅 없음, 트랜잭션 없음
    api.charge(card, amount)
    return True

해결: Kent Beck의 3단계를 기억하라: Work → Right → Fast. "Work"는 시작일 뿐이다.

Pitfall 2: "Simple" First Version is Still Complex

"단순한" 첫 버전이 여전히 너무 복잡하다.

# ❌ 이게 "단순"?
class SimpleAuthenticator:
    def __init__(self, db, cache, logger, config):
        self.db = db
        self.cache = cache
        self.logger = logger
        self.config = config

    def authenticate(self, credentials):
        # 100줄의 "단순한" 코드...

해결: 정말 최소한만. TinyExperiment - 가장 작은 것부터.

Pitfall 3: No Tests Along the Way

각 단계마다 테스트 없이 진행한다.

문제: "작동"을 검증할 방법이 없다. 다음 단계에서 이전 단계가 깨질 수 있다.

해결: 각 단계마다 테스트 추가. DesignThroughTest.

# Phase 1: Work + Test
def login(username, password):
    return username == "admin" and password == "secret"

def test_login():
    assert login("admin", "secret") == True
    assert login("admin", "wrong") == False

# Phase 2: Improve + Update Test
def login(username, password):
    user = db.get_user(username)
    return user and user.password == password

def test_login():
    user = User.create(username="admin", password="secret")
    assert login("admin", "secret") == True
    assert login("admin", "wrong") == False

Pitfall 4: Prototype Becomes Production

Fred Brooks의 경고를 무시하고, 프로토타입을 그대로 프로덕션에 넣는다.

문제:

해결:

# 프로토타입을 명확히 표시
def login_PROTOTYPE(username, password):
    """
    PROTOTYPE: For testing only
    TODO: Add error handling, hashing, sessions
    """
    return username == "admin" and password == "secret"

# 배운 것을 기반으로 새로 작성
def login(username, password):
    # 프로토타입에서 배운 것을 적용
    # 하지만 제대로 구현
    ...

Pitfall 5: Skipping the "Right" Phase

Work → Fast로 바로 점프한다. "Right" 단계를 건너뛴다.

# ❌ Work에서 Fast로 직행
def ugly_but_working_code():
    # 작동하지만 난장판
    pass

@cache
def ugly_but_working_code():
    # 여전히 난장판, 이제 캐싱까지
    pass

해결: 최적화 전에 정리하라. Clean code first, then optimize.

Pitfall 6: Wrong "Working" Definition

"작동"의 정의가 잘못되었다.

# ❌ 이게 "작동"?
def api_call(endpoint):
    # 성공 케이스만 작동
    return requests.get(endpoint).json()
    # 에러나면? 네트워크 끊기면? 타임아웃이면?

해결: "작동"은 핵심 flow가 end-to-end로 실행되는 것. 완벽할 필요는 없지만, 실제 사용 가능해야 한다.

Connection to Other Patterns

TinyExperiment - WorkingFirst를 위해 작은 실험들을 수행한다. 가장 작은 것이 작동하는지 확인하라. 도구

BabySteps - 작동 상태에서 다음 작동 상태로 작은 단계들로 이동한다. 실행 방법

OrganicGrowth - 작동하는 핵심에서 시스템을 유기적으로 성장시킨다. 성장 방식

TwoWorlds - 문제 공간을 이해하기 위해 해결 공간에서 작동하는 것을 만들어 실험한다. 탐색 도구

GreenRefuge - 작동하는 상태가 안전한 피난처다. 막히면 돌아갈 곳. 안전망

DetectiveWork - 작동하는 것을 만들면서 진짜 문제를 발견한다. 발견 과정

DesignThroughTest - 테스트로 "작동"을 정의하고 검증한다. 검증 방법

TightLoop - 빠르게 작동 상태에 도달해서 빠른 피드백을 받는다. 피드백 루프

ArtisanMind - 작동하는 실체를 만드는 것은 장인의 가장 기본이 되는 태도다. 정신

The95PercentRule - 일단 95%라도 작동하게 만들어라. 완벽을 기하다가 0%에 머물지 마라. 순서

AtomicCommit - 각 작동 상태를 커밋한다. 되돌릴 수 있게. 버전 관리

Contrasts With (대조)

Big Design Up Front - 실행 전 완벽한 설계 시도. WorkingFirst는 반대다.

Waterfall - 설계 → 구현 → 테스트의 순차적 진행. WorkingFirst는 반복적이다.

Analysis Paralysis - 결정하지 못하고 분석만 계속. WorkingFirst는 빠른 실행이다.

Prevents (예방)

YAGNI violations - 작동하는 것을 만들면서 실제 필요를 발견한다.

Over-engineering - 실제 복잡성을 안 후에 설계한다.

Premature Optimization - 작동 후 측정, 그다음 최적화.

Analysis Paralysis - 빠른 실행이 결정을 만든다.

Enables (가능하게 함)

DataAsFoundation - 작동하는 것을 만들면서 올바른 데이터 구조를 발견한다.

LanguageBuilding - 작동하는 코드에서 패턴을 보고 언어를 추출한다.

StrongCenter - 작동하는 핵심을 먼저 만들고 그것이 중심이 된다.

Signs of Success

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

빠른 초기 피드백 - 프로젝트 시작 후 하루 이내에 "뭔가 작동하는 것"을 볼 수 있다.

자신감 증가 - "이것은 가능하다"는 확신이 일찍 생긴다. 두려움이 줄어든다.

진짜 문제 발견 - 설계 단계에서 예상하지 못한 문제를 실행을 통해 발견한다.

덜 복잡한 최종 솔루션 - 처음 계획했던 것보다 훨씬 단순한 솔루션으로 끝난다.

빠른 iteration - 작동 → 피드백 → 개선의 사이클이 하루 단위로 돌아간다.

낮은 스트레스 - "막혔다"는 느낌이 적다. 항상 작동하는 상태에서 시작하기 때문에.

더 나은 설계 - 역설적으로, 설계를 먼저 하지 않았는데 더 나은 설계가 나온다.

팀 신뢰 - 매일 데모할 수 있는 것이 있어서 팀과 stakeholder가 진행을 본다.

For Teachers and Mentors

주니어가 바로 완벽한 설계를 하려 할 때:

멈추게 하라: "잠깐, 먼저 가장 단순한 버전이 작동하는지 확인해보자. 10분만 투자해서."

작은 목표를 제시하라:

3단계를 가르쳐라:

1. Make it work   - "작동만 하면 돼"
2. Make it right  - "이제 깔끔하게 만들자"
3. Make it fast   - "성능이 문제면 최적화하자"

성공 경험을 만들어라: "봐, 30분 만에 작동하는 걸 만들었잖아! 이제 여기서부터 개선하면 돼."

실패의 안전성을 강조하라: "이건 프로토타입이야. 나중에 버려도 돼. 지금은 배우는 게 목표야."

점진적 개선을 시연하라:

# "이렇게 단계적으로 발전시키는 거야"
V1: 하드코딩 (5분)
V2: 변수로 추출 (5분)
V3: 함수로 (10분)
V4: 에러 처리 (10분)
V5: 테스트 추가 (15분)
V6: 리팩토링 (15분)

총 1시간, 6개의 작동하는 버전

The Ultimate Insight

Kent Beck이 말했다: "Make it work, make it right, make it fast."

Donald Knuth가 경고했다: "Premature optimization is the root of all evil."

Fred Brooks가 통찰했다: "Plan to throw one away; you will, anyhow."

Chris Argyris가 가르쳤다: 의사결정은 과정이다. 탐색하고 실험하라.

George Polya가 보여주었다: 문제를 이해하는 것은 해결하면서 온다.

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

우리는 만들어보기 전에는 알 수 없다.
작동하는 것을 만드는 것은 이해의 도구다.
탐색이 설계보다 먼저다.

The Epistemology of Making

프로그래밍에서 지식은 실천을 통해 온다:

이론적 지식: "OAuth2는 인증 프로토콜이다"

실천적 지식: "이 상황에서 OAuth2를 어떻게 구현하는가"

Michael Polanyi의 말: "We know more than we can tell." 암묵적 지식(tacit knowledge)은 실천에서 온다.

The Paradox of Perfection

역설: 완벽을 추구하면 완성하지 못한다. 완성을 추구하면 완벽에 도달할 수 있다.

처음부터 완벽을 만들려는 시도는:

작동하는 것부터 만들면:

결과: 역설적으로 더 나은 설계.

The Psychology of Momentum

Newton의 제1법칙은 프로그래밍에도 적용된다:

WorkingFirst는 momentum을 만든다:

  1. 작은 작동 → 성취감
  2. 성취감 → 자신감
  3. 자신감 → 다음 단계 시도
  4. 다음 단계 → 또 작동
  5. 반복 → momentum

두려움을 극복하는 방법: 작은 작동하는 것을 만드는 것.

The Path to Mastery

시니어와 주니어의 진짜 차이는 지식의 양이 아니다. 접근 방식이다:

주니어: 완벽한 설계 → 구현 → 테스트 → 디버그 → 리팩토링

시니어: 작동 → 개선 → 작동 → 개선 → 작동 → ...

WorkingFirst는 시니어의 사고방식이다.

Summary

WorkingFirst는 탐색의 철학이다:

핵심 원칙:

왜 작동하는가:

주니어 vs 시니어:

궁극의 통찰:

작동하는 것을 만들면:
- 가능하다는 것을 안다
- 어떻게 만드는지 안다
- 진짜 문제가 무엇인지 안다
- 초기 프로토타입을 버리고 올바르게 다시 만들 수도 있다

하지만 그때는 머릿속에 어떻게 작동하게 만드는지 알고 있다.

WorkingFirst는 두려움을 극복하고, momentum을 만들고, 올바른 문제를 해결하게 하는 방법이다.

올바른 방법은 여러 가지다. WorkingFirst는 그 중 하나에 빠르게 도달하게 돕고, 거기서부터 올바른 방향으로 진화하게 한다.

"The best way to get a project done faster is to start sooner." - Jim Highsmith

지금 시작하라. 작게. 작동하게. 그다음 개선하라.


CategoryPatternLanguage CategoryProgramming CategoryTDD CategoryLearning CategoryWorkflow