카카오페이

카카오페이

개발팀 리뷰

위 내용은 카카오페이 전 • 현 재직자의 응답 결과입니다.

기술 스택

언어

Java

프론트엔드

React

Next.js

React Query

백엔드

SpringBoot

재직자가 작성한 글

profile picture

황지연

카카오페이 Backend Engineer

Grab의 Shift-left 테스트 전략

협업 프로세스의 변경을 통해 테스트 비용을 낮추고, 소프트웨어 품질을 향상한 사례입니다. 테스트 단계를 왼쪽으로(앞으로) 가져오는 것만으로도 생산성과 품질의 향상을 가져올 수 있다는 게 너무나 인상깊었어요. 새로운 기술에 돈을 쓴 게 아니라 함께 일하는 방식을 바꿔보는 것만으로도 우리 제품이 좋아진다는 거잖아요. Grab의 성장과 함께 급증한 테스트 비용 * Grab은 모빌리티 뿐만 아니라 음식 배달 등 아시아의 슈퍼 앱이 되어가며 많은 서비스들이 생겨났고, 테스트 비용이 증가하기 시작했습니다. * 이전에는 통상적인 방식(Planning - Design - Development - Testing - Release - Monitoring - Analysis)으로 개발 완료 후 QA에서 테스트하고 sign-off를 통해 앱을 릴리즈했어요. 하지만 오히려 많은 버그를 일으키고 테스트에 오랜 시간이 소요된다는 것을 발견했습니다. * Shift-left 테스트 전략을 적용해 개발이 완료된 후 테스트를 하는게 아니라, 초기단계인 플래닝과 디자인 단계부터 테스팅을 접목했어요. 아래 3가지 방법을 통해 업무 프로세스에 적용했습니다. 1. 개발자가 인수 테스트(Acceptance Test) 수행 * 인수테스트는 개발이 완료된 후 QA에 의해 시행되었는데, 이때 버그가 발견되면 수정하는 비용이 훨씬 비쌌어요. 특히 대부분이 불분명한 요구사항, 부족한 테스트 케이스로 인한 것이었습니다. * 이를 개선하여, 개발이 시작되기 전에 QA가 테스트 케이스를 작성하고 개발자들이 인수 테스트를 수행하며 개발을 완료하게 됩니다. * 일종의 TDD와 비슷하다고 느꼈는데요. 개발자가 단위 테스트를 작성하고 비즈니스 로직을 구현하는 게 코드 레벨의 TDD라면, 제품 주기의 레벨에서 QA가 먼저 인수 테스트 케이스를 작성한 후 개발자가 이를 만족하는 개발을 수행해요. 코드 레벨이 아닌 협업 레벨에서도 TDD를 적용한 것 같아서 정말 신선했어요. * 인수테스트가 먼저 작성되고 나면, 불분명한 요구사항이 더욱 명확하게 정의될 수 있고(테스트 케이스를 작성해야하니 명확하게 정의될 수 밖에 없다!) 테스트 단계에 돌입하기 전에 개발자들이 스스로 버그를 찾아내 수정했습니다. 개발자 입장에서도 컨텍스트 스위칭 없이 바로 버그를 수정할 수 있으니 훨씬 빨리 해결할 수 있게 되었죠. 2. DoR(준비 정의)과 DoD(완료 정의) * Shift-left 테스트를 업무 프로세스 상에 녹이는 방법으로 DoR(Incorporate Definition of Ready)과 DoD(Definition of Done)를 정의했습니다. * DoR은 스프린트가 승인되기 전에 티켓(에픽/스토리/태스크)에 충족해야 되는 명시적인 기준입니다. DoD은 티켓이 완료 또는 상태가 변경되기 전에 충족되어야할 기준입니다. * 이 2가지는 애자일 표준 프로세스의 일부인데요. Grab에서는 여기에 품질과 테스트에 대한 기준을 구체적으로 정의했다는 의미같아요. 글로 예측해보건데, DoR은 품질 기준을 명확하게 세운다, DoD로 모든 인수테스트가 성공해야 한다가 될 수 있을 것 같습니다. * 이 프로세스를 채택한 팀의 경우 릴리즈 속도와 품질이 향상되어 계획했던 기능의 90%를 포함할 수 있었고, 수동 테스트 시간이 단축되었습니다. 3. 테스트 전략의 밸런스 * QA의 작업을 효율화하는 전략도 함께 적용했어요. UI 테스트를 자동화하고, 백엔드 통합 테스트, E2E(End to End) 테스트를 개선하는 등 수동 테스트를 최소화하기 위해 노력했습니다. Shift-left 테스트 적용 이후 * Grab에서는 Shift-left 테스트를 실행한 이후 릴리즈 속도는 보장된 상태로 앱의 품질을 향상시킬 수 있었어요. 릴리즈 후 발견되는 Major/Ciritical 버그들은 60% 줄었고, 개발 단계에서 발견되는 Major/Critical 버그들은 40% 줄었습니다.

profile picture

황지연

카카오페이 Backend Engineer

쉬운 문제는 쉽게 풀어야 한다

