NDC Oslo 2025 - 우리가 매일 쓰는 앱에 숨겨진 버그들, 그리고 이걸 막는 방법
여기 아주 좋은 유튜브 강연이 있는데요, 이 강연의 핵심만 전체적으로 살펴볼까 합니다.
발표자는 무려 2년 동안 일상에서 사용하는 앱과 웹사이트에서 발견한 버그를 전부 수집했다고 하더라고요.
강연 제목은 '82개의 버그'였지만, 사실은 그보다 훨씬 많은 279개나 모았다고 합니다.
정말 대단한 집념이죠.
이런 실제 사례들은 단순한 웃음거리를 넘어, 우리 소프트웨어를 더 안정적으로 만들고 테스트 프로세스를 개선하는 데 아주 중요한 교훈을 주거든요.
우리 모두가 알만한 유명 서비스에서도 이런 실수들이 나온다는 걸 보면, 배울 점이 참 많을 거예요.
도대체 어떤 버그들이 있었을까요?
발표자는 정말 다양한 버그들을 수집했는데요.
가장 먼저 보여준 건 제 이름처럼 특수 문자가 들어간 이름이 깨지는 '인코딩' 문제였습니다.Fábián
같은 이름이 Fábián
이나 이상한 문자로 깨져 나오는 화면은 우리에게도 꽤 익숙하죠.
또 '서버가 고집을 부리고 있습니다(servers being stubborn)' 같은 정체불명의 에러 메시지도 있었고요.
심지어 '이 이름은 영숫자 문자만 포함할 수 있습니다'라는 오류 메시지가 뜨는데, 정작 입력된 값은 영숫자만 있는 황당한 경우도 있더라고요.
아마 개발자라면 한 번쯤 겪어봤을 'null'이나 'NaN(Not a Number)' 같은 값들이 사용자 화면에 그대로 노출되는 경우도 비일비재했습니다.
이런 건 정말 부끄러운 실수죠.
가장 재미있었던 예시 중 하나는 햄버거 주문 앱이었는데요.
치즈를 추가하려고 '+' 버튼을 눌렀더니 수량이 '1'에서 '2'로 잘 올라갔습니다.
여기까지는 완벽했죠.
그런데 여기서 '+' 버튼을 한 번 더 누르니까 수량이 갑자기 '0'이 되어버리더라고요.
한 번 더 누르니 이번엔 '0.4'가 되고요.
도대체 0.4장의 치즈는 어떻게 올려주겠다는 건지, 정말 궁금해지는 순간이었습니다.
버그 통계에서 발견한 의외의 사실
발표자는 수집한 279개의 버그를 꼼꼼하게 분석해서 통계를 냈는데요.
여기서 아주 흥미로운 인사이트를 얻을 수 있었습니다.
먼저, 가장 많은 버그가 발견된 영역은 단연 'UI' 영역이었어요.
백엔드 로직보다는 사용자 인터페이스에서 발생하는 문제가 압도적으로 많았다는 거죠.
이건 어느 정도 예상 가능한 결과입니다.
하지만 버그를 세부 유형으로 나누어보니 정말 의외의 결과가 나왔는데요.
가장 흔한 버그 유형 1위는 바로 '반응형 디자인' 문제였습니다.
화면 크기가 달라질 때 레이아웃이 깨지거나 특정 기능이 제대로 동작하지 않는 문제가 생각보다 훨씬 많았다는 거예요.
그 뒤를 '글리치(Glitch)', 즉 원인을 알 수 없는 일시적인 오류와 '템플릿 미처리'가 이었습니다.
그런데 여기서 더 중요한 포인트가 있습니다.
버그의 '개수'가 아니라 '심각도'를 기준으로 다시 정렬해보니 순위가 완전히 뒤바뀌었거든요.
사용자의 작업을 완전히 막아버리는 'Blocker'나 'Critical' 등급의 심각한 버그들은 '데이터 유효성 검사(Data Validation)'나 '에러 핸들링(Error Handling)'에서 가장 많이 발생했습니다.
즉, UI 버그는 자주 발생하지만 덜 치명적인 반면, 데이터나 에러 처리 관련 버그는 발생 빈도는 낮아도 한번 터지면 훨씬 더 치명적이라는 거죠.
이건 우리가 어디에 더 많은 테스트 리소스를 집중해야 하는지 알려주는 아주 중요한 지표가 될 거예요.
1. 반응형 디자인 버그, 아직도 이렇게나 많다고요?
가장 흔했던 반응형 버그의 예시로는 화면이 작아지자 메뉴 버튼을 눌렀을 때 메뉴가 화면 밖으로 잘려서 보이지 않는 경우가 있었는데요.
사용자는 메뉴가 열렸다는 사실조차 인지하기 어렵죠.
이런 문제를 어떻게 막을 수 있을까요?
발표자가 제시한 첫 번째 해결책은 바로 '모바일 퍼스트(Mobile First)' 디자인 철학을 도입하는 겁니다.
이건 작은 모바일 화면을 기준으로 먼저 디자인하고 개발한 뒤, 점차 화면을 키워가며 데스크톱 버전을 만드는 방식인데요.
이렇게 하면 작은 화면에서 발생할 수 있는 제약사항을 처음부터 고려하게 되므로, 데스크톱 디자인을 억지로 모바일에 구겨 넣을 때 발생하는 문제를 원천적으로 줄일 수 있습니다.
큰 화면에서 잘 작동하는 디자인이 작은 화면에서도 잘 작동하리란 보장은 없지만, 작은 화면에 최적화된 디자인은 큰 화면에서도 어느 정도 잘 작동하는 경우가 많거든요.
두 번째는 '모바일 기기에서의 엔드투엔드(E2E) 테스트'를 자동화하는 겁니다.
단순히 브라우저 크기만 줄여서 테스트하는 것과 실제 모바일 기기에서 테스트하는 것은 경험이 완전히 다르죠.
발표자는 'WebDriver.io'처럼 실제 기기 테스트를 지원하는 프레임워크를 추천했습니다.
이미 'Playwright'를 쓰고 있다면 에뮬레이션 기능이라도 적극적으로 활용하는 게 아무것도 안 하는 것보다는 훨씬 낫다고 강조했죠.
2. 원인 불명의 '글리치'는 어떻게 잡아야 할까?
다음으로 많았던 건 '글리치'성 버그인데요.
스타일이 갑자기 전부 깨져서 나온다거나, 아이패드 이름 옆에 정체불명의 태국어가 표시되는 등 재현하기 어려운 버그들이 여기에 속합니다.
심지어 문법 검사기에서 'bug'라는 단어를 'bug bug'로 수정하라고 제안하는 황당한 경우도 있었죠.
이런 버그들은 자동화된 테스트만으로는 잡기가 정말 어렵습니다.
그래서 발표자는 '도그푸딩(Dogfooding)' 문화를 강력하게 추천했는데요.
'우리 개밥은 우리가 직접 먹어본다'는 뜻으로, 우리 회사가 만든 제품을 내부 직원들이 먼저 적극적으로 사용하는 문화를 말합니다.
내부 직원만큼 우리 제품을 열심히, 그리고 끈질기게 사용하는 '테스터'는 없죠.
직원들이 버그를 쉽게 보고하고, 보고된 버그가 수정되었을 때 피드백을 주는 문화를 만들면 이런 글리치성 버그를 발견할 확률이 훨씬 높아질 거예요.
또 다른 방법으로는 '탐색적 테스팅(Exploratory Testing)'이 있습니다.
정해진 시나리오 없이 테스터의 직관과 경험에 의존해 자유롭게 시스템을 탐색하며 버그를 찾는 기법인데요.
스크립트 기반 테스트가 놓치기 쉬운 의외의 버그들을 찾아내는 데 아주 효과적이죠.
마지막으로 '히트맵 시각화' 도구를 활용하는 방법도 제안했는데요.
사용자들이 화면의 어느 부분을 클릭하고 마우스를 어디에 오래 두는지 분석하는 겁니다.
이를 통해 사용자들이 버튼이라고 생각하고 클릭했지만 아무 일도 일어나지 않는 '데드 클릭(Dead Clicks)'이나, 답답해서 같은 곳을 여러 번 클릭하는 '레이지 클릭(Rage Clicks)'을 발견할 수 있거든요.
이런 지점들은 잠재적인 버그나 UX 마찰이 있다는 강력한 신호가 됩니다.
3. 화면에 그대로 노출되는 템플릿과 에러 메시지
`{{RECEPTION_HOURS}}`
처럼 변수로 대체되어야 할 템플릿 문자열이 사용자 화면에 그대로 노출되는 버그도 꽤 많았는데요.
발표자가 실제로 겪은 일인데, 호텔 예약 사이트에서 리셉션 운영 시간이 이런 식으로 깨져서 나오는 바람에 24시간 체크인이 가능한지 확인할 수 없어서 결국 다른 호텔을 예약했다고 하더라고요.
사소해 보이는 버그 하나가 실제 고객을 놓치는 결과로 이어진 거죠.
이런 문제는 이메일 템플릿에서 특히 자주 발생합니다.
'{{FIRST_NAME}}' 고객님, 하고 이메일이 날아오면 프로페셔널해 보이지 않겠죠.
이런 문제를 막으려면 템플릿 교체 로직에 대한 '유닛 테스트'와 '통합 테스트'가 필수적입니다.
특히 값이 비어 있거나, 아주 길거나, 발표자의 이름처럼 UTF-8 문자가 포함된 엣지 케이스들을 반드시 테스트해야 하죠.
비슷한 맥락에서 필터링되지 않은 에러 메시지가 사용자에게 그대로 노출되는 경우도 심각한 문제인데요.Cannot read properties of undefined
같은 메시지는 개발자에게나 의미가 있지, 사용자는 어리둥절할 뿐입니다.
더 위험한 건, 이런 에러 메시지가 시스템의 내부 구조나 기술 스택(.NET
), 심지어 서버의 파일 경로(C:\Users\Workbox\...
)까지 노출할 수 있다는 점이에요.
이건 해커에게 아주 좋은 공격 단서를 제공하는 셈이죠.
해결책은 명확합니다.
운영 환경에서는 스택 트레이스를 절대 노출해서는 안 되고요.
예상치 못한 에러가 발생하면 "예상치 못한 오류가 발생했습니다. 나중에 다시 시도해 주세요."와 같은 일반적인 메시지를 보여주는 것이 좋습니다.
그리고 여기서 한발 더 나아가, 사용자가 고객 지원팀에 쉽게 연락할 수 있도록 이메일 주소를 제공하거나, 클릭하면 에러 정보를 담아 메일 클라이언트를 바로 열어주는 'mailto' 링크를 제공하는 것이 아주 좋은 방법이라고 하더라고요.
4. 사소해 보이지만 치명적인 번역 및 정보 오류
마지막으로 다룰 문제는 국제화(i18n) 과정에서 발생하는 '텍스트 키' 노출과 잘못된 정보 표시 문제입니다.
"Pairing Completed" 대신 pairing.completed
같은 텍스트 키가 화면에 표시되는 경우가 종종 있는데요.
이게 만약 법적 효력이 있는 '면책 조항(Disclaimer)' 부분에서 발생했다면 어떨까요?
사용자가 내용을 이해하지 못했다고 주장하면 법적 분쟁으로까지 번질 수 있는 심각한 문제가 될 수 있습니다.
이런 깜빡임(Flickering) 현상을 막기 위해선, 서버 사이드 렌더링(SSR)을 도입해 처음부터 번역된 HTML을 내려주거나, 비동기로 번역 파일을 불러오는 동안에는 '스켈레톤 스크린'을 보여주는 것이 좋은 해결책이 될 수 있습니다.
정보가 아예 '틀리게' 표시되는 버그는 더 위험한데요.
발표자는 일본 엔화 환율이 하루아침에 100분의 1 토막이 난 것처럼 표시되거나, 100달러짜리 CPU 쿨러가 24,000달러로 표시되는 황당한 사례를 보여주었습니다.
이런 데이터 입력 오류를 막기 위해선 수동으로 데이터를 입력할 때 다른 한 명이 검토하는 '4중 확인(Four-eyes principle)' 원칙을 적용하거나, 이전 데이터와 비교해 값이 비정상적으로 크게 변동하면 경고를 띄우는 자동 검증 로직을 추가하는 것이 중요합니다.
결국 이 강연이 우리에게 주는 메시지는 명확한데요.
버그는 단순히 기술적인 결함이 아니라, 비즈니스에 직접적인 손실을 끼치고, 법적 리스크를 만들며, 보안을 위협하는 실제적인 문제라는 겁니다.
그리고 이런 문제들은 거창한 기술이 아니라, '모바일 퍼스트', '도그푸딩', '철저한 엣지 케이스 테스트'와 같은 기본적인 원칙을 꾸준히 지키는 것만으로도 상당 부분 예방할 수 있다는 거죠.
오늘 살펴본 여러 사례들이 여러분의 프로젝트 품질을 한 단계 높이는 데 좋은 자극이 되었으면 좋겠습니다.