Skip to content
Published on

실용주의 철학과 엔지니어링: 완벽주의를 넘어서는 의사결정 프레임워크

Authors
  • Name
    Twitter

실용주의 철학과 엔지니어링

서론: 완벽주의라는 이름의 함정

소프트웨어 엔지니어는 본질적으로 완벽주의에 끌리는 직업이다. 코드는 논리적이어야 하고, 시스템은 견고해야 하며, 아키텍처는 우아해야 한다. 이런 기질은 장점이기도 하지만, 때로는 가장 치명적인 약점이 된다.

한 팀이 새로운 API 게이트웨이를 설계한다고 하자. 아키텍트는 모든 엣지 케이스를 처리하고, 완벽한 추상화 계층을 갖추며, 향후 5년간의 확장성까지 고려한 설계를 원한다. 3개월이 지났지만 설계 문서만 50페이지가 넘고, 코드는 한 줄도 작성되지 않았다. 그 사이 경쟁사는 이미 출시하고 고객 피드백을 반영한 두 번째 버전을 내놓았다.

이것이 바로 완벽주의의 함정이다. 완벽을 추구하다가 아무것도 완성하지 못하는 상태, 19세기 미국의 실용주의 철학자들은 이 문제를 이미 간파했다.

"진리의 기준은 실제적 결과이다. 어떤 차이도 만들어내지 않는 차이는 차이가 아니다." - 윌리엄 제임스

이 글에서는 윌리엄 제임스(William James)와 존 듀이(John Dewey)의 실용주의(Pragmatism) 철학을 소프트웨어 엔지니어링에 적용하여, 완벽주의의 함정에서 벗어나 실질적 가치를 극대화하는 의사결정 프레임워크를 제시한다.


1장: 실용주의 철학의 핵심 원리

윌리엄 제임스 - 진리는 결과로 판단한다

윌리엄 제임스는 1907년 출간한 Pragmatism에서 진리의 새로운 정의를 제시했다. 전통 철학이 "진리란 현실과의 일치"라고 정의한 것과 달리, 제임스는 **"진리란 실제로 작동하는 것"**이라고 주장했다.

"어떤 관념이 참이 되는 것은 그것이 우리의 경험에서 실제로 작동할 때이다. 진리는 사건이다. 관념은 참이 되는 것이지, 원래부터 참인 것이 아니다." - 윌리엄 제임스, Pragmatism

이 원칙을 엔지니어링에 적용하면 다음과 같다.

  • 이론적으로 완벽한 아키텍처보다 실제로 작동하는 시스템이 더 가치 있다
  • 설계 문서의 우아함보다 프로덕션에서의 안정성이 진짜 기준이다
  • 모든 가능성을 고려한 추상화보다 현재 문제를 해결하는 코드가 우선이다

존 듀이 - 경험을 통한 학습

존 듀이는 Experience and Education(1938)에서 지식은 경험과 실험을 통해 구축된다고 주장했다. 이론을 먼저 완성한 뒤 적용하는 것이 아니라, 행동하고 피드백을 받으며 이론을 수정해나가는 과정 자체가 학습이라는 것이다.

"우리는 행동함으로써 배운다. 실수를 통한 학습이 추상적 사고보다 더 효과적이다." - 존 듀이

이것은 현대 소프트웨어 개발 방법론의 핵심과 정확히 일치한다.

존 듀이의 경험적 학습 사이클 vs 애자일 개발

듀이의 학습 사이클:
  1. 문제 인식 (Problematic Situation)
  2. 가설 수립 (Hypothesis)
  3. 실험 (Experimentation)
  4. 결과 관찰 (Observation)
  5. 반성과 수정 (Reflection)

애자일 개발 사이클:
  1. 유저 스토리/요구사항 정의
  2. 설계 및 계획
  3. 구현 (Sprint)
  4. 리뷰 및 데모
  5. 회고 (Retrospective)

공통점: 계획-실행-학습의 반복 순환
핵심: 완벽한 계획 없이도 시작할 수 있다

찰스 샌더스 퍼스 - 의미의 명확화

실용주의의 창시자 찰스 샌더스 퍼스(Charles Sanders Peirce)는 **실용주의 격률(Pragmatic Maxim)**을 제시했다. "어떤 개념의 의미를 명확히 하려면, 그 개념이 실제 행동에 어떤 결과를 가져오는지를 생각하라."

이것을 엔지니어링 토론에 적용하면 강력한 도구가 된다.

퍼스의 실용주의 격률 적용 - 기술 토론 정리법

팀 논쟁: "마이크로서비스가 좋은가, 모놀리스가 좋은가?"