서비스가 성장하면 잘 돌아가던 코드에서 조금씩 문제가 발생합니다. 어느 순간부터 어드민 조회가 느려지더니, 타임아웃으로 조회가 실패하는 현상이 발생했어요. 문제 된 쿼리에서 조인된 테이블은 4개, 쿼리 실행계획을 보니 인덱스를 타지 않고, full scan으로 동작했습니다. 이때 저는 2가지 접근 방법이 떠올랐어요. 1️⃣ SQL에 딥 다이브하여 쿼리를 개선합니다. 개발자답게 쿼리를 리팩토링해 성능을 향상시키는 거죠. 2️⃣ 문제를 사라지게 합니다. 수줍게 밝혀보자면 저는 2번, 즉 문제를 사라지게 하는 것을 선호합니다. 정말로 개선할 필요가 있는 문제인가를 먼저 확인합니다. 이 기능이 사용자의 니즈에 맞게 설계된 확인해요. 얼마나 많은 사용자가 빈번하게 사용하는지 접근 로그를 통해 사용성을 확인합니다. 이 많은 데이터를 한 화면에서 조회하는 게 정말 필요한지도 직접 물어봐요. 알고 보면 사용자가 필요로 하지 않는 데이터를 보여주느라 지나치게 조인을 많이 했을 수도 있으니까요. 최초에는 여러 가지 데이터를 보고자 기획했을 수도 있는데, 시간이 지나면서 목적과 용도가 바뀌기도 하니까요. 기획자를 나무랄 일이 아니지요. 문제 자체를 쉽게 풀고자 하는 마음은 이런 경험들 때문인데요. 힘들게 성능 향상을 했는데, 알고 보면 "음.. 사실 이 기능 별로 사용하지 않아요."라는 이야기를 들은 적이 꽤 있었거든요. 알고 보면 사용되지 않는 기능인데 고쳤던 경우도 있었구요. 문제를 어렵게 풀었다는 생각에 허탈해졌어요. 사용자가 기능을 어떻게 사용하는 지 본질을 파헤치다 보면 다르게 해결할 수 있는 경우가 많았어요. 김상욱 교수의 강연에서 '과학자의 접근법'에 대해 들었는데요. 교수님이 학생들에게 방탈출 문제를 냈대요. 학생들은 탈출하기 위해 방 안에서 열쇠를 찾습니다. 과학적인 접근법이라면 방을 4 x 4 그리드로 나누고 그 안에서 열심히 찾아봅니다. 찾지 못했어요. 그러면 더 촘촘하게 방을 8 x 8 그리드로 나눠 더 꼼꼼하게 열쇠를 찾습니다. 그래도 찾지 못하면 그때 '아 열쇠가 방 안에 없구나'라는 확신을 가지게 되고, 방문을 열어 밖에서 열쇠를 찾게 됩니다. 그중 경계 없이 생각하는 학생은 방을 촘촘하게 뒤지기 전에 문을 벌컥 열고 나가는 경우가 있대요. 그러나 과학적인 접근법은 꼼꼼하게 문제를 푸는 것이고, 이를 통해 '이 방법으로는 문제를 풀 수 없다'는 것을 확신하고 나서, 다른 방법으로 접근합니다. 우리가 푸는 문제는 대부분 과학적, 공학적인 접근법으로 가는 게 맞을 거예요. 그러나 들어가는 시간과 비용을 고려했을 때, '쉽게 풀 수 있을까?'라는 생각으로 문고리 한번 돌려볼 수도 있는 거잖아요. 키가 안에 없다고 가정하고 문을 열어보는 것은 낮은 비용으로 확인해 볼 수 있으니까요. (방탈출가서 문제 안 풀고 다른 데 가서 들쑤시고 있는 사람이 접니다. 대부분은 주어진 문제를 풀어야 풀리더라구요^^; 그래도 가끔 히트할 때가 짜릿한걸요.. ) 조인이 많은 쿼리에서 문제를 쉽게 푸는 방법은 조인을 없애는 것입니다. 정말 이 많은 테이블이 조인되어 한 번에 조회되어야 할까. select 하는 컬럼 중 어떤 것 때문에 조인하는 것일까. 그 컬럼은 정말 필요할까? 만약, 조인을 없앨 수 없는 상황이었다면 어떻게 할까요? explain으로 쿼리 실행 계획을 살펴보고, 인덱스를 추가해서 개선할 수 있을지, 쿼리 힌트를 사용해야 할지 고민해 보고 DBA에게 조언을 구할 것 같아요. 쿼리를 가장 잘 아는 사람에게 도움을 구하며 지식을 얻을 수 있으니까요. 하지만 모든 회사에 DBA가 있는 것도 아니고, 조언을 구할 수 없는 상황이 있겠죠. 우리 개발자들이 잘하는 것처럼 커뮤니티에 올려 도움을 요청할 것 같습니다. 감사하게도 개발자 문화는 열려있기 때문에 다양한 곳에서 의견을 구할 수 있습니다. 하지만 커뮤니티에 올리는 것이 버겁게 느껴질 수 있습니다. 스스로가 찾을 수 있는 최선의 방법으로 해결하되 최고의 방법이 아니라는 것은 알아두면 되지 않을까요. 현재 내가 적용할 수 있는 최선의 방법이 여기까지라는 것을 받아들입니다. 이 또한 나쁘지 않다고 생각해요. 기획자나 디자이너에게 한계점을 설명하고, 유저향 서비스라면 UI/UX로 문제를 푸는 방법을 사용합니다. 어드민 같은 내부 사용자를 위한 것이라면 사용 조건을 제약한다는 것을 알립니다. 우리는 대체로 문제를 물어뜯고 딥 다이브하는 정공법을 사용합니다. 그러나, 본격적으로 들어가기 전에 문고리 한번 돌려보면 어떨까요?