소프트웨어를 빠르게 개발하는 나만의 방법

8 hours ago 1

  • 완벽함속도의 균형은 쉽지 않지만, 상황에 맞는 적정 품질기한 준수가 중요함
  • 초안(러프 드래프트) 개발을 먼저 진행하고, 이후에 코드 품질을 개선하는 방식이 효과적임
  • 요구사항을 완화하거나 과도한 요구를 줄이면 속도와 효율을 높일 수 있음
  • 산만함을 피하고 작은 단위로 자주 커밋하며, 핵심에 집중하는 습관이 필요함
  • 빠른 개발에 도움이 된 코드 읽기, 데이터 모델링, 스크립팅, 디버깅, 순수 함수 지향 등의 구체적 스킬이 있음

“얼마나 좋은 코드여야 하는가?” – 품질 기준과 현실적 선택

  • 초창기에는 모든 코드가 완벽하길 원함
    • 모든 함수가 철저히 테스트되고, 변수명이 우아하며, 추상화가 명확하고, 버그가 전혀 없는 코드를 꿈꿨음
  • 하지만 시간이 흐르며 “정답은 없다” 는 현실을 배움
    • 상황에 따라 요구되는 코드 품질이 다름
    • 24시간 게임잼: 완성된 코드가 꼭 깔끔하거나 버그가 없어야 할 필요 없음
      • 제한된 시간 내에 동작하는 결과물을 만드는 것이 더 중요함
    • 심장박동기 소프트웨어: 실수 하나가 사람의 생명을 위협할 수 있으므로
      • 최고 수준의 신뢰성과 안전성이 필수임
  • 대부분의 프로젝트는 이 두 극단 사이에 존재함
    • 어떤 회사는 빠른 납기를 요구해 약간의 버그는 허용함
    • 어떤 프로젝트는 높은 품질을 요구하지만 일정이 넉넉함
    • 실제 업무에서는 이 균형을 파악하는 능력이 중요함
    • 팀의 ‘충분히 괜찮음(good enough)’ 기준이 무엇인지를 먼저 파악함
      • 허용 가능한 버그의 범위, 완벽하지 않아도 괜찮은 부분 등 실질적 기준을 함께 점검함
  • 본인의 개인적 기준
    • “10점 만점에 8점 품질을, 기한 내에 달성” 하는 것
      • 코드는 목적을 충실히 수행하고, 치명적인 문제는 없지만 사소한 이슈는 남아 있을 수 있음
      • 가장 중요한 건 기한 내에 제출하는 것임
    • 단, 이 기준도 프로젝트의 맥락에 따라 유연하게 조정
      • 때로는 완벽을 추구해 일정이 밀려도 괜찮고,
      • 때로는 완성도는 낮아도 일단 빠르게 끝내는 편이 더 가치 있을 때가 있음