실용주의적 질문:
  "이 선택이 실제로 어떤 차이를 만드는가?"

구체적 점검:
  1. 배포 빈도가 달라지는가? -> 현재 주 1회, 목표 일 3회
  2. 팀 독립성이 달라지는가? -> 현재 4팀이 하나의 코드베이스 공유
  3. 장애 격리가 달라지는가? -> 현재 하나의 장애가 전체 시스템 영향
  4. 운영 복잡도가 달라지는가? -> 현재 DevOps 인원 2명

결론:
  추상적 논쟁을 멈추고, "실제로 어떤 차이를 만드는가"에 집중하면
  팀 상황에 맞는 답이 명확해진다.

2장: 완벽주의 vs 실용주의 - 엔지니어링 비교

근본적 차이

완벽주의와 실용주의의 차이는 단순히 "품질을 포기하느냐"의 문제가 아니다. 어디에 에너지를 집중하느냐의 문제다.

관점완벽주의적 접근실용주의적 접근
목표결함 없는 시스템가치를 전달하는 시스템
설계모든 시나리오를 미리 고려현재 알려진 요구사항에 집중
코드 품질매 줄이 최적화핵심 경로에 집중 투자
출시 기준모든 테스트 통과, 모든 엣지 케이스 처리핵심 기능 동작, 치명적 결함 없음
리팩터링한번에 완전한 재작성점진적 개선, Boy Scout Rule
기술 선택최고의 도구를 찾을 때까지 비교충분히 좋은 도구로 시작
문서화완벽한 문서가 되기 전에는 공개 안 함불완전해도 공유, 점진적 보완
실패 대응실패를 용납하지 않음실패를 학습 기회로 활용

의사결정 속도와 품질 트레이드오프

결정 유형완벽주의 소요 시간실용주의 소요 시간품질 차이실용주의 판정
프로그래밍 언어 선택2-3주 비교 분석3일 핵심 기준 평가미미빠른 결정 유리
데이터베이스 스키마완벽 정규화 2주1주 후 마이그레이션 계획 포함초기 약간 낮음, 장기 동등빠른 시작 유리
API 인터페이스모든 엔드포인트 사전 정의 3주핵심 3개 먼저, 나머지 점진 추가동등빠른 피드백 유리
클라우드 인프라멀티 리전 HA 완벽 구성 1개월단일 리전 시작, 필요 시 확장초기 낮음, 비용 절감상황에 따라 다름
모니터링 구축모든 메트릭 대시보드 완성 후 배포핵심 5개 알림 먼저, 점진 확장동등빠른 가시성 확보 유리

3장: 실전 의사결정 도구

도구 1: 되돌릴 수 있는 결정 판별법

Amazon CEO였던 제프 베조스는 2015년 주주 서한에서 의사결정을 두 가지 유형으로 분류했다. 이것은 실용주의 철학의 현대적 적용이다.

되돌릴 수 있는 결정 판별 매트릭스

Type 1 Decision (되돌릴 수 없는 결정):
  특성: 한번 결정하면 되돌리기 어렵거나 비용이 매우 큼
  접근: 신중하게, 충분한 데이터와 합의를 통해 결정
  예시:
    - 프로그래밍 언어 전면 교체
    - 데이터베이스 엔진 마이그레이션 (Oracle -> PostgreSQL)
    - 클라우드 벤더 변경 (AWS -> GCP)
    - 핵심 아키텍처 패턴 변경 (모놀리스 -> 마이크로서비스)
    - 오픈소스 라이선스 변경

Type 2 Decision (되돌릴 수 있는 결정):
  특성: 잘못되어도 쉽게 되돌릴 수 있음
  접근: 빠르게 결정하고, 결과를 보고 조정
  예시:
    - 새 라이브러리/프레임워크 도입 (특정 모듈에만)
    - 코딩 컨벤션 변경
    - CI/CD 파이프라인 도구 교체
    - A/B 테스트 설계
    - 내부 도구 선택 (Slack vs Teams)
    - 피처 플래그로 제어되는 새 기능

판별 체크리스트:
  [ ] 이 결정을 되돌리는 데 1주일 이상 걸리는가?
  [ ] 되돌릴 때 데이터 손실이 발생하는가?
  [ ] 외부 고객에게 직접적 영향을 미치는가?
  [ ] 다른 팀이나 시스템에 연쇄적 변경이 필요한가?
  [ ] 계약이나 비용 약정이 수반되는가?

  3개 이상 Yes -> Type 1 (신중하게)
  2개 이하 Yes -> Type 2 (빠르게 결정)

도구 2: RICE 우선순위 프레임워크

