강연자: 대니얼 잭슨 (Daniel Jackson) - MIT 컴퓨터 과학 교수 출처: ACM Tech Talk
"왜 소프트웨어 시스템은 설계로 인해 실패하는가, 그리고 어떻게 고칠 것인가"
미첼 카포(Mitchell Kapor)가 1996년 소프트웨어 설계 선언문에서 던진 질문:
"집을 지을 때는 기술자가 아니라 건축가와 먼저 이야기한다. 소프트웨어는 왜 그렇지 않은가?"
카포는 좋은 건물의 기준이 공학의 영역 밖에 있듯이, 소프트웨어의 구성 요소 선택도 **'사용 조건'**에 의해 주도되어야 한다고 주장했습니다.
대니얼 잭슨은 사용자가 올바른 **개념적 모델(conceptual model)**을 갖는 것이 핵심이라고 말합니다. 그는 나쁜 사례가 아니라, 대기업이 만든 최고의 제품들에서 발견되는 작은 실패들을 분석함으로써 더 나은 소프트웨어를 만드는 원칙을 찾고자 했습니다.
버그나 단순한 UI 오류가 아니라, 근본적인 설계의 문제입니다.
상황:
- 에이바(Ava)가 'BellaPlan'이라는 폴더를 벨라(Bella)와 공유합니다
- 벨라가 이 폴더 이름을 'MyPartyPlan'으로 변경합니다
문제:
- 벨라가 이름을 바꿔도 에이바에게는 바뀌지 않는 경우가 있고, 바뀌는 경우가 있습니다
- 최상위 공유 폴더를 삭제하면 "공유 폴더를 제거하시겠습니까?"라고 묻지만, 그 내부 폴더를 삭제하면 경고 없이 두 사람 모두에게서 파일이 영구 삭제될 수 있습니다
실험 결과: MIT 학부생들을 대상으로 실험한 결과, 이 동작을 정확히 예측하는 비율은 동전 던지기 수준에 불과했습니다.
상황: 2017년, 멜라니아 트럼프가 자신을 모욕하는 트윗에 '좋아요(Like)'를 눌렀다가 취소
문제: 그녀는 모욕적인 트윗을 좋아한 것이 아니라, 나중에 다시 보기 위해 '저장'하려고 했을 가능성이 높습니다. 트위터의 '좋아요(과거의 즐겨찾기)'가 공개적인 승인을 의미하는지, 개인적인 북마크를 의미하는지 혼동이 있었습니다.
상황: 사용자가 자신의 캘린더에서 이메일로 온 행사 일정을 삭제
문제: 삭제 버튼을 누르자 사용자의 의도와 달리 행사 주최자와 모든 참가자에게 **"행사가 취소되었습니다"**라는 메일이 발송
기존의 사용성(Usability) 연구(돈 노먼 등)는 사용자 심리학에서 출발하여 사용자가 인터페이스를 어떻게 해석하는지에 집중했습니다. 하지만 시스템 자체가 잘못된 동작을 한다면 아무리 좋은 UI도 소용이 없습니다.
잭슨 교수의 제안:
**"디자이너의 모델이 올바른가?"**라는 질문에서 시작해야 한다.
이는 프레드 브룩스(Fred Brooks)가 말한 **"개념적 무결성(Conceptual Integrity)"**이 시스템 디자인의 핵심이라는 주장과 일맥상통합니다.
소프트웨어의 기본 단위를 '개념'으로 정의합니다. 이는 추상 데이터 타입(ADT)이나 클래스, 데이터 모델의 엔티티와는 다릅니다.
개념을 식별하고 지식을 공유하는 데 필수적입니다.
- 예: "업보트(Upvote)", "옵저버 패턴"
해당 개념이 존재하는 이유입니다.
| 개념 | 목적 |
|---|---|
| 업보트 (Upvote) | 인기순으로 항목을 정렬 |
| 반응 (Reaction) | 저자에게 피드백 제공 (순서 변경 없음) |
| 추천 (Recommendation) | 내 취향 기반으로 다른 콘텐츠 제안 |
개념이 기능을 수행하는 데 필요한 최소한의 데이터 모델입니다.
- 개념은 '마이크로서비스' 혹은 '나노서비스'처럼 자신만의 데이터 영역을 가짐
- 예: 업보트 개념은 중복 투표 방지를 위해 '사용자' 정보를 상태에 포함해야 함
사용자가 수행할 수 있는 행위입니다.
- 예: 업보트(upvote), 다운보트(downvote), 투표 취소(unvote)
개념이 목적을 달성하는 방식을 설명하는 전형적인 시나리오입니다.
"많은 사람이 업보트를 하면, 그 항목은 목록의 상단으로 올라간다."
이는 개별 동작의 나열이 아니라, 동작과 그 결과를 연결하여 시스템의 거동을 설명합니다.
소프트웨어는 여러 개념의 조합으로 이루어집니다. 개념들을 코드로 결합(coupling)하는 대신 **동기화(Synchronization)**해야 합니다.
해커뉴스에서:
- 사용자가 글을 투표(Upvote 개념)하면 → 해당 글 작성자의 점수(Karma 개념)가 올라감
- '다운보트' 동작은 카르마가 충분할 때만 허용 → '허가(Permit)' 동작과 동기화
토니 호어(Tony Hoare)의 CSP(Communicating Sequential Processes) 아이디어에 기반하여, 각 개념을 독립적으로 유지하면서도 상호작용하게 만듭니다.
유닉스 디렉터리 모델 (실제 드롭박스 모델):
- 디렉터리는 파일 자체를 담은 상자가 아님
- '엔트리(Entry)'들의 목록일 뿐
- 각 엔트리 = '이름(Name)' + '아이템(inode)에 대한 포인터'
작동 방식:
- 최상위 공유 폴더를 공유할 때, 두 사람의 루트 디렉터리에 각각 별도의 '엔트리'가 생성 → 벨라가 이름을 바꿔도 에이바에게 영향 없음
- 하위 폴더는 공유된 디렉터리 안의 '단일 엔트리' → 이름을 바꾸면 두 사람 모두에게 변경됨
결론: 유닉스의 '하드 링크' 개념은 기술적으로 훌륭하지만, 일반 사용자의 '공유' 목적(Fit for purpose)에는 부합하지 않는 개념 선택
사용자는 '북마크' 개념이 필요했지만, 시스템에는 '좋아요(업보트)' 개념만 있었습니다. 트위터는 2018년에야 북마크 개념을 별도로 추가하여 이 문제를 해결했습니다.
'캘린더(개인 일정 관리)' 개념과 '초대(사회적 조정)' 개념이 너무 강하게 묶여 있어, 개인 캘린더에서 삭제하는 행위가 초대 취소 행위와 강제로 동기화되었습니다.
해결책: 사용자에게 두 동작을 분리할지 묻는 옵션을 제공하여 동기화를 선택적으로 만드는 것
디자인 패턴처럼 개념에 대한 지식을 담은 핸드북을 만들어 불필요한 시행착오를 줄일 수 있습니다.
| 항목 | 내용 |
|---|---|
| 관련 개념 | 추천(Recommendation), 반응(Reaction) 등과의 비교 |
| 전형적 용도 | 소셜 미디어 게시물, 뉴스 기사 댓글, Q&A 포럼 답변 |
| 디자인 변형 | 다운보트 허용 여부, 시간 가중치, 다운보트/업보트 가중치 비율 |
| 알려진 문제 | 중복 투표 방지(로그인/IP/쿠키), 저장 공간 폭발 |
| 완화 전략 | 오래된 게시물 '동결(Freeze)'하여 투표 데이터 삭제 |
| 연결된 개념 | 카르마(Karma), 세션(Session) |
선택한 개념이 해결하려는 문제의 본질과 맞는가?
각 개념은 독립적으로 이해되고 동작할 수 있어야 합니다. 개념끼리 코드 레벨에서 결합(Coupling)되지 않고, 동기화 규칙으로만 연결
사용자가 이미 알고 있는 개념을 재사용하는가?
앱을 구성하는 개념들의 목록을 만들고 자문:
- "누락된 개념(Missing Concept)은 없는가?"
- "잘못된 동기화(Bad Synchronization)는 없는가?"
개념은 기능 수행에 필요한 최소한의 데이터와 동작을 묶은 단위로 설계
- 실수로 9억 달러(약 1조 원)를 채권자들에게 이체
- 판사: "9억 달러짜리 오류를 낸 사람에게 유감을 표한다. 좋은 커리어 무브는 아니다"
- 원인: '중간 계좌(Wash account)'라는 혼란스러운 개념이 사용자로 하여금 전체 원금을 송금하게 만드는 치명적 실수를 유도
- 페이스북 '좋아요'나 업보트와 UI는 비슷하지만, 메시지 순서(랭킹)를 바꾸지 않음
- 저자에게 피드백만 제공 (연대기적 순서 유지)
- 현재 항목의 랭킹을 올리는 것이 아닌, 미래에 추천할 콘텐츠를 선별하는 '추천' 개념
- '화나요' 같은 부정적 감정도 '좋아요'와 동일하게 (5배 가중치로) 게시물 랭킹을 올림
- 사회적으로 해로운 결과를 초래한 **'나쁜 동기화'**의 사례
- 약물 주입기에서 '용량(Dosage)'과 '유속(Rate of flow)' 개념이 혼동되어 심각한 의료 사고 발생
- 사용자가 '토큰'을 단순한 비밀번호로 오해
- 토큰의 핵심 개념(취소 가능, 범위 제한 가능)을 제대로 전달 필요
UI만으로 모든 것을 설명할 수 없습니다. 사용자가 추론할 수 없는 개념은 그 목적과 작동 원리를 명시적으로 설명해야 합니다.
이름을 잘 짓는 것도 중요하지만, 근본적인 개념 자체가 잘못되었다면 이름만으로는 해결 불가 (트위터 별→하트 변경으로도 해결 안 됨)
개념이 강하게 결합(interwoven)되어 있으면 수정이 어려움. 처음부터 개념을 분리하고 동기화하는 방식으로 설계하면 유연성이 높아짐
개념은 요구사항을 조직화하고 발견하는 도구. 기존에 검증된 개념을 재사용함으로써 요구사항 정의를 더 쉽게 할 수 있음
개념 단위로 웹 서비스를 나누는 것은 마이크로서비스를 더 잘 조직화하는 방법
이 강연은 소프트웨어의 복잡성을 관리하고 사용자에게 직관적인 시스템을 만들기 위해, 코드 이전에 **설계자의 멘탈 모델(개념)**을 정립하는 것이 얼마나 중요한지를 강조합니다.
- 개념은 소프트웨어의 원자: 기능의 최소 단위는 클래스나 함수가 아니라 '개념'
- 목적이 핵심: 모든 개념에는 명확한 존재 이유가 있어야 함
- 동기화로 결합: 개념을 코드로 결합하지 말고 동기화 규칙으로 연결
- 실패는 설계에서 시작: 대부분의 사용성 실패는 UI가 아닌 개념 설계의 문제
- 핸드북으로 지식 공유: 검증된 개념을 재사용하여 시행착오를 줄임
이 문서는 Daniel Jackson 교수의 ACM Tech Talk "The Essence of Software" 강연 내용을 한글로 번역/정리한 것입니다.