Rough drafts – 러프 드래프트, 프로토타이핑의 실제적인 활용과 장점

  • 소프트웨어 개발도 글쓰기처럼 초안(rough draft, spike, walking skeleton) 작성이 매우 유용함
  • 최대한 빠르게 러프 드래프트를 구현하고, 이후에 이를 다듬어 완성형 솔루션으로 발전시킴
  • 나의 러프 드래프트 코드는 버그 투성이이고, 테스트 실패, TODO 주석 남발, 예외 미처리, print/log 남용,
    성능 고려 없음, WIP 커밋 메시지, 불필요한 패키지 추가, 반복 코드, 하드코딩, 린터 경고 등 엉망
  • 이 과정이 비효율적으로 보이지만, “최소한 문제의 본질을 파악할 수 있는 상태” 에 도달하는 것이 목적임
  • 당연히, 이런 초안 상태의 코드를 최종 배포로 내보내지 않으며, 실제 배포 전에는 반드시 정제함
    (팀에서 초안 코드를 그대로 내보내자고 압박할 때도 있지만 최대한 저항함)
  • 러프 드래프트 접근법의 주요 장점

    • “알려지지 않은 문제(unknown unknowns)”를 빨리 드러냄
      • 완성된 후 버려지는 코드보다, 초기에 프로토타입 단계에서 미지의 장애물을 찾는 것이 훨씬 유리함
    • 프로토타입 작성 중 자연스럽게 사라지는 문제들이 많음
      • 느린 함수나 잘못된 구조도, 나중에 아예 필요 없게 되는 경우가 많아 시간 낭비를 막을 수 있음
      • 지나치게 일찍 최적화나 테스트에 힘 쏟을 필요 없음
    • 집중력을 높여줌
      • 불필요한 리팩터링, 네이밍 고민, 다른 코드베이스 고치기 등 산만함을 방지하고
        오직 현재 해결해야 하는 문제에 몰입할 수 있음
    • 불필요한 조기 추상화 방지
      • 일단 동작하는 해답을 빠르게 만드는 과정에서는 미래를 위한 불필요한 추상화를 덜 시도하게 됨
      • 당장의 문제에만 집중하여, 불필요하게 복잡한 설계를 피함
    • 진척 상황의 명확한 소통
      • 러프 드래프트를 통해 앞으로 얼마나 남았는지 정확한 예측이 가능해짐
      • 무엇이든 동작하는 것을 먼저 보여주며, 이해관계자의 피드백과 방향성 변경이 빠르게 이뤄짐
  • 러프 드래프트 실전 운영법

    • 되돌리기 어려운 결정(biding decision)은 초안 단계에서 반드시 실험
      • 예: 언어, 프레임워크, DB스키마 등 큰 방향성은 초기에 확인
    • 모든 임시방편/핵(hack)은 반드시 TODO 주석 등으로 기록
      • polish(정제) 단계에서 git grep TODO 등으로 전수 조사해 보완함
    • Top-Down(상위-하위) 순서로 개발
      • UI, API 등 사용 방식부터 scaffold(뼈대) 작성, 내부 로직은 하드코딩/임시 구현도 허용
      • 실제로는 UI/사용 경험이 정해지면서 하위 로직이 바뀌는 일이 많으므로, 상위 레이어부터 구현이 유리함
      • 하위부터 완벽히 구현 후 상위에 맞추는 방식은 비효율적임
    • 작은 변화는 따로 패치 분리
      • 러프 드래프트 도중 코드베이스 개선이나 의존성 업데이트 필요성을 발견하면,
        해당 부분만 별도 PR/커밋으로 분리해서 빠르게 반영
      • 전체 변경의 복잡도를 줄이고, 리뷰/통합 속도를 높임

참고: “코드의 첫 번째 초안은 버려라”, “지금 당장 단순한 시스템이 최고”, “YAGNI(You Aren’t Gonna Need It)

요구사항을 바꿔보려는 시도

  • 덜 하는 것이 더 빠르고 쉽다는 원칙을 강조함
  • 실제 업무에서, 주어진 과업의 요구사항을 완화할 수 있는지 항상 고민
    • 예시 질문:
      • 여러 화면을 하나로 합칠 수 있는가?
      • 까다로운 엣지 케이스를 굳이 다뤄야 하는가?
      • 1000개 입력을 지원해야 한다면 10개만 지원해도 되는가?
      • 완성형 대신 프로토타입으로 대체 가능한가?
      • 이 기능 자체를 빼버려도 되는가?
  • 이러한 접근은 개발 속도와 효율을 높임
  • 조직 문화 자체도 조금씩 더 느리고 합리적인 페이스로 유도하려고 시도함
    • 갑작스럽고 큰 변화 요구는 잘 먹히지 않음
    • 점진적인 제안, 토론 방식 전환 등으로 조금씩 분위기를 바꿈

코드에서 산만함(Distraction) 피하기

  • 외부 환경(알림, 회의) 뿐 아니라, 코드 작업 중 엉뚱한 일로 새는 것도 큰 방해 요인임
  • 나도 종종 버그를 고치다 전혀 상관 없는 곳을 뜯고 있고, 결국 원래 과제는 미루어짐
  • 두 가지 구체적 실천법:
    • 타이머 설정: 한 작업마다 시간 제한을 두고, 알람이 울리면 현재 진행 상황을 점검
      • 예상보다 시간이 더 걸릴 때 주의 환기 효과 있음
      • 알람과 동시에 git commit 하면 작은 성취감도 생김
      • (이 방법은 시간 추정 연습에도 효과적임)
    • 페어 프로그래밍: 함께 작업하면 쓸데없는 길로 새는 일 감소, 집중력 유지에 도움됨
  • 일부 개발자에겐 이런 산만함 회피가 자연스럽지만, 내겐 의식적 집중과 습관화가 필요함