RICE는 Intercom이 만든 우선순위 프레임워크로, 실용주의 철학의 "실제적 결과로 판단하라"는 원칙을 정량화한 도구다.

RICE 스코어 계산

RICE = (Reach * Impact * Confidence) / Effort

각 항목 정의:
  Reach (도달 범위): 일정 기간 내 영향받는 사용자/거래 수
    - 예: 분기당 10,000명의 사용자에게 영향 -> R = 10,000

  Impact (영향도): 개별 사용자에 미치는 영향 정도
    - 3 = 매우 큼 (massive)
    - 2 = 큼 (high)
    - 1 = 보통 (medium)
    - 0.5 = 작음 (low)
    - 0.25 = 매우 작음 (minimal)

  Confidence (확신도): 추정의 정확도
    - 100% = 높은 확신 (데이터 기반)
    - 80% = 중간 확신 (일부 데이터)
    - 50% = 낮은 확신 (직감)

  Effort (노력): 인-월(person-months) 단위의 작업량
    - 예: 2명이 3주 작업 -> E = 1.5

실전 예시:
  프로젝트 A - 결제 페이지 성능 개선
    R = 50,000 (분기 방문자)
    I = 2 (전환율 직접 영향)
    C = 80%
    E = 2 (인-월)
    RICE = (50,000 * 2 * 0.8) / 2 = 40,000

  프로젝트 B - 관리자 대시보드 리뉴얼
    R = 50 (내부 사용자)
    I = 1 (업무 효율 보통 향상)
    C = 50%
    E = 4 (인-월)
    RICE = (50 * 1 * 0.5) / 4 = 6.25

  결론: 프로젝트 A가 압도적 우선순위 (40,000 vs 6.25)

도구 3: 기술 선택 체크리스트

실용주의 관점에서 기술 선택은 "최고의 기술"이 아니라 "지금 우리에게 가장 적합한 기술"을 고르는 것이다.

실용주의 기술 선택 체크리스트

1단계: 문제 정의 (What)
  [ ] 해결하려는 구체적 문제가 명확한가?
  [ ] 성공 기준이 정량적으로 정의되어 있는가?
  [ ] 현재 기술로 정말 해결할 수 없는가?

2단계: 팀 역량 평가 (Who)
  [ ] 팀 내 해당 기술 경험자가 있는가?
  [ ] 학습 곡선을 감당할 시간적 여유가 있는가?
  [ ] 채용 시장에서 해당 기술 인력을 구할 수 있는가?

3단계: 생태계 점검 (Where)
  [ ] 프로덕션 레퍼런스가 충분한가?
  [ ] 커뮤니티가 활성화되어 있는가?
  [ ] 문서화가 잘 되어 있는가?
  [ ] 서드파티 라이브러리가 풍부한가?

4단계: 비용 분석 (How Much)
  [ ] 라이선스 비용은 적정한가?
  [ ] 인프라 비용은 예측 가능한가?
  [ ] 마이그레이션 비용을 계산했는가?
  [ ] 유지보수 비용을 고려했는가?

5단계: 리스크 평가 (What If)
  [ ] 벤더 락인 리스크는 어느 정도인가?
  [ ] 해당 기술이 중단되면 대안이 있는가?
  [ ] 보안 취약점 대응 체계가 갖춰져 있는가?
  [ ] 되돌릴 수 있는 결정인가? (Type 1 vs Type 2)

점수: 각 항목 Yes = 1점
  20점 만점 중 15점 이상: 도입 추천
  10-14점: 파일럿 프로젝트로 검증 후 결정
  10점 미만: 보류 또는 재검토

도구 4: 빠른 프로토타이핑 워크플로우

존 듀이의 "경험을 통한 학습" 원칙을 직접 적용한 워크플로우다.

실용주의 프로토타이핑 워크플로우 (5일 스프린트)

Day 1 (월): 문제 정의와 가설 수립
  오전: 이해관계자 인터뷰 (30분 x 3명)
  오후: 핵심 가설 3개 정의
  산출물: 1페이지 문제 정의서

Day 2 (화): 최소 설계
  오전: 화이트보드 아키텍처 (완벽할 필요 없음)
  오후: 핵심 데이터 모델 및 API 3개만 정의
  산출물: 간단한 시스템 다이어그램

Day 3-4 (수-목): 구현
  원칙:
    - 가장 중요한 기능 하나만 동작하게 만든다
    - 에러 처리는 최소한으로 (happy path only)
    - UI는 기본 스타일만 적용
    - 하드코딩 허용 (나중에 설정으로 분리)
    - 테스트는 핵심 시나리오 1개만
  산출물: 동작하는 프로토타입

