잘못된 추상화보다 중복을 선호하라: 유연한 설계를 위한 전략적 중복
잘못된 추상화보다 중복을 선호하라: 유연한 설계를 위한 전략적 중복
한 줄 요약
성급하게 공통점을 찾아 묶는 '잘못된 추상화'는 수정 불가능한 복잡성을 낳으므로, 차라리 중복을 허용하며 요구사항의 본질이 드러날 때까지 기다리는 것이 장기적으로 유지보수 비용을 낮추는 길이다.
원문 핵심 내용
추상화의 함정과 '잘못된 경로'의 메커니즘
개발자는 본능적으로 중복을 싫어하며, 비슷한 코드 조각을 발견하면 이를 하나의 메서드나 클래스로 묶어 이름(추상화)을 붙이려 합니다. 하지만 이 과정에서 '우연한 유사성'을 '본질적 동일성'으로 착각하는 오류가 발생합니다.
- 실패의 흐름: 중복 발견 $\rightarrow$ 공통 함수 추출 $\rightarrow$ 새로운 요구사항 등장 $\rightarrow$ 기존 추상화를 유지하기 위해 매개변수(Parameter) 추가 $\rightarrow$ 내부 조건문(If/Else) 증폭 $\rightarrow$ 코드의 가독성 상실 및 취약성 증가.
- 비유: 모든 동물에게 '소리 내기'라는 공통 기능을 부여했는데, 나중에 '짖기', '야옹하기', '침묵하기' 등 개별 특성이 너무 강해져서
소리내기(동물종류, 기분, 상황)라는 복잡한 매개변수를 계속 추가하는 꼴입니다. 결국 이 함수는 어떤 동물에게도 맞지 않는 기괴한 괴물이 됩니다.
매몰 비용 오류(Sunk Cost Fallacy)와 심리적 저항
잘못된 추상화가 무서운 이유는 그것이 '투자'로 인식되기 때문입니다.
- 심리적 기제: 코드가 복잡하고 이해하기 어려울수록, 개발자는 무의식적으로 "이렇게 복잡한 걸 구현했으니 매우 중요하고 가치 있는 코드일 것"이라고 착각합니다.
- 결과: 이미 들인 노력이 아까워 잘못된 구조를 깨부수기보다, 그 위에 덧칠(조건문 추가)을 하는 방식을 택하게 됩니다. 이는 시스템을 '진화의 막다른 길'로 몰아넣는 치명적인 선택이 됩니다.
해결책: 가장 빠른 전진은 '뒤로 가기(Inlining)'
잘못된 추상화의 징후(과도한 매개변수, 복잡한 조건 분기)가 보인다면, 과감하게 인라이닝(Inlining)을 수행해야 합니다.
- 작동 방식: 공통 함수를 호출하던 모든 곳에 그 함수 내용을 다시 복사해서 넣고(중복 재도입), 각 호출부에서 필요 없는 조건문과 코드를 삭제합니다.
- 효과: 억지로 묶여 있던 코드들이 각자의 고유한 경로를 찾게 됩니다. 이렇게 중복된 상태에서 다시 관찰하면, 이전에는 보이지 않았던 진짜 공통점이 드러나며, 이때 다시 추출하는 추상화는 훨씬 견고하고 단순합니다.
Hacker News 커뮤니티 반응
댓글 처리 기록: HN 댓글 3개 뭉치(약 100여 개 이상의 논점)를 분석하여 핵심 갈등과 통찰을 추출함.
1. 추상화의 적정 타이밍과 '3의 법칙'
- 핵심 주장: 무조건적인 중복도 위험하며, 추상화의 '골든 타임'을 잡는 것이 중요하다.
- 근거/사례:
cyberax,ghosty141등은 'Rule of Three'를 제시합니다. 코드가 2번 중복될 때는 지켜보고, 3번째 반복될 때 비로소 공통 패턴을 추출하는 것이 안전하다는 실무적 경험칙입니다. - 내 판단: 추상화는 '예측'이 아니라 '관찰의 결과'여야 합니다. 2번까지는 우연일 수 있지만, 3번은 패턴일 가능성이 높습니다.
2. '외형적 유사성' vs '의미적 동일성'의 구분
- 핵심 주장: 코드가 똑같이 생겼다고 해서 같은 기능을 하는 것이 아니다.
- 근거/사례:
Akronymus,ubertaco는 '우연한 유사성(Similarity by coincidence)'을 경고합니다. 결제 로직과 회원가입 로직이 우연히 같은 DB 저장 방식을 쓴다고 묶어버리면, 나중에 결제 로직만 바뀔 때 회원가입 로직까지 영향을 받는 '강결합' 상태가 됩니다. - 반론/대댓글:
lg5689는 데이터의 단일 진실 공급원(SSOT) 원칙을 강조하며, 데이터가 불일치할 때 버그가 되는 지점이라면 무조건 추상화하여 한 곳에서 관리해야 한다고 맞섭니다. - 내 판단: '로직의 중복'은 허용하되, '데이터의 진실(Truth)'은 하나여야 합니다. 로직은 다를 수 있지만, 기준 데이터가 달라지면 그것은 시스템 붕괴입니다.
3. 중복의 위험성: "나쁜 추상화라도 제어는 가능하다"
- 핵심 주장: 중복을 방치하면 나중에 수정할 때 수백 군데를 찾아 고쳐야 하는 재앙이 온다.
- 근거/사례:
dofm은 하청업체가 짠 중복 쿼리 수백 개 때문에 DB 버전 업그레이드 시 며칠 밤을 새운 사례를 듭니다.hedora는 인증 로직을 복사-붙여넣기 했다가 일부 누락되어 대규모 데이터 유실이 발생한 경험을 공유합니다. - 내 판단: 원문의 주장(중복 $\rightarrow$ 추상화)은 '설계 단계'의 유연성을 말하는 것이고,
dofm의 우려는 '운영 단계'의 관리 비용을 말하는 것입니다. 즉, "유연하게 중복하되, 관리 가능한 범위 내에서 추상화하라"는 합의점으로 수렴됩니다.
4. LLM(AI) 시대의 새로운 비용 구조
- 핵심 주장: AI가 코드를 짜주는 시대에는 중복의 비용이 낮아지므로 추상화 기준이 더 엄격해져야 한다.
- 근거/사례:
dang,fpoling은 LLM이 중복 코드를 빠르게 찾아내고 일괄 수정하는 능력이 뛰어나므로, 굳이 복잡한 추상화로 뇌를 고생시킬 필요가 없다고 주장합니다. - 반론/대댓글:
more-coffee는 LLM의 컨텍스트 윈도우(한 번에 읽는 양) 제한 때문에, 너무 많은 중복 코드는 오히려 AI가 전체 맥락을 파악하는 것을 방해할 것이라 반박합니다. - 내 판단: AI는 '코드 작성' 비용은 낮췄지만, '코드 검증' 비용은 높였습니다. 추상화가 너무 없으면 AI가 짠 수만 줄의 중복 코드 중 어디가 틀렸는지 인간이 검증할 수 없게 됩니다.
5. 실무자의 구체적 증언: "오버엔지니어링의 사회학"
- 대표 주장:
throwaway2037은 지루하고 단순한 결정을 내리는 것은 커리어(이력서)에 도움이 안 되기 때문에, 엔지니어들이 '지적 허영심'을 채우기 위해 오버엔지니어링(과한 추상화)을 한다는 날카로운 분석을 내놓습니다. - 추가 사례:
Waterluvian은 게임 개발 중EverythingLoader라는 만능 로더를 만들려다 포기하고 각각의 로더를 만든 것이 결과적으로 훨씬 효율적이었다고 증언합니다.
새로운 시각
추상화는 '압축'이 아니라 '인터페이스'의 설계다
많은 개발자가 추상화를 '코드 라인 수를 줄이는 압축(Compression)'으로 오해합니다. 하지만 진정한 추상화는 "어디까지가 바뀌어도 괜찮은가"라는 경계를 설정하는 인터페이스 설계입니다. 원문과 댓글을 종합하면, 추상화의 목적은 '재사용'이 아니라 '교체 가능성(Replaceability)'에 있어야 합니다.
'전략적 중복'이라는 개념의 도입
중복을 단순히 '실수'나 '게으름'으로 보는 것이 아니라, 미래의 불확실성에 대응하기 위한 '옵션 비용'으로 보는 관점이 필요합니다. 지금 당장 추상화하는 것은 미래의 변경 가능성을 차단하는 '베팅'과 같습니다. 반면 중복을 유지하는 것은 나중에 더 정확한 추상화를 할 수 있는 '권리'를 사는 행위입니다.
자녀와 미래에 대한 시사점
다음 세대를 위한 교육: '정답'보다 '수정 가능성'
미래의 아이들은 AI와 함께 협업하며 거대한 시스템을 다루게 될 것입니다. 이때 중요한 것은 "한 번에 완벽한 설계를 하는 능력"이 아니라, "잘못된 설정을 빠르게 발견하고 되돌릴 수 있는 용기와 능력(Reversibility)"입니다. '정답'을 맞히는 교육보다, '틀렸을 때 어떻게 효율적으로 되돌릴 것인가'를 가르치는 것이 더 중요해질 것입니다.
의료 분야로의 확장: '표준 진료 지침'과 '개별 맞춤 치료'의 균형
의료 현장에서도 '표준 진료 지침(Clinical Guideline)'은 일종의 추상화입니다. 모든 환자에게 적용되는 공통 분모를 뽑아낸 것이죠. 하지만 환자의 개별 특성(Comorbidity)이 강해질 때, 지침을 억지로 적용하려 하면(매개변수 추가/조건문 증폭) 위험한 결과가 나옵니다.
- 시사점: 표준 지침(추상화)을 유지하되, 환자의 특이성이 임계점을 넘으면 과감히 표준에서 벗어나 '개별 맞춤형 접근(중복/인라이닝)'을 택하는 유연함이 필요합니다. "표준이니까 따라야 한다"는 매몰 비용 오류가 의료 사고의 원인이 될 수 있음을 경계해야 합니다.