사용자의 첫 질문에 바로 답하지 않고 그 이면의 맥락을 파고들어야 하는 이유, 그리고 그것이 더 나은 도구와 더 나은 엔지니어링 대화를 만드는 방식에 대한 글.
제 Perfetto 작업, 즉 성능 디버깅 도구를 만드는 일에서 제가 자주 받는 질문 하나는 이렇습니다. “Perfetto 트레이스를 여러 파일로 어떻게 나누나요?” 저는 곧바로 답하는 대신 이렇게 말합니다. “그걸 쉽게 하는 방법은 없는데, 왜 나눠야 할 정도로 큰 트레이스를 수집하게 되었는지 말해줄 수 있나요?”
이것은 직장에서 제가 따르는 황금률 가운데 하나입니다. 사용자가 뭔가 “이상한” 질문을 하면, 질문의 첫 번째 버전에 답하지 마라.
겉으로 보면 이것은 XY problem에 대한 이야기처럼 보일 수도 있습니다. 하지만 그것만으로는 한 걸음 부족합니다. 그 관점은 사용자가 말한 질문을 해독해야 할 퍼즐로 취급합니다. 즉, 사용자가 정말로 뜻한 바를 알아내고, 그것에 답한 뒤, 넘어가는 것입니다. 저는 우리가 훨씬 더 멀리 갈 수 있다고 생각합니다.
오히려 잘못된 질문을 만들어낸 혼란 자체가 하나의 출발점이고, 그로 인해 시작되는 대화는 양쪽 모두에게 가치가 있습니다. 사용자는 도구에 대해 더 나은 멘탈 모델을 갖고 돌아갑니다. 저는 제품이 사람들을 어디에서 혼란스럽게 만드는지 더 선명한 그림을 얻습니다. 그리고 때로는, 우리 사이에서 제품 자체가 바뀌어야 한다는 결론에 이르기도 합니다.
예전에 저는 주목받지 않고도 성공적인 엔지니어가 될 수 있는 방식에 대해 쓴 적이 있습니다. 그 글이 전반적인 전략을 다뤘다면, 이 글은 그것이 실제로 작동하게 만드는 구체적인 전술 가운데 하나입니다. 또 하나 덧붙이자면, 이 글은 다른 엔지니어를 위해 무언가를 만드는 사람들을 대상으로 합니다. 소비자용 제품이나 B2B 서비스를 만든다면 그대로 옮겨가지는 않겠지만, 그 밑바탕의 직감은 여전히 유용할 수 있습니다.
어떤 질문들은 쉽고, 일상적이며, 문서를 가리키기만 하면 되는 경우입니다. 그런 경우는 여기서 길게 논할 가치가 없습니다. 흥미로운 경우는 뭔가가 보통과 다를 때인데, 사용자가 첫 질문만으로 제게 충분한 정보를 준 경우는 드뭅니다1.
그래서 저는 다음에 어디로 갈지 판단하기 위해 머릿속에서 점검표를 돌립니다.
무엇이 어색한지 파악하고 나면, 다음 단계는 빠져 있는 맥락이 드러나게 할 질문을 하는 것입니다. 저는 대략 이렇게 말할 수 있습니다. “당장 질문하신 것에 대한 답은 X이긴 한데, Y라는 이유 때문에 그건 꽤 이상한 요청이에요. 해결하려는 더 큰 문제에 대해 조금 더 말해주실 수 있나요?”
아마 이것이 여러 차례 주고받는 대화의 시작이 될 것입니다. 얼마나 빨리 진행되는지는 사용자가 자기 생각을 얼마나 잘 전달하는지에 달려 있습니다. 하지만 보통은 몇 가지 경우 가운데 하나로 귀결됩니다. 사용자가 도구의 철학을 놓치고 있거나, 제품이 올바른 경로를 숨기고 있거나, 아니면 제품 자체가 바뀌어야 하는 경우입니다.
사용자들이 자신이 무엇을 원하는지 모르거나, 해결하려는 문제 자체를 제대로 이해하지 못한 채 찾아오는 일은 꽤 흔합니다.
분명히 해두자면, 저는 이것을 비판하려는 것이 아닙니다. 팀은 종종 제한된 시간과 자원 속에서 문제를 풀어야 하고, 진척이 나지 않을 때 새로운 디버깅 도구를 찾게 됩니다. 그 결과, 대체로 자신들이 원하는 대부분을 해주는 도구를 발견하지만, “원래 이렇게 동작해야 한다”는 자신의 모델과는 맞지 않는다는 사실도 발견합니다. 그래서 기능 요청을 올립니다.
자주 보는 한 가지 형태는 이렇습니다. 사람들이 Perfetto를 접하고, 트레이스가 일정 시간 구간 동안 기기가 무엇을 했는지를 매우 자세히 기록한 것임을 이해하고, Perfetto 트레이스에서 메트릭을 계산할 수 있다는 사실을 깨닫고는, 그것을 모든 문제의 성배 같은 해결책으로 취급합니다. 프레임 레이트가 필요하다면? 트레이스에서 프레임을 세면 됩니다. 앱이 사용한 메모리가 궁금하다면? 할당과 해제를 보면 됩니다. 원칙적으로는 어떤 메트릭이든 트레이스에서 계산 할 수는 있습니다.
하지만 단순한 이유로 이것은 나쁜 생각입니다. 트레이스는 수집하고 처리하는 비용이 큽니다. 하나의 숫자만 샘플링하는 것이 아니라 시스템 전체에 대한 데이터를 모으고 있기 때문입니다. 전용 메트릭 수집 시스템이 훨씬 더 효율적으로 해결할 수 있는 일을 하면서 많은 자원을 낭비하게 됩니다2.
제가 말하고 싶은 큰 요지는, 도구가 설계될 때는 나름의 철학이 있다는 점이고, 사용자는 당장의 문제에 집중하느라 그것을 자주 놓친다는 것입니다.
제 일의 큰 부분은 단순히 Perfetto 사용법을 설명하는 것이 아니라, 팀이 애초에 성능 엔지니어링에 어떻게 접근해야 하는지를 가르치는 것입니다. 이는 사람들이 자신이 사용할 수 있는 도구들을 인식하게 만들고, 시작 시간, 프레임 드롭, 메모리, 전력 같은 문제를 어떻게 생각해야 하는지, 그리고 정상적인 상황과 문제가 생긴 상황 모두에서 그것들과 어떻게 작업해야 하는지를 이해하도록 돕는다는 뜻입니다.
또 다른 경우에는 팀이 문제는 이해하고 있지만, 기존 도구를 어떻게 조합해야 할지 보지 못하는 경우가 있습니다. 우리의 도구들은 의도적으로 강력하게 설계되어 있고, 다른 팀이 우리가 만든 것의 전체 가능 범위를 이해하지 못할 수 있다는 점을 늘 염두에 두어야 합니다. 그들이 वास्तव적으로 원하는 것이 무엇인지 파악하는 것이 제 일입니다. 종종 다른 목적을 위해 만든 것이 그들의 필요를 충족하도록 다시 활용될 수 있습니다.
여기서 완벽한 예가 바로 앞서 말한 트레이스 분할입니다. 대화는 대략 이렇게 흘러갑니다. “…왜 나눠야 할 정도로 큰 트레이스를 수집하게 되었나요?” 그러면 그들은 긴 트레이스 안에 관심 있는 구간들이 있어서 그것을 잘라 나누고 싶다고 말합니다. 일부는 성능 때문이고, 일부는 시각화를 더 쉽게 하기 위해서입니다.
하지만 그때 저는 Perfetto가 이미 주기적 트레이스 스냅샷, 즉 하나의 긴 기록 대신 짧은 기록을 반복해서 수집하는 방식을 지원한다고 설명합니다. 이렇게 하면 애초에 긴 트레이스를 수집할 필요가 없어집니다. 그들은 원래 생기지 말았어야 할 문제를 해결하려 하고 있었던 것입니다.
사람들이 “바로 그게 제가 필요했던 거예요!”라고 말하는 모습을 보는 일은 언제나 만족스럽습니다. 비록 그것이 그들이 요청한 것은 아니더라도 말입니다. 그것은 제가 그들이 생각한 요청이 아니라, 그들이 वास्तव적으로 원했던 것을 제대로 찾아냈다는 뜻입니다.
가끔은 답변 과정에서 진짜로 새로운 무언가가 드러나기도 합니다. 우리를 큰 무언가를 만드는 길로 이끌 수도 있는 그런 것 말입니다. 이런 경우는 까다롭습니다. 요청이 새롭더라도, 요청한 사람 자신은 자신이 वास्तव적으로 무엇을 필요로 하는지 말하지 못하는 경우가 많습니다.
기반이 되는 소프트웨어에서 잘못된 선택의 비용은 크기 때문에, 저는 없는 것이 아플 정도가 될 때까지는 무언가를 만들지 않는 쪽으로 기웁니다. 여러 팀이 제게 와서 “이게 필요해요”라고 말할 때까지 기다리는 것입니다. 이상적으로는 그 시점쯤이면, 우리가 실제로 만들 가치가 있는 것의 본질을 찾아낸 상태여야 합니다. 이런 일은 단 한 번의 요청 뒤에 일어날 가능성이 매우 낮기 때문에, 기다리는 것은 정말로 강력합니다.
Perfetto에서도 우리는 이런 실수를 한 적이 있습니다. 예를 들어 즉흥적인 UI 커스터마이징이 그렇습니다. 사람들은 자신의 워크플로에 맞게 UI를 손보고 싶어 했고, 그게 얼마나 어려운지 계속 불평했습니다. 그래서 우리는 그것을 허용했고, 곧바로 막대한 기술 부채를 떠안았습니다. 모든 새 기능은 기존의 모든 기능과 상호작용해야 했고, 전체 시스템은 금세 확장 불가능한 상태가 되었습니다.
우리는 적절한 플러그인 API를 설계함으로써 이 구덩이에서 빠져나오는 데 대략 1년이 걸렸습니다. 처음부터 아무도 명확히 표현할 수 없었던 진짜 필요는, 다른 모든 사용자에게 영향을 주지 않으면서 자기 팀이나 사용 사례의 필요에 맞게 UI를 개인화 할 수 있는 방법이었습니다. 하지만 물론 이것은 너무 늦기 전까지 누구도 이름 붙일 수 없었습니다. 그래서 요청이 계속 들어오던 초기에 이것을 알아채는 것은 우리의 책임이었습니다.
사람들이 Perfetto 트레이스를 “병합”할 수 있게 해달라는 요청은 우리가 잘 대처한 사례였습니다. 사람들은 그것에 대해 끊임없이 물었지만, 우리는 보류했습니다. 사람들에게 우회 방법을 안내하고 “지켜보죠”라고 말했습니다. 제대로 구현하는 데 많은 일이 필요하고, 잘못 만들기도 쉬운 기능이라는 것을 알고 있었기 때문에 기다렸습니다. 우리는 마침내 작년에 이것을 유지보수 가능한 방식으로 만들었지만, 그건 애초에 문제 공간을 아주 잘 이해하고 있었기 때문에 가능했습니다.
질문의 첫 번째 버전이 진짜 질문인 경우는 드뭅니다. 답하기 전에 왜 그런 질문을 하는지 물어보세요. 때로는 그 대답이 사용자에게 도구가 어떻게 쓰이도록 의도되었는지를 가르쳐 줍니다. 때로는 제품이 올바른 길을 숨기고 있다는 사실을 알려줍니다. 때로는 아직 만들 가치가 있는 것이 없다는 점을 알려줍니다. 그리고 때로는 다음 큰 것을 두 번이 아니라 한 번만 만들 수 있게 준비시켜 줍니다.
이 기법은 단순하지만, 반응을 빨리 해야 한다는 압박은 늘 존재하고 빠른 답변 하나하나가 생산적으로 느껴지기 때문에 쉽게 건너뛰게 됩니다. 그래도 잠깐 한 걸음 물러서세요. 거의 언제나 양쪽 모두 처음보다 더 많은 것을 얻고 돌아가게 됩니다.