Day 5 (금): 검증과 학습
  오전: 이해관계자 데모
  오후: 피드백 정리 및 다음 단계 결정
  판단 기준:
    - GO: 핵심 가설 검증됨 -> 본 개발 진행
    - PIVOT: 방향 수정 필요 -> 다음 주 재시도
    - KILL: 가치 없음 확인 -> 다른 프로젝트로 전환
  산출물: 의사결정 문서 (1페이지)

윌리엄 제임스의 관점:
  "이 프로토타입이 실제로 작동하는가?"가 유일한 판단 기준이다.
  아름다운 코드나 완벽한 아키텍처는 그 다음 문제다.

도구 5: 의사결정 매트릭스 (가중치 기반)

의사결정 매트릭스 예시: 메시지 큐 선택

평가 기준 (가중치):
  성능 처리량    (25%)
  운영 난이도    (25%)
  팀 경험       (20%)
  생태계 성숙도  (15%)
  비용          (15%)

점수 (1-5):
  항목          | Kafka | RabbitMQ | SQS
  성능 처리량    |  5    |    3     |  3
  운영 난이도    |  2    |    3     |  5
  팀 경험       |  2    |    4     |  3
  생태계 성숙도  |  5    |    4     |  4
  비용          |  2    |    3     |  4

가중 점수:
  Kafka:    5*0.25 + 2*0.25 + 2*0.20 + 5*0.15 + 2*0.15 = 3.20
  RabbitMQ: 3*0.25 + 3*0.25 + 4*0.20 + 4*0.15 + 3*0.15 = 3.35
  SQS:      3*0.25 + 5*0.25 + 3*0.20 + 4*0.15 + 4*0.15 = 3.80

실용주의적 결론:
  SQS가 가장 높은 점수 (3.80)
  "최고 성능"의 Kafka가 아닌 "가장 적합한" SQS 선택
  완벽한 기술이 아닌, 충분히 좋은 기술을 선택한다

4장: 실패 사례에서 배우는 교훈

사례 1: 과도한 설계 (Over-Engineering)

사례: 스타트업 A의 마이크로서비스 도입

상황:
  - 시리즈 A 스타트업, 개발자 8명
  - DAU 5,000명의 B2B SaaS 제품
  - CTO가 "확장성을 위해 마이크로서비스를 도입하자"고 결정

진행:
  - 3개월간 Kubernetes 클러스터 구축
  - 서비스 메시(Istio) 도입
  - 분산 트레이싱(Jaeger) 설정
  - 이벤트 드리븐 아키텍처(Kafka) 구현
  - 서비스 12개로 분리

결과:
  - 운영 복잡도 5배 증가
  - 인프라 비용 월 300만원 -> 1,200만원
  - 8명 중 3명이 인프라 운영에만 매달림
  - 신규 기능 개발 속도 50% 저하
  - 6개월 후 모놀리스로 롤백 결정

실용주의적 교훈:
  윌리엄 제임스: "실제로 작동하는가?"
    -> DAU 5,000에 마이크로서비스는 과잉이었다
  존 듀이: "경험에서 배웠는가?"
    -> 롤백 자체가 귀중한 학습이었다
  퍼스: "이 선택이 실제로 어떤 차이를 만드는가?"
    -> 확장성 문제가 아직 존재하지 않았다

올바른 접근:
  1. 모놀리스를 잘 구조화 (모듈러 모놀리스)
  2. 병목이 발생하는 부분만 분리
  3. DAU 50,000 도달 시 마이크로서비스 재검토

사례 2: 분석 마비 (Analysis Paralysis)

사례: 기업 B의 프론트엔드 프레임워크 선정

상황:
  - 대기업 사내 플랫폼 팀, 개발자 15명
  - 레거시 jQuery 기반 어드민 시스템 리뉴얼
  - 프레임워크 선택 필요

진행:
  - 1주차: React, Vue, Angular, Svelte 비교 문서 작성
  - 2주차: 각 프레임워크로 PoC 제작 (4명 투입)
  - 3주차: 성능 벤치마크, 번들 사이즈 비교
  - 4주차: 보안 취약점 분석, 라이선스 검토
  - 5주차: 외부 컨설턴트 자문
  - 6주차: 팀 내 투표 (결과: React 8표, Vue 7표로 결론 안 남)
  - 7주차: 재투표, 프레임워크별 장단점 재정리
  - 8주차: 최종 결정... 여전히 미결

문제:
  - 2개월간 실질적 진전 없음
  - 팀 사기 저하, "결정 좀 내리자" 불만
  - 그 사이 jQuery 시스템에서 보안 이슈 2건 발생
  - 경영진의 신뢰 하락

