이제 갓 시작한 서비스를 만들면 새로운 기능 개발을 주로 하게 된다. 이전과 비슷한 기능을 만들 때는 큰 고민 없이 바로 코드를 적어나갈 수 있겠지만 그렇지 않은 경우도 있다. 웹페이지의 요청을 처리하는 API 서버 개발만 하다가 매일 1번씩 실행되어야 하는 배치 애플리케이션을 개발해야하는 순간처럼 말이다. 서버의 형태가 완전히 달라지는 것만큼 큰 변화는 아니더라도 새로운 공통 모듈이 필요하거나 새로운 메세지 처리 방식이 필요할 때도 있다. 이럴 때 우리는 바로 키보드 앞으로 달려가 코드를 짜기 전에, 질문을 먼저 해야 한다.
질문을 던지면서 항상 생각해야 할 것은 '모든 것은 트레이드 오프'라는 사실이다.
소프트웨어 아키텍처 101 1장 서론 中
- 소프트웨어 아키텍처의 모든 것은 다 트레이드오프다. (소프트웨어 아키텍처 제1법칙)
- 아키텍트가 트레이드오프가 아닌 뭔가를 발견했다고 생각하면 그것은 그가 아직 트레이드오프를 발견하지 못했다는 증거일 가능성이 높다. (제1정리)
모든 기준을 충족할 수 있는 완벽한 시스템은 존재할 수 없다. 적어도 지금 내가 아는 선에서는 그렇다. 어떤 시스템이나 기능이 성능, 일관성, 확장성 등 수많은 기준을 100%로 달성할 수는 없다. 그런걸 생각해냈다면 분명 무언가 놓친게 있을 것이다. 아무리 생각해도 놓친게 없다면 당장 스택오버플로우, 깃허브, 레딧 등 전세계 개발자 커뮤니티에 널리 전파하도록 하자.
요구사항 파악하기. 기능 개발의 시작점이다. 가장 많이 하고, 중요하고, 간단해보이지만 제대로 해내기 쉽지 않은 것이다. 요구사항에는 이런 항목들이 포함된다.
기능 개발하는 사람이 직접 요구사항을 정하는 경우도 있고 다른 사람 혹은 다른 팀이 요구사항을 전달하는 경우도 있다. 요구사항을 만드는 사람과 개발하는 사람이 같은 사람이라고 해서 방심해서는 안 된다. 스스로에게 위 질문을 던져보면서 정확하게 어떤 기능이 필요한지 구체화 할 필요가 있다. 다른 사람으로부터 요구사항을 받을 때에도 마찬가지다. 요구사항을 파악하는 단계의 핵심은 질문이다.
모두가 물음표 살인마가 되어야 한다. 첫째는 요구사항을 처음 만드는 사람도 미처 고려하지 못한 부분이 있을 수 있기 때문이고 둘째는 요구사항에 따라 전체적인 설계도안이 크게 달라질 수 있기 때문이다.
🤷🏻♂️: 우리 사이트에 쪽지 기능을 추가할거에요. 사용자들은 서로 쪽지를 주고받을 수 있고, 각자의 쪽지 보관함으로 관리할 수 있어야 해요. 화면 디자인은 여기에 있어요.
💁🏻♀️: 언제까지 되어야 하나요?
🤷🏻♂️: 3달 뒤에 런칭하고 싶어요.
💁🏻♀️: 오 넵. 바로 개발 착수하겠습니다!
🤷🏻♂️: 우리 사이트에 쪽지 기능을 추가할거에요. 사용자들은 서로 쪽지를 주고받을 수 있고, 각자의 쪽지 보관함으로 관리할 수 있어야 해요. 화면 디자인은 여기에 있어요.
💁🏻♀️: 쪽지는 얼마나 빨리 전달되어야 하나요? 거의 실시간이어야 하나요?
🤷🏻♂️: 그럴 필요는 없고 1분 내로만 도착하면 돼요.
💁🏻♀️: (그러면 굳이 실시간 DB 안 쓰고 원래 쓰던거 그대로 써도 되겠군. 네트워크 지연도 크게 고려하지 않아도 되겠어.)
💁🏻♀️: 쪽지 보관함 화면에서 보낸 사람 닉네임을 클릭하면 프로필로 이동하는건가요?
🤷🏻♂️: 네 맞습니다.
💁🏻♀️: 그렇다면 만약 그 사람이 탈퇴한 회원이면 어떻게 되나요?
🤷🏻♂️: 오 그건 미처 생각하지 못했네요. 좀 더 보완해서 기획서와 디자인 페이지에 반역해놓겠습니다.
... (오고가는 수많은 물음표들) ...
💁🏻♀️: 개발 기간은 어느정도 있을까요?
🤷🏻♂️: 3달 뒤에 런칭하고 싶어요.
💁🏻♀️: 현재 개발 인원과 리소스, 개발 범위 등을 고려하면 ~~~ 가능할 것 같아요!
이런 질문을 하는 이유는 단순하다. 비용이 정해져있기 때문이다. 우리는 한정된 시간과 유한한 노동력을 갖고 일한다. 그 누구도 하루를 48시간으로 늘리거나 일주일에 168시간이 넘는 시간을 일할 수 없다. 이건 우리가 게을러서가 아니라, 물리적인 한계가 있기 때문이다. (만약 이 한계를 깰 수 있는 방법이 있다면 제발 알려주세요)
그렇다면 우리는 작업의 효율성을 따져봐야 한다. 하루 실사용자가 10명밖에 없는데 대규모 분산 시스템을 구축하기 위해 하둡 공식 문서를 뒤지고 있으면 곤란하다.
💁🏻♂️: "아니 언제는 확장성을 고려하라면서요?
그건 맞다. 하지만 적절한 시기가 있는 것이다. 트위터 예시를 보자.
진화적 아키텍처 7장 진화 가능한 아키텍처 구축 中
- 트위터는 출시일을 앞당기기 위해 루비 온 레일즈를 이용해 개발됐다. 그러나 트위터 플랫폼은 트위터의 성장세를 감당하기에는 확장성이 부족했기에, 이후 빈번하게 장애를 일으키고 ...(중략)... 초창기 트위터 사용자는 이 그림에 나타난 고래 그림이 익숙할 것이다.
...- 만일 트위터 엔지니어가 출시 전부터 최종적이고 견고한 플랫폼을 구축했다면 제때 시장에 진출하지 못했을 것이다. 만일 그랬다면 트위터가 지연된 만큼 Snitter 등의 단문 메시징 서비스가 먼저 등장해 시장을 선점했을지도 모를 일이다.
개발을 하면서 매 순간 최선을 다해 '가장 좋은 선택'을 하지만 시간이 지나고나면 본인이 짠 코드를 보면서 의문을 갖게 되는 경우가 많다. '도대체 왜 이렇게 짠거야? 다르게 해도 됐을텐데.'라는 생각으로 히스토리를 뒤지다보면 당시에는 그게 제일 나은 선택이라서 그랬던 경우가 많다. 다만 상황이 바뀌는 것일 뿐이다. 트위터가 유명해지고 몇년 뒤에 트위터에 입사한 신입 개발자가 있다면 이렇게 질문했을 것이다. '도대체 왜 루비 온 레일즈를 선택한거야? 트래픽이 이렇게나 많은데말이야.' 하지만 처음부터 견고하고 강력한 서버 체계를 구축하느라 시간을 너무 많이 쏟았다면 그정도 트래픽을 받아볼 일이 없었을지도 모른다.
왜 이런 질문을 던지냐하면, 팀으로 일하기 때문이다. 팀은 마치 하나의 무언가처럼 움직여야 한다. 여기서 말하는 팀은 1인 개발자도 포함된다. 과거의 나, 현재의 나, 그리고 미래의 나. 이렇게 셋이서 한 팀이다.
컨벤션이 중요한 이유는 팀 구성원이 계속 바뀌기 때문이다. (물론, 1인 개발자도 이 문장의 '팀'에 해당된다. 앞서 말했듯이 과거의 나, 현재의 나, 미래의 나 이렇게 3명으로 구성된 팀이다.) 계속되는 변화 속에서 이미 개발된 기능은 여전히 잘 작동해야 한다. 새롭게 개발될 기능도 잘 동작해야한다. 시스템을 유지보수하는 사람은 무엇이 어떻게 돌아가는지 빠르고 정확하게 파악할 수 있어야한다. 다른 사람이 짠 코드리뷰를 한 경험이 있다면 바로 와닿을 것이다. 코드를 이해하는데 불필요한 잡음과 변수를 최대한 없애야한다.
잡음이나 변수를 발견하기 위해서는 이런 질문을 던져보는게 좋다.
요구사항을 파악하고, 내 작업의 효과를 따져보고, 팀 컨벤션을 따르는지 확인 했으며, 다른 질문에 대한 대답도 했다. 이제 마지막으로 할 일이 남아있다. 바로 기록하는 것이다.
과거에 짠 코드를 보고 있으면 무엇을 어떻게 만들었는지 파악할 수 있다. 하지만 그것을 '왜 이렇게 만들었는지'는 주석으로 적지 않는 한 알기 쉽지 않다. 그저 그 코드와 연결된 깃허브 이슈나 PR을 따라가면서 마치 장님이 코끼리 만지듯 파악할 수밖에 없다. 물론 코드를 적은 사람이 팀에 남아있다면 물어보면 그만이지만, 만약 없다면? 반대의 상황이 될 수도 있다. 누군가 내가 몇년 전에 짠 코드를 파악하기 위해 하루고 이틀이고 시간을 보내야 한다면? 그 누군가는 '미래의 나'가 될 수도 있다.
어떤 이유로 이런 설계를 했는지 잘 기록해두자. 기록을 많이 해서 손해 볼 일은 없다. (물론 하루에 절반 이상 기록만 하고 코드를 짜지 않는다면 문제가 되겠지만!)