20P by kciter1 2일전 | favorite | 댓글 4개
  • 소프트웨어는 많은 것이 불확실하다.
  • 불확실한 이유는 무엇일까?
    • 가장 큰 이유는 비즈니스의 복잡성이 존재하기 때문
    • 복잡성으로 인해 상황은 계속해서 변하며 이로 인해 개발자의 예측은 높은 확률로 틀린다.
    • 공들인 탑이 무너져 그대로 기술부채로 변한다.
    • 작은 이유는 지식과 경험의 부족 때문
    • 지식과 경험이 없다면 개발자 스스로 만들어낸 기술부채를 만들 수 있음
    • 비즈니스의 복잡성은 개발자가 통제할 수 없는 외부 요인, 반면 지식과 경험은 개발자가 통제할 수 있는 내부 요인
  • 개발자에게는 세 가지 길이 있음
    • 복잡성에 대항하는 것은 무의미하다고 생각하는 염세주의적 길
      • ’어차피 변경될테니 그냥 하자’, ‘기술은 무의미해’와 같은 말을하게 됨
      • 편하고 안락한 길이기에 자신도 모르게 이 길을 선택 할 수 있음
    • 복잡성을 외면하고 이상적인 가상만을 생각하는 길
      • 자신이 이상적이라 생각하는 한 가지 기술로 모든 것을 해결할 수 있다고 믿음
      • 경직되고 획일화된 사고를 가지게 됨
      • 개발자는 쉽게 빠질 수 있는 길이지만 빠져나오기 힘듬
    • 복잡성을 받아들이고 맞서 싸우는 길
      • 완벽할 수 없다는 것을 받아들여도 계속 더 나은 길을 찾으려 하는 것
      • 어렵고 견뎌야하는 길
    • 소프트웨어 개발은 계속해서 복잡성과 싸워왔음
      • 아키텍처, 방법론, 애자일 등…
      • 다음은 무엇이 등장할까?
  • 파괴 지향 개발
    • 현실을 보면 어차피 지워진다라는 염세주의적 생각에 빠지기 쉽다.
    • 우리가 열심히 작성한 코드가 실패작이라 느끼며 스스로 지우는 것은 매우 고통스럽기 때문
    • 차라리 거꾸로 생각하여 차라리 잘 지울 수 있게 만드는 것은 어떨까?
  • 파괴는 좋은 것인가?
    • 파괴가 없다면 새로운 것은 탄생할 수 없음
    • 소프트웨어에서 볼 수 있는 파괴는 크게 두 가지 - 피벗과 리팩터링
    • 피벗은 조직과 제품이 더 나은 길을 선택할 수 있게 해줌
    • 리팩터링은 소프트웨어의 생명은 더 연장하기 위해서 꼭 필요한 일
  • 그래서 파괴 지향 개발이란?
    • 언젠가 코드가 파괴될 것이라는 사실을 받아들이고, 그것을 지향하여 개발하는 방법론
    • 세 가지 대원칙을 지향
      • 불확실성이 있다면 가능한 만큼 불확실성을 줄인다.
      • 여러 방법을 선택할 수 있다면 파괴하기 쉬운 쪽을 선택한다.
      • 필요한 것만을 유지한다. 따라서 필요 없는 것은 전부 지운다.
    • 분석 -> 경계 분리 -> 코드 구현 -> 복잡성 제거
    • 내부 요인에 따른 불확실성을 줄이고 어쩔 수 없는 외부 요인으로 인한 파괴에 대비하는 것이 핵심
  • 경계 분리
    • 불확실성은 변화율이며 이를 기반으로 분리하는 것이 가능
    • 개발자는 외부 요인에 대비하며 최대한 내부 요인으로 인한 변화율을 줄여야 함
    • 각 요인의 변화율은 조직마다 다를 수 있기 때문에 고정적인 수치로 표현하는 것은 불가능 -> 휴리스틱한 방법으로 측정
      • ex) 스토리 포인트 측정
    • 무엇을 기준으로 분리할지 추상화 레벨을 결정해야함
  • 파괴 가능성
    • 구현을 할 때는 대원칙에 따라 파괴하기 쉬운 쪽을 선택
    • 독립성, 인지가능성, 통제가능성을 고려하여 파괴 가능성을 판단할 수 있음
      • 독립성은 결합도와 응집도의 정도, 단일 책임 원칙을 어느정도로 지켰는지로 판단
      • 인지가능성은 개발자가 코드를 보고 이해할 수 있는 정도
      • 통제가능성은 개발자가 통제할 수 있는 영역인지를 판단
  • 복잡성 제거
    • 불필요한 것이 있는지 확인하고 제거해야 한다. 즉, 최종적으로 코드베이스엔 필요한 것만을 남겨야 함
    • 마감일 등에 대한 문제로 인해 작업하는 것이 어렵다면 기록만 해두고 작업해도 문제는 없음
      • 내부 요인은 통제 가능하기 때문
    • 파괴에 대비하여 최대한 단순성을 유지하는 것이 핵심
  • 코드 파괴의 기술
    • 코드를 잘 지우는 여러 원칙과 방법이 있음
    • 단계 쪼개기 (리팩터링 패턴)
    • 참조 투명성 지키기
    • 단일 책임 원칙 지키기
    • 인터페이스 분리 원칙 지키기
    • 스트랭글러 무화과 패턴
    • 메서드 전문화
    • 중복 코드 작성
    • 변화율 기록