실용주의적 교훈:
  윌리엄 제임스: "어떤 차이도 만들어내지 않는 차이는 차이가 아니다"
    -> React와 Vue의 차이는 이 프로젝트에서 의미 있는 차이를 만들지 않았다

  올바른 접근:
    1. 핵심 기준 3개만 정의 (팀 경험, 생태계, 채용)
    2. 3일 내 결정 (Type 2 Decision - 되돌릴 수 있음)
    3. 작은 모듈로 시작, 문제가 있으면 전환
    4. "충분히 좋은" 선택으로 빠르게 시작

사례 3: 황금 도금 (Gold Plating)

사례: 엔지니어 C의 로깅 라이브러리 개발

상황:
  - 시니어 엔지니어가 팀 내부용 로깅 라이브러리 개발 담당
  - 예상 기간: 2주
  - 요구사항: 구조화된 로그 출력, 로그 레벨 지원

진행:
  - 1-2주: 기본 기능 구현 완료
  - 3주: "로그 집계 기능도 추가하면 좋겠다"
  - 4주: "로그 회전(rotation)도 직접 구현하자"
  - 5주: "분산 트레이싱 ID도 자동 삽입하자"
  - 6주: "플러그인 아키텍처를 만들어서 확장 가능하게 하자"
  - 7주: "성능 벤치마크 스위트도 포함시키자"
  - 8주: 아직 코드 리뷰도 받지 못한 상태

결과:
  - 2주 예상 작업이 8주로 확장
  - 추가 기능 대부분 실제로 사용되지 않음
  - 코드 복잡도 증가로 유지보수 부담
  - 결국 팀에서 기존 오픈소스 라이브러리(Zap, Logrus 등) 채택

실용주의적 교훈:
  YAGNI 원칙: 지금 필요하지 않은 기능을 미리 구현하지 않는다
  2주차에 멈추고 배포했다면 6주의 시간을 절약했다
  완벽한 라이브러리보다 충분히 좋은 라이브러리가 팀에 더 유용하다

5장: Good Enough 엔지니어링

"충분히 좋은"의 기준 정립

The Pragmatic Programmer(David Thomas, Andrew Hunt)에서는 "Good Enough Software"라는 개념을 소개한다. 이것은 품질을 포기하라는 뜻이 아니다. "어디에 얼마만큼의 품질을 투자할 것인가"를 의식적으로 선택하라는 뜻이다.

Good Enough 기준 설정 가이드

1. 핵심 기능 (Must Have)
   품질 수준: 높음 (테스트 커버리지 90% 이상)
   기준: 사용자 핵심 가치를 전달하는 기능
   예시: 결제 처리, 인증, 데이터 저장

2. 중요 기능 (Should Have)
   품질 수준: 중간 (테스트 커버리지 70% 이상)
   기준: 사용자 경험을 향상시키는 기능
   예시: 검색 필터, 알림, 대시보드

3. 부가 기능 (Nice to Have)
   품질 수준: 기본 (테스트 커버리지 50% 이상)
   기준: 있으면 좋지만 없어도 되는 기능
   예시: 테마 설정, 고급 통계, 내보내기 형식 다양화

4. 미래 기능 (YAGNI)
   품질 수준: 구현하지 않음
   기준: 현재 요구되지 않은 기능
   예시: "나중에 필요할 수도 있는" 추상화 레이어

80/20 법칙의 적용

파레토 법칙(80/20 법칙)은 실용주의 철학의 정량적 표현이다.

소프트웨어 엔지니어링의 80/20 법칙

코드 품질:
  전체 코드의 20%가 버그의 80%를 포함한다
  -> 핵심 모듈에 코드 리뷰 집중

성능 최적화:
  전체 코드의 20%가 실행 시간의 80%를 차지한다
  -> 프로파일링 없이 최적화하지 않는다

기능 사용:
  전체 기능의 20%를 사용자의 80%가 사용한다
  -> 핵심 20% 기능을 먼저 완성한다

테스트:
  전체 테스트의 20%가 버그의 80%를 잡아낸다
  -> 핵심 시나리오 테스트에 집중한다

실용주의적 결론:
  모든 것을 동일한 수준으로 완벽하게 하려는 것은
  비효율적일 뿐 아니라 불가능하다.
  핵심 20%에 80%의 에너지를 집중하라.

6장: 실용주의 의사결정 프레임워크 (PRAGMATIC)

앞서 다룬 모든 원칙을 하나의 종합 프레임워크로 정리한다.

PRAGMATIC 의사결정 프레임워크

