새로운 기능 개발 전, 물음표 살인마 되기

Broccolism·2024년 1월 21일
7

이제 갓 시작한 서비스를 만들면 새로운 기능 개발을 주로 하게 된다. 이전과 비슷한 기능을 만들 때는 큰 고민 없이 바로 코드를 적어나갈 수 있겠지만 그렇지 않은 경우도 있다. 웹페이지의 요청을 처리하는 API 서버 개발만 하다가 매일 1번씩 실행되어야 하는 배치 애플리케이션을 개발해야하는 순간처럼 말이다. 서버의 형태가 완전히 달라지는 것만큼 큰 변화는 아니더라도 새로운 공통 모듈이 필요하거나 새로운 메세지 처리 방식이 필요할 때도 있다. 이럴 때 우리는 바로 키보드 앞으로 달려가 코드를 짜기 전에, 질문을 먼저 해야 한다.

질문 하기 전에: trade-off

질문을 던지면서 항상 생각해야 할 것은 '모든 것은 트레이드 오프'라는 사실이다.

소프트웨어 아키텍처 101 1장 서론 中

  • 소프트웨어 아키텍처의 모든 것은 다 트레이드오프다. (소프트웨어 아키텍처 제1법칙)
  • 아키텍트가 트레이드오프가 아닌 뭔가를 발견했다고 생각하면 그것은 그가 아직 트레이드오프를 발견하지 못했다는 증거일 가능성이 높다. (제1정리)

모든 기준을 충족할 수 있는 완벽한 시스템은 존재할 수 없다. 적어도 지금 내가 아는 선에서는 그렇다. 어떤 시스템이나 기능이 성능, 일관성, 확장성 등 수많은 기준을 100%로 달성할 수는 없다. 그런걸 생각해냈다면 분명 무언가 놓친게 있을 것이다. 아무리 생각해도 놓친게 없다면 당장 스택오버플로우, 깃허브, 레딧 등 전세계 개발자 커뮤니티에 널리 전파하도록 하자.

질문들

첫 번째 질문: 요구사항 파악하기

요구사항 파악하기. 기능 개발의 시작점이다. 가장 많이 하고, 중요하고, 간단해보이지만 제대로 해내기 쉽지 않은 것이다. 요구사항에는 이런 항목들이 포함된다.

  • 인풋과 아웃풋: '기능'이 받아서 처리할 데이터와 이 기능이 제대로 동작했을 때 기대되는 결과
  • 전달 방법: 이 기능이 어떤 방식으로 제공되어야 하는지.
    • 때로는 코드를 적지 않고도 요구사항을 만족할 수 있는 경우도 있다.
      • 예를 들어 '사용자가 서비스 사용법에 대해 질문하고 답변을 받을 공간이 필요합니다' 라는 요구사항이 들어왔을 때, 팀 규모가 크지 않아 고객센터를 만들 시간이 없다면 GitHub Discussions를 질의응답 공간으로 사용하는 것도 좋은 방법이다.
  • 제약사항: 기능 자체에 대한 설명은 아니지만 기능이 가져야 하는 성질을 설명한다.
    • 성능: 어느 정도의 네트워크 지연이 있어도 괜찮은지
      • 피드를 노출하기 전까지 어느 정도의 로딩 시간이 허용되는지, 버튼을 클릭했을 때 동작이 완료되기까지 시간이 얼마나 걸려도 되는지
    • 규모: 어느 정도의 요청을 처리할 수 있어야 하는지, 어느 정도의 데이터를 저장할 수 있어야 하는지
      • 동시에 몇 TPS까지 처리할 수 있어야 하는지, 매일 적재하는 데이터 양이 대략 어느정도로 예측이 되는지
    • 정확성: 어느 정도 수준의 일관성을 보장해야 하는지
      • Eventual consistency 최종적 일관성을 보장하기만 하면 되는지, 혹은 strong consistency 강력한 일관성을 보장해야 하는지
    • 보안: 개인정보가 포함된 데이터를 다루어야 하는지, 암호화가 필요한 데이터가 있는지