지식과 경험이 부족해서 코드 부채를 만든다는 말은 별로 공감이 안가네요

-> 요구사항 구현에 주어진 시간이 모자랄 수도 있고, 협업하는 경우 타인과 조화를 위해 약간의 기술부채를 감내하는 경우도 있고 상황은 다양하다고 생각합니다.

지식과 경험을 개발자가 통제할 수 있는 내부 요인으로 보는 것도 잘 모르겠어요

-> 비즈니스는 복잡해서 어떤 상황이 닥쳐올지 예측할 수 없는데 모든 경우의 수를 그때그때 공부할 수도 없죠. 그 상황에 닥쳐서 공부를 하더라도 다음번엔 전혀 새로운 문제가 발생해 지식이 쓸모없어질 수도 있고요.

글 잘 읽었습니다. 조직의 스테이지에 따라 무엇이 이른 최적화고 오버엔지니어링이냐도 달라지는 듯 해요. 어차피 다시 짜야할 코드기도 하면서 다시 짤 순간이 올지 안올지도 모르는 코드라는게 어려운 지점이네요. 저는 xxx 서비스, 기능이 없어진다 했을 때 yyy 코드, 데이터는 어디에 있는게 적절한가? 라는 질문으로 판단할 때도 있는데 다른 분들의 방법도 궁금하네요.

코드 말고도 데이터나 스키마도 없어지거나 변경될 수 있는지 생각하는 편입니다

  1. DB 스키마, 프로토콜(REST API 같은), 기능 세 가지 분류 중 코드가 어디에 해당하는지 생각합니다. 스키마와 프로토콜은 필연적으로 회사 내부의 코드나 외부에 전파되기 때문에 나중에 바꾸려면 혼자 며칠만에 해결할 수 없고 협업이 필요하게 됩니다. 따라서 설계 단계에서 시간을 좀 더 씁니다
  2. 코드가 다루는 데이터의 라이프사이클과 휘발성을 생각합니다. winterjung님께서 고민하시는 서비스가 없어질때의 상황도 포함이 될 것 같네요. OLTP에서 얘기하는 원장, 거래, 이력 테이블 분류도 이런 고민을 시작해보는 방법이 될 수 있을 것 같습니다

데이터에 대한 내용도 넣고 싶었는데 잘 떠올리기 어렵더라구요. 크리티컬한 부분이라 쉽게 건드리기 어렵고 자칫 마이그레이션 지옥에 빠질 수도 있어서 조심스러웠습니다.

말씀하신 것처럼 처음 설계 단계가 매우 중요한 것 같은데요, RAW를 최대한 잘 쌓게 만드는 것이 핵심일 것 같습니다. 아니면 이벤트 소싱 아키텍처가 삭제라는 측면에선 유리할 수 있겠네요. 물론 해당 아키텍처를 제대로 써본 적이 없어서 정말 유효할지는 잘 모르겠습니다.