P - Problem First (문제부터 정의하라)
  "해결하려는 문제가 무엇인가?"
  문제가 불명확하면 어떤 해결책도 올바를 수 없다.
  퍼스의 격률: 실제 행동에 어떤 결과를 가져오는가?

R - Reversibility Check (되돌릴 수 있는가?)
  "이 결정은 Type 1인가, Type 2인가?"
  Type 2라면 70%의 정보로 결정한다.
  베조스: "대부분의 결정은 되돌릴 수 있다."

A - Acceptable Minimum (수용 가능한 최소 기준)
  "충분히 좋은 수준은 어디인가?"
  완벽이 아닌 Good Enough를 목표로 한다.
  The Pragmatic Programmer: "Good Enough Software"

G - Gather Evidence (증거를 수집하라)
  "데이터가 무엇을 말하는가?"
  직감이 아닌 데이터에 기반하여 판단한다.
  RICE 프레임워크로 정량화한다.

M - Move Fast (빠르게 움직여라)
  "지금 시작할 수 있는 가장 작은 단계는?"
  분석 마비에 빠지지 않는다.
  존 듀이: 행동함으로써 배운다.

A - Adapt Continuously (지속적으로 적응하라)
  "결과를 보고 조정할 준비가 되어 있는가?"
  계획에 집착하지 않는다.
  제임스: 진리는 결과로 검증된다.

T - Time-box (시간 제한을 두어라)
  "이 결정에 얼마나 시간을 쓸 것인가?"
  결정의 중요도에 비례하는 시간만 투자한다.
  Type 2 결정에 2주를 쓰지 않는다.

I - Impact Focus (영향에 집중하라)
  "이 결정이 실제로 얼마나 중요한가?"
  80/20 법칙: 핵심 20%에 집중한다.
  파레토: 모든 결정이 동등한 가중치를 갖지 않는다.

C - Communicate (소통하라)
  "결정의 근거와 맥락을 공유했는가?"
  ADR 작성, 팀과 투명하게 공유한다.
  결정 과정의 투명성이 신뢰를 만든다.

PRAGMATIC 프레임워크 적용 예시

시나리오: 새 프로젝트의 인증 시스템 구축 방식 결정

P (문제 정의):
  사용자 인증/인가가 필요하다.
  소셜 로그인, 이메일 인증, 역할 기반 접근 제어.

R (되돌릴 수 있는가?):
  인증 시스템은 핵심 인프라 -> Type 1에 가까움.
  단, Auth0/Cognito 같은 SaaS는 교체 가능 -> Type 2 요소 있음.
  판정: Type 1.5 - 신중하되 과도하지 않게.

A (수용 가능한 최소 기준):
  MVP 기준: 이메일/비밀번호 로그인 + JWT 토큰
  2차: 소셜 로그인 추가
  3차: RBAC(역할 기반 접근 제어)

G (증거 수집):
  자체 구현 vs SaaS 비교
  자체 구현: 4주 소요, 보안 리스크, 유지보수 부담
  Auth0: 월 23달러, 즉시 사용 가능, 보안 전문팀 관리

M (빠르게 움직여라):
  Auth0로 1주 내 MVP 인증 완성.
  사용자 100,000명 초과 시 자체 구현 재검토.

A (지속 적응):
  월별 사용량과 비용 모니터링.
  한계 도달 시 마이그레이션 계획 수립.

T (시간 제한):
  이 결정에 3일 투자. (Type 1.5이므로 신중하되 빠르게)

I (영향 집중):
  인증은 핵심이지만, 비즈니스 로직이 더 중요하다.
  인증에 4주를 쓰면 핵심 기능 개발이 4주 지연된다.

C (소통):
  ADR-001로 문서화.
  "Auth0 선택 이유와 자체 구현 전환 기준"을 팀에 공유.

7장: 일상에서의 실용주의 실천

코드 리뷰에서의 실용주의

실용주의 코드 리뷰 가이드

반드시 지적해야 하는 것 (Must Fix):
  - 보안 취약점
  - 데이터 손실 가능성
  - 성능에 심각한 영향을 미치는 코드
  - 명백한 논리 오류

지적하되 선택에 맡기는 것 (Suggestion):
  - 더 나은 알고리즘 제안
  - 가독성 개선 사항
  - 테스트 추가 권장

지적하지 않는 것 (Nitpick - 자동화):
  - 코딩 스타일, 포매팅 -> Linter에 위임
  - import 순서 -> 자동 정렬 도구 사용
  - 변수명 취향 차이 -> 팀 컨벤션이 없다면 무시