기능 개발하는 사람이 직접 요구사항을 정하는 경우도 있고 다른 사람 혹은 다른 팀이 요구사항을 전달하는 경우도 있다. 요구사항을 만드는 사람과 개발하는 사람이 같은 사람이라고 해서 방심해서는 안 된다. 스스로에게 위 질문을 던져보면서 정확하게 어떤 기능이 필요한지 구체화 할 필요가 있다. 다른 사람으로부터 요구사항을 받을 때에도 마찬가지다. 요구사항을 파악하는 단계의 핵심은 질문이다.

모두가 물음표 살인마가 되어야 한다. 첫째는 요구사항을 처음 만드는 사람도 미처 고려하지 못한 부분이 있을 수 있기 때문이고 둘째는 요구사항에 따라 전체적인 설계도안이 크게 달라질 수 있기 때문이다.

🧐 아쉬운 예

🤷🏻‍♂️: 우리 사이트에 쪽지 기능을 추가할거에요. 사용자들은 서로 쪽지를 주고받을 수 있고, 각자의 쪽지 보관함으로 관리할 수 있어야 해요. 화면 디자인은 여기에 있어요.
💁🏻‍♀️: 언제까지 되어야 하나요?
🤷🏻‍♂️: 3달 뒤에 런칭하고 싶어요.
💁🏻‍♀️: 오 넵. 바로 개발 착수하겠습니다!

🤗 좋은 예

🤷🏻‍♂️: 우리 사이트에 쪽지 기능을 추가할거에요. 사용자들은 서로 쪽지를 주고받을 수 있고, 각자의 쪽지 보관함으로 관리할 수 있어야 해요. 화면 디자인은 여기에 있어요.
💁🏻‍♀️: 쪽지는 얼마나 빨리 전달되어야 하나요? 거의 실시간이어야 하나요?
🤷🏻‍♂️: 그럴 필요는 없고 1분 내로만 도착하면 돼요.
💁🏻‍♀️: (그러면 굳이 실시간 DB 안 쓰고 원래 쓰던거 그대로 써도 되겠군. 네트워크 지연도 크게 고려하지 않아도 되겠어.)
💁🏻‍♀️: 쪽지 보관함 화면에서 보낸 사람 닉네임을 클릭하면 프로필로 이동하는건가요?
🤷🏻‍♂️: 네 맞습니다.
💁🏻‍♀️: 그렇다면 만약 그 사람이 탈퇴한 회원이면 어떻게 되나요?
🤷🏻‍♂️: 오 그건 미처 생각하지 못했네요. 좀 더 보완해서 기획서와 디자인 페이지에 반역해놓겠습니다.
... (오고가는 수많은 물음표들) ...
💁🏻‍♀️: 개발 기간은 어느정도 있을까요?
🤷🏻‍♂️: 3달 뒤에 런칭하고 싶어요.
💁🏻‍♀️: 현재 개발 인원과 리소스, 개발 범위 등을 고려하면 ~~~ 가능할 것 같아요!

두 번째 질문: 얼마나 효용이 있는 작업인가

  • 내가 개발한 기능이나 모듈이 향후에 얼마나 많이 쓰일 것인가?
  • 개발에 드는 비용(시간과 노동력)에 비해 얼마나 큰 효과를 낼 것인가?
  • 요구사항을 충족하기 위해 얼마나 deep한 기술을 사용할 것인가?
  • 예상되는 미래의 요구사항을 얼마나 커버할 수 있도록 만들 것인가?

이런 질문을 하는 이유는 단순하다. 비용이 정해져있기 때문이다. 우리는 한정된 시간과 유한한 노동력을 갖고 일한다. 그 누구도 하루를 48시간으로 늘리거나 일주일에 168시간이 넘는 시간을 일할 수 없다. 이건 우리가 게을러서가 아니라, 물리적인 한계가 있기 때문이다. (만약 이 한계를 깰 수 있는 방법이 있다면 제발 알려주세요)

그렇다면 우리는 작업의 효율성을 따져봐야 한다. 하루 실사용자가 10명밖에 없는데 대규모 분산 시스템을 구축하기 위해 하둡 공식 문서를 뒤지고 있으면 곤란하다.

💁🏻‍♂️: "아니 언제는 확장성을 고려하라면서요?

그건 맞다. 하지만 적절한 시기가 있는 것이다. 트위터 예시를 보자.