작은 단위의 변경, 작게 쪼개기

  • 예전에 큰 단위의 패치, 광범위한 변경을 장려하는 상사가 있었지만
    실제로는 매우 비효율적임을 경험함
  • 작고 집중된 diff가 거의 항상 더 낫다고 느낌
    • 코드를 작성하는 데 부담이 적고
    • 코드 리뷰가 더 쉽고 빨라져 동료의 피로감도 줄고, 내 실수도 쉽게 발견됨
    • 문제가 생겼을 때 롤백이 쉽고 안전함
    • 한 번에 바꾸는 범위가 작으므로 신규 버그 발생 위험도 감소함
  • 큰 기능/기능 추가도 작은 변경의 축적으로 완성
    • 예: 화면 추가가 필요하다면, 버그 수정/의존성 업그레이드/기능 추가를 각각 별도 패치로 분리
  • 작은 단위의 변화가 더 빠르고 높은 품질의 소프트웨어 개발에 도움이 된다고 강조함

빠른 개발에 정말 도움이 된 구체적인 스킬들

위에서 언급한 내용들은 다소 추상적이지만, 실제로 빠른 개발에 효과적인 실전 스킬도 존재함

  • 코드 읽기(Reading code) : 지금까지 습득한 가장 중요한 개발자 역량

    • 기존 코드를 능숙하게 해석할 수 있으면, 디버깅이 훨씬 쉬워지고
    • 오픈소스/서드파티 라이브러리의 버그나 부족한 문서도 크게 두렵지 않게 됨
    • 타인의 코드를 읽으며 배우는 양도 엄청나고, 전반적인 문제 해결 능력 향상에 직접적 도움을 줌
  • 데이터 모델링(Data modeling) : 시간이 걸려도 데이터 모델을 제대로 설계하는 것이 중요함

    • 잘못 설계된 데이터베이스 스키마는 나중에 다양한 문제와 복잡한 수정 비용을 초래함
    • 유효하지 않은 상태 자체를 아예 표현할 수 없도록 설계하는 것이 버그를 원천적으로 줄임
    • 데이터가 저장되거나 외부와 주고받는 경우엔 더더욱 신중해야 함
  • 스크립팅(Scripting) : Bash, Python 등으로 짧은 스크립트를 빠르게 작성하는 능력은 개발 효율을 극대화함

    • 매주 여러 번씩, 마크다운 정렬, 데이터 정리, 파일 중복 찾기 등 자동화 작업에 활용
    • Bash는 Shellcheck 같은 도구로 문법 오류를 사전에 예방함
    • Robust하지 않아도 되는 작업엔 LLM의 도움을 받아 빠르게 완성 가능
  • 디버거(Debuggers) 활용 : 디버거 사용은 print/log만으로는 불가능한 신속한 문제 진단과 코드 흐름 파악에 필수적임

    • 복잡한 버그의 근본 원인 파악이 훨씬 빨라짐
  • 적절히 쉬는 타이밍 : 막힐 때는 과감하게 휴식을 취하는 습관

    • 장시간 고생해도 못 푸는 문제가, 5분 쉬었다가 바로 풀리는 경험이 빈번함
    • 집중의 효율성을 위해서도 중요함
  • 순수 함수와 불변 데이터 지향 : 함수형 프로그래밍: 순수 함수와 immutable data를 선호하면

    • 버그 감소, 상태 추적 부담 감소, 코드의 명확성/예측성 증가
    • 복잡한 클래스 계층 설계보다 더 단순하고 효과적인 경우가 많음
    • 반드시 항상 가능한 건 아니지만, 기본적으로 이 방식을 먼저 고려함
  • LLM(대규모 언어 모델) 활용 : LLM(예: ChatGPT 등) 은 단점도 있지만, 반복적이거나 자동화가 가능한 개발 업무에서 큰 속도 향상을 가져옴

    • 자신의 코드에 LLM을 접목하는 방법과 한계를 충분히 이해한 뒤 적극 활용 중
    • 커뮤니티의 다양한 경험과 팁, 사례도 참고함
      이 모든 스킬들은 오랜 시간 반복적으로 연습해왔고, 실제로 빠른 개발에 큰 자산이 되었음

요약

  • 내가 소프트웨어를 빠르게 개발하며 얻은 핵심 교훈은 다음과 같음
    • 과제별로 필요한 코드 품질 기준을 명확히 파악
    • 러프 드래프트(초안)를 빠르게 작성해 전체 윤곽을 잡음
    • 요구사항을 완화할 수 있는 여지를 항상 탐색
    • 산만함에 휘둘리지 않고 집중력을 유지
    • 변경은 작고 자주 커밋하며, 큰 패치는 피함
    • 구체적 실전 스킬(코드 읽기, 데이터 모델링, 디버깅, 스크립팅 등)을 꾸준히 연습
  • 모두 너무 당연해 보이지만, 실제로 이 교훈을 얻기까지 오랜 시간이 걸렸음

Read Entire Article