원칙:
  "이 코멘트가 실제로 어떤 차이를 만드는가?"
  차이를 만들지 않는 피드백은 피드백이 아니라 소음이다.

기술 부채 관리의 실용주의

기술 부채 실용주의 분류법

의도적 부채 (Deliberate):
  "이 접근이 최선은 아니지만, 출시 일정을 맞추기 위해 선택한다."
  관리법: 티켓으로 등록, 1-2 스프린트 내 해결 계획

비의도적 부채 (Inadvertent):
  "나중에 보니 더 좋은 방법이 있었다."
  관리법: 발견 즉시 기록, 관련 작업 시 함께 개선 (Boy Scout Rule)

방치된 부채 (Reckless):
  "일단 되니까 넘어가자. 나중에 누군가 고치겠지."
  관리법: 이것만은 막아야 한다. 코드 리뷰에서 차단.

실용주의적 규칙:
  - 모든 기술 부채를 즉시 갚으려 하지 않는다
  - 이자율이 높은 부채(보안, 성능)를 먼저 갚는다
  - 매 스프린트의 20%를 부채 상환에 할당한다
  - "완벽한 코드베이스"는 목표가 아니다. "지속 가능한 코드베이스"가 목표다

8장: 실용주의 엔지니어 체크리스트

매일 업무를 시작하기 전, 다음 체크리스트로 실용주의적 사고를 점검하자.

일일 실용주의 체크리스트

의사결정 점검:
  [ ] 오늘 내릴 결정 중 Type 1과 Type 2를 구분했는가?
  [ ] Type 2 결정을 불필요하게 오래 고민하고 있지 않은가?
  [ ] "충분히 좋은" 기준을 명확히 정의했는가?

작업 점검:
  [ ] 현재 작업이 사용자에게 실제 가치를 전달하는가?
  [ ] YAGNI 위반이 없는가? (필요하지 않은 것을 만들고 있지 않은가?)
  [ ] 80/20 법칙에 따라 핵심에 집중하고 있는가?

소통 점검:
  [ ] 결정의 근거를 팀에 공유했는가?
  [ ] "왜 이 방식을 선택했는가"를 설명할 수 있는가?
  [ ] 코드 리뷰에서 실질적 피드백만 남기고 있는가?

학습 점검:
  [ ] 오늘의 실수에서 무엇을 배웠는가?
  [ ] 내일 더 나은 결정을 내릴 준비가 되었는가?
  [ ] 완벽주의에 빠져 있지는 않은가?
주간 회고 질문 (실용주의 버전)

1. 이번 주에 "충분히 좋은" 수준에서 멈추고 전달한 것은?
   -> 제대로 멈췄는가? 너무 일찍/늦게 멈추지는 않았는가?

2. 이번 주에 분석 마비에 빠진 순간은?
   -> 어떻게 빠져나왔는가? 다음에는 어떻게 예방할 것인가?

3. 이번 주에 YAGNI를 위반한 것은?
   -> 필요하지 않은 것을 만들었다면 왜 그랬는가?

4. 이번 주 의사결정 중 데이터에 기반한 것과 직감에 기반한 것의 비율은?
   -> 데이터 기반 비율을 높일 수 있는가?

5. 윌리엄 제임스의 질문: "이 결정이 실제로 어떤 차이를 만들었는가?"

9장: 실전 퀴즈

아래 퀴즈를 통해 실용주의 원칙의 이해도를 점검해보자.

Q1: 팀에서 새 프로젝트의 ORM을 선택하는 데 2주째 논의 중이다. 실용주의적으로 어떻게 접근해야 하는가?

A: 이것은 전형적인 분석 마비(Analysis Paralysis) 사례다. ORM 선택은 대부분 Type 2 Decision(되돌릴 수 있는 결정)에 해당한다. 핵심 기준 3개(팀 경험, 성능, 생태계)만으로 평가하고, 3일 내에 결정한다. 팀에서 가장 익숙한 ORM으로 시작하고, 문제가 발생하면 그때 전환을 검토한다. 윌리엄 제임스의 관점에서 "이 ORM들의 차이가 실제 프로젝트에서 의미 있는 차이를 만드는가?"를 먼저 질문해야 한다.

Q2: "Good Enough Software"는 품질을 포기하라는 뜻인가?

A: 아니다. Good Enough는 "모든 곳에 동일한 품질을 적용하지 말고, 중요도에 따라 품질 투자를 차등화하라"는 의미다. 결제 시스템의 보안은 최고 수준이어야 하지만, 관리자 페이지의 UI 정렬은 기본 수준이면 충분하다. 핵심은 의식적으로 "어디에 얼마만큼의 품질을 투자할 것인가"를 선택하는 것이다.