트위터

진화적 아키텍처 7장 진화 가능한 아키텍처 구축 中

  • 트위터는 출시일을 앞당기기 위해 루비 온 레일즈를 이용해 개발됐다. 그러나 트위터 플랫폼은 트위터의 성장세를 감당하기에는 확장성이 부족했기에, 이후 빈번하게 장애를 일으키고 ...(중략)... 초창기 트위터 사용자는 이 그림에 나타난 고래 그림이 익숙할 것이다.
    ...
  • 만일 트위터 엔지니어가 출시 전부터 최종적이고 견고한 플랫폼을 구축했다면 제때 시장에 진출하지 못했을 것이다. 만일 그랬다면 트위터가 지연된 만큼 Snitter 등의 단문 메시징 서비스가 먼저 등장해 시장을 선점했을지도 모를 일이다.

개발을 하면서 매 순간 최선을 다해 '가장 좋은 선택'을 하지만 시간이 지나고나면 본인이 짠 코드를 보면서 의문을 갖게 되는 경우가 많다. '도대체 왜 이렇게 짠거야? 다르게 해도 됐을텐데.'라는 생각으로 히스토리를 뒤지다보면 당시에는 그게 제일 나은 선택이라서 그랬던 경우가 많다. 다만 상황이 바뀌는 것일 뿐이다. 트위터가 유명해지고 몇년 뒤에 트위터에 입사한 신입 개발자가 있다면 이렇게 질문했을 것이다. '도대체 왜 루비 온 레일즈를 선택한거야? 트래픽이 이렇게나 많은데말이야.' 하지만 처음부터 견고하고 강력한 서버 체계를 구축하느라 시간을 너무 많이 쏟았다면 그정도 트래픽을 받아볼 일이 없었을지도 모른다.

세 번째 질문: 팀의 컨벤션을 따르는가

왜 이런 질문을 던지냐하면, 팀으로 일하기 때문이다. 팀은 마치 하나의 무언가처럼 움직여야 한다. 여기서 말하는 팀은 1인 개발자도 포함된다. 과거의 나, 현재의 나, 그리고 미래의 나. 이렇게 셋이서 한 팀이다.

컨벤션이 중요한 이유는 팀 구성원이 계속 바뀌기 때문이다. (물론, 1인 개발자도 이 문장의 '팀'에 해당된다. 앞서 말했듯이 과거의 나, 현재의 나, 미래의 나 이렇게 3명으로 구성된 팀이다.) 계속되는 변화 속에서 이미 개발된 기능은 여전히 잘 작동해야 한다. 새롭게 개발될 기능도 잘 동작해야한다. 시스템을 유지보수하는 사람은 무엇이 어떻게 돌아가는지 빠르고 정확하게 파악할 수 있어야한다. 다른 사람이 짠 코드리뷰를 한 경험이 있다면 바로 와닿을 것이다. 코드를 이해하는데 불필요한 잡음과 변수를 최대한 없애야한다.