Q3: YAGNI 원칙과 확장성 설계는 모순되는가?

A: 모순되지 않는다. YAGNI는 "현재 필요하지 않은 구체적 기능을 미리 구현하지 말라"는 것이지, "확장 가능한 구조를 만들지 말라"는 뜻이 아니다. 예를 들어, 다국어 지원 기능을 미리 구현하는 것은 YAGNI 위반이지만, 문자열을 하드코딩하지 않고 상수로 분리하는 것은 좋은 설계 습관이다. 실용주의적 접근은 "확장 가능한 구조는 갖추되, 확장 자체는 필요할 때 하라"는 것이다.

Q4: Amazon의 Type 1과 Type 2 Decision의 차이는?

A: Type 1 Decision은 되돌릴 수 없거나 되돌리는 비용이 매우 큰 결정이다. 클라우드 벤더 변경, 프로그래밍 언어 전면 교체 등이 해당한다. 이런 결정은 신중하게, 충분한 데이터와 합의를 통해 내려야 한다. Type 2 Decision은 되돌릴 수 있는 결정이다. 라이브러리 선택, 내부 도구 교체 등이 해당한다. 이런 결정은 70%의 정보만으로도 빠르게 내리고, 결과를 보고 조정해야 한다. 대부분의 엔지니어링 결정은 Type 2에 가깝다.

Q5: 존 듀이의 "경험을 통한 학습"이 애자일 방법론과 어떻게 연결되는가?

A: 존 듀이는 지식이 추상적 사고가 아닌 "경험과 실험의 반복"을 통해 구축된다고 주장했다. 이것은 애자일의 핵심 원칙과 정확히 일치한다. 스프린트를 통한 반복 개발, 회고를 통한 프로세스 개선, 고객 피드백을 통한 제품 방향 수정 모두 듀이의 경험적 학습 사이클의 현대적 구현이다. 완벽한 계획을 세운 뒤 실행하는 폭포수 모델은 듀이가 비판한 "경험 없는 추상적 사고"에 해당한다.


결론: 실용주의 엔지니어의 길

실용주의 철학의 핵심 메시지는 단순하다. "실제로 작동하는가?" 이 질문이 모든 의사결정의 출발점이어야 한다.

완벽주의는 종종 두려움의 다른 이름이다. 실패에 대한 두려움, 비판에 대한 두려움, 불완전함에 대한 두려움. 실용주의는 이런 두려움을 인정하면서도, 행동하지 않는 것이 가장 큰 리스크임을 가르친다.

윌리엄 제임스는 이렇게 말했다.

"행동이 항상 행복을 가져다주지는 않을 수 있다. 그러나 행동 없이는 행복도 없다."

소프트웨어 엔지니어링에서도 마찬가지다. 완벽한 코드를 작성하지 못할 수 있다. 그러나 코드를 작성하지 않으면 아무 가치도 전달할 수 없다. 충분히 좋은 코드를 빠르게 전달하고, 피드백을 받아 개선하는 것이 실용주의 엔지니어의 길이다.

오늘부터 다음 질문을 습관화해보자.

  1. 이 결정은 되돌릴 수 있는가? (Type 1 vs Type 2)
  2. "충분히 좋은" 수준은 어디인가? (Good Enough)
  3. 이 작업이 실제로 어떤 차이를 만드는가? (Pragmatic Maxim)
  4. 지금 시작할 수 있는 가장 작은 단계는? (Move Fast)
  5. 완벽주의에 빠져 있지는 않은가? (YAGNI)

"완벽을 기다리지 말라. 충분히 좋은 것을 지금 전달하고, 내일 더 나아지면 된다." - 실용주의 엔지니어의 신조


참고 문헌

  • William James, "Pragmatism: A New Name for Some Old Ways of Thinking" (1907) - Project Gutenberg
  • John Dewey, "Experience and Education" (1938) - Amazon
  • David Thomas, Andrew Hunt, "The Pragmatic Programmer: 20th Anniversary Edition" (2019) - pragprog.com
  • Jeff Bezos, "2015 Letter to Shareholders" - aboutamazon.com
  • Sean Ellis, "Hacking Growth" (2017) - RICE 프레임워크의 실전 적용
  • Kent Beck, "Extreme Programming Explained" (2004) - YAGNI 원칙의 원전
  • Martin Fowler, "Is High Quality Software Worth the Cost?" (2019) - martinfowler.com
  • Charles Sanders Peirce, "How to Make Our Ideas Clear" (1878) - peirce.org
  • Intercom, "RICE: Simple prioritization for product managers" - intercom.com