잡음이나 변수를 발견하기 위해서는 이런 질문을 던져보는게 좋다.

  • 같은 코드 포메터를 사용하는가
    • 코드 포메터는 코드를 예쁘게 보기 위해 사용하는게 아니다. 가독성을 높이고 통일된 모양을 갖게 하기 위해 사용하는 것이다.
      • 알고보니 바꾼 내용은 하나도 없지만 포멧팅만 깨진 파일의 코드 리뷰를 하고 있었을 때를 떠올려보자. 함정카드가 따로 없다.
        • (더 심각한 경우는 '바꾼 내용은 하나도 없고 포멧팅만 깨져 보이는데, 사실 아주 적은 양이지만 파급력이 큰 변화가 일어난 경우' 이다.)
  • 하나의 개념을 하나의 용어로 통일해서 지칭하는가
    • '쪽지 보내기' 기능을 말할 때 create, send, post 중 어떤 단어를 쓸 것인지 팀원들과 미리 협의하자.
      • 그 전에 '쪽지'를 어떤 단어로 지칭할 것인지 먼저 정해졌어야 한다. 그렇지않으면 각자의 '쪽지' 라는 단어로 소통을 하게 될 것이고 모두가 합의하지 않은 단어가 데이터베이스 스키마명이 될 것이다.
  • 동일한 케이스 스타일(case style)을 사용하는가
    • 자바에서 메소드명에 케밥 케이스 사용하기
    • C++에서 함수명에 카멜 케이스 사용하기
    • ... 뭐 이것까지는 용납이 된다. 용납하기 어려운 것은 '우리 팀은 메소드명에 카멜 케이스 쓰지만 나는 스네이크 케이스 쓰기' 같은 것이다.
  • 비슷한 개발 패턴을 따르는가
    • 에러 핸들링 방식, 재시도 방식, 인증 방식 등 기존에 있던 패턴을 따르지 않고 완전히 새로운 길을 걸을 필요는 없다. 아니, 좋지 않다.
    • 한 가지 일을 달성하기 위한 방법이 너무 다양하면 유지보수 난이도가 급상승하기 때문이다.
      • 쪽지 보낼 때 사용하는 인증 방식과 쪽지 읽을 때 사용하는 인증 방식이 달라진다면 기획하는 사람, 만드는 사람도 혼란스럽고 나중에 코드를 확인하고 고쳐야 하는 사람도 혼란스럽다.
    • 그리고 이미 잘 동작하고 있는 기능을 믿고 잘 갖다쓰는 것도 개발자의 덕목이라고 생각한다. 시간 단축을 위해서다.
      • 하지만 진짜 '잘' 갖다써야 한다.

남아있는 여러가지 질문들

  • 좀 더 단순하게 만들 수 없는가
    • 이 질문은 꼼꼼하게 해야 한다. 단순함을 추구하다가 정확성을 놓칠 수 있기 때문이다.
    • 하지만 한 번쯤 해볼만한 질문이다. 극도의 정확성만 추구하다가 설계 전체가 오버 엔지니어링을 하게 될 수 있기 때문이다. 너무 복잡한 시스템은 관리하기도 힘들다.
  • 난이도를 고려했을 때 개발 기간을 지킬 수 있는가
    • 다음달에 출시해야 하는 기능을 개발하기 위한 학습 기간이 1개월 걸린다면 재빨리 다른 방법을 찾아봐야한다. 우리의 목표는 학습이 아닌 개발이기 때문이다.
  • 각 기능이 어느 모듈에 들어가야 하는가
    • 나중에 공통적으로 사용될만한 것이라면 공통 모듈로 만들고, 공통 모듈에 대한 의존성이 있는 기능이라면 개별 모듈로 빼는 것을 생각해봐야 한다.
    • 하지만 처음부터 너무 공통 모듈을 만드려고 하지 않아도 된다. '이거 계속 쓰다보니 하나로 묶어야 할 것 같은데?'라는 생각이 금지되어있는건 아니니까.

질문을 했다면 기록하자.

요구사항을 파악하고, 내 작업의 효과를 따져보고, 팀 컨벤션을 따르는지 확인 했으며, 다른 질문에 대한 대답도 했다. 이제 마지막으로 할 일이 남아있다. 바로 기록하는 것이다.

과거에 짠 코드를 보고 있으면 무엇을 어떻게 만들었는지 파악할 수 있다. 하지만 그것을 '왜 이렇게 만들었는지'는 주석으로 적지 않는 한 알기 쉽지 않다. 그저 그 코드와 연결된 깃허브 이슈나 PR을 따라가면서 마치 장님이 코끼리 만지듯 파악할 수밖에 없다. 물론 코드를 적은 사람이 팀에 남아있다면 물어보면 그만이지만, 만약 없다면? 반대의 상황이 될 수도 있다. 누군가 내가 몇년 전에 짠 코드를 파악하기 위해 하루고 이틀이고 시간을 보내야 한다면? 그 누군가는 '미래의 나'가 될 수도 있다.

어떤 이유로 이런 설계를 했는지 잘 기록해두자. 기록을 많이 해서 손해 볼 일은 없다. (물론 하루에 절반 이상 기록만 하고 코드를 짜지 않는다면 문제가 되겠지만!)

profile
설계를 좋아합니다. 코드도 적고 그림도 그리고 글도 씁니다. 넓고 얕은 경험을 쌓고 있습니다.

0개의 댓글