Skip to main content
Summary

오류는 실패가 아니라 신호다

프로그램을 쓰다 보면 화면이 멈추거나, 결제가 되지 않거나, 저장한 내용이 사라지는 일을 겪을 수 있다. 우리는 이런 일을 보통 오류라고 부른다. 오류는 프로그램이 기대한 대로 작동하지 않는 상태다. 버튼을 눌렀는데 아무 반응이 없거나, 잘못된 결과가 나오거나, 아예 서비스가 중단되는 경우가 모두 포함된다.

버그는 이런 오류를 일으키는 원인에 가깝다. 코드 한 줄의 실수일 수도 있지만, 항상 그렇게 단순하지는 않다. 요구사항을 잘못 이해했거나, 예상하지 못한 사용 방식이 있었거나, 데이터가 이상한 형태로 들어왔거나, 특정 기기에서만 문제가 생겼을 수도 있다.

예를 들어 회원가입 화면에서 이메일을 입력하고 가입 버튼을 누르면 가입이 완료된다고 해 보자. 정상적인 입력에서는 잘 작동한다. 하지만 이미 가입된 이메일을 넣으면 어떻게 해야 할까. 이메일에 공백이 들어가면 어떻게 처리할까. 인증 문자가 만료된 뒤 가입 버튼을 누르면 어떤 메시지를 보여 줄까. 이런 경우를 미리 정하지 않으면 프로그램은 어느 순간 어긋난다.

따라서 오류를 단순히 개발자의 실수로만 보면 문제의 일부만 보게 된다. 실제 서비스의 품질은 코드뿐 아니라 요구사항, 데이터, 화면 흐름, 서버 상태, 외부 서비스, 사용자의 행동이 함께 만든다.

오류, 버그, 테스트를 이해하는 법AI 생성 이미지

버그는 어디에서 생기는가

버그가 생기는 첫 번째 이유는 요구사항 오해다. "한 사람당 한 번만 예약할 수 있다"라는 말은 명확해 보이지만, 실제로는 질문이 많다. 하루에 한 번인지, 전체 기간에 한 번인지, 같은 전화번호 기준인지, 같은 계정 기준인지 정해야 한다. 이 기준이 기획자와 개발자, 운영자 사이에서 다르게 이해되면 프로그램은 누군가의 기대와 다르게 작동한다.

두 번째 이유는 예외 상황 누락이다. 예외 상황은 평소 흐름에서 벗어난 경우를 말한다. 입력칸을 비워 둔 채 제출하거나, 결제 버튼을 여러 번 누르거나, 인터넷이 끊긴 상태에서 예약을 시도하는 일이 여기에 해당한다. 사용자는 늘 안내서처럼 행동하지 않는다. 그래서 좋은 서비스는 정상적인 사용뿐 아니라 실수, 중복 클릭, 지연, 취소 같은 상황도 고려해야 한다.

세 번째 이유는 데이터 문제다. 데이터는 서비스의 기억이다. 그런데 이 기억이 항상 깨끗하게 정리되어 있는 것은 아니다. 같은 이메일이 두 번 저장되어 있거나, 예전 정책에 따라 만들어진 주문 데이터가 남아 있거나, 날짜 형식이 서로 다를 수 있다. 프로그램은 규칙대로 데이터를 읽는데, 데이터가 그 규칙을 벗어나면 예상하지 못한 결과가 나온다.

네 번째 이유는 환경 차이다. 개발자의 컴퓨터에서는 잘 되던 기능이 실제 사용자의 스마트폰에서는 안 될 수 있다. 브라우저 종류, 운영체제 버전, 앱 버전, 화면 크기, 네트워크 속도, 결제사의 상태가 모두 다르기 때문이다. 특히 앱은 사용자가 최신 버전으로 바로 업데이트하지 않을 수 있어 더 많은 조합을 고려해야 한다.

정상 상황과 예외 상황을 함께 확인해야 한다

테스트는 만든 기능이 기대한 대로 작동하는지 확인하는 과정이다. 여기서 중요한 점은 정상 상황만 확인해서는 충분하지 않다는 것이다. 정상 상황은 사용자가 서비스가 의도한 길을 그대로 따라가는 경우다. 예를 들어 올바른 이메일과 비밀번호를 입력해 회원가입에 성공하는 흐름이다.

하지만 실제 품질은 예외 상황에서 더 잘 드러난다. 회원가입 기능이라면 다음과 같은 상황을 확인해야 한다.

  • 올바른 정보로 가입이 되는가

  • 이미 가입된 이메일을 입력하면 적절한 안내가 나오는가

  • 비밀번호가 너무 짧거나 형식에 맞지 않을 때 막히는가

  • 인증번호가 틀렸거나 만료되었을 때 다시 시도할 수 있는가

  • 필수 약관에 동의하지 않으면 가입이 진행되지 않는가

결제 기능은 더 조심스럽다. 결제는 돈과 직접 연결되기 때문이다. 정상 결제뿐 아니라 카드 한도 초과, 잔액 부족, 결제 도중 인터넷 끊김, 결제 버튼 중복 클릭, 결제사 응답 지연을 확인해야 한다. 특히 결제는 성공했는데 우리 서비스의 주문 저장이 실패하는 경우처럼 중간 상태가 생길 수 있다. 이때 사용자는 돈을 냈는데 주문이 없다고 느낀다. 이런 상황을 줄이려면 결제 결과와 주문 상태를 다시 맞춰 보는 절차가 필요하다.

예약 기능도 마찬가지다. 비어 있는 시간에 예약이 되는지만 보면 부족하다. 두 사람이 동시에 마지막 한 자리를 예약하려 할 때 어떻게 처리할지, 영업시간이 지난 날짜를 선택할 수 있는지, 관리자가 막아 둔 시간대가 사용자에게 보이는지 확인해야 한다. 예약은 시간, 인원, 장소, 취소 정책이 얽혀 있어 작은 기준 차이가 곧 오류가 된다.

수동 테스트와 자동 테스트는 역할이 다르다

테스트에는 사람이 직접 확인하는 수동 테스트와 프로그램이 반복해서 확인하는 자동 테스트가 있다. 둘 중 하나만 있으면 된다고 생각하기 쉽지만, 실제로는 역할이 다르다.

수동 테스트는 사람이 사용자의 입장에서 직접 눌러 보고 읽어 보는 방식이다. 화면이 어색하지 않은지, 안내 문구가 이해되는지, 버튼 위치가 헷갈리지 않는지 확인하는 데 강하다. 새로 만든 기능이나 복잡한 흐름을 처음 점검할 때도 유용하다. 사람은 예상 밖의 이상함을 잘 발견한다. 예를 들어 기능은 작동하지만 오류 메시지가 너무 차갑거나, 사용자가 다음에 무엇을 해야 할지 모르는 문제는 수동 테스트에서 잘 드러난다.

반면 수동 테스트는 반복에 약하다. 매번 회원가입, 로그인, 상품 선택, 결제, 취소를 사람이 직접 확인하면 시간이 많이 걸리고 빠뜨리는 항목도 생긴다.

자동 테스트는 이런 반복 확인을 프로그램에 맡기는 방식이다. 예를 들어 가격 계산이 정확한지, 로그인 규칙이 유지되는지, 주문 상태가 올바르게 바뀌는지 자동으로 검사할 수 있다. 한 번 만들어 두면 기능을 수정할 때마다 빠르게 다시 확인할 수 있다. 예전에는 잘 되던 기능이 새 수정 때문에 망가지는 일을 회귀라고 하는데, 자동 테스트는 이런 회귀를 줄이는 데 도움이 된다.

다만 자동 테스트도 만능은 아니다. 테스트 자체를 만드는 시간과 비용이 들고, 무엇을 확인할지 사람이 정해야 한다. 잘못 만든 자동 테스트는 중요한 문제를 놓칠 수 있다. 그래서 실제 프로젝트에서는 중요한 규칙과 자주 반복되는 흐름은 자동으로 확인하고, 사용자 경험과 새 흐름은 사람이 직접 살펴보는 식으로 섞어 쓴다.

오류 메시지, 로그, 재현 단계는 문제 해결의 단서다

오류가 났을 때 가장 답답한 말은 "안 돼요"다. 사용자 입장에서는 당연한 표현이지만, 문제를 고치는 사람에게는 단서가 부족하다. 어떤 화면에서, 어떤 버튼을 눌렀고, 어떤 값이 입력되었으며, 언제 발생했는지가 필요하다.

오류 메시지는 사용자에게 현재 상황과 다음 행동을 알려 주는 문장이다. "오류가 발생했습니다"보다 "인증번호가 만료되었습니다. 새 인증번호를 받아 주세요"가 낫다. 좋은 오류 메시지는 사용자를 탓하지 않고, 가능한 해결 방법을 알려 준다.

로그는 프로그램이 남기는 기록이다. 사람이 CCTV를 보고 상황을 되짚어 보듯이, 개발자는 로그를 보고 서버가 어떤 요청을 받았고 어떤 순서로 처리했는지 확인한다. 예를 들어 결제 실패가 발생했을 때 로그에는 결제 요청 시간, 주문 번호, 결제사 응답, 서버 처리 결과 같은 정보가 남을 수 있다. 이 기록이 있어야 카드 문제인지, 결제사 문제인지, 우리 서버 문제인지 구분할 수 있다.

다만 로그에도 주의가 필요하다. 비밀번호, 주민등록번호, 카드번호 같은 민감한 정보가 그대로 남으면 보안 문제가 된다. 문제 해결에 필요한 정보는 남기되, 개인정보는 최소한으로 다루어야 한다.

재현 단계는 같은 오류를 다시 일으키는 방법이다. 요리법처럼 순서가 구체적일수록 좋다. 예를 들어 "예약이 안 됩니다"보다 "아이폰에서 앱 2.3.1 버전으로 접속해 6월 20일 오후 7시, 4명을 선택한 뒤 쿠폰을 적용하고 예약 버튼을 두 번 누르면 실패 메시지가 나옵니다"가 훨씬 유용하다. 재현할 수 있는 버그는 원인을 찾기 쉽고, 고친 뒤에도 다시 확인할 수 있다.

테스트는 품질의 기준을 맞추는 일이다

테스트는 개발이 끝난 뒤 대충 눌러 보는 절차가 아니다. 무엇을 정상으로 볼지, 어떤 예외를 막아야 할지, 문제가 생겼을 때 어디까지 안내해야 할지를 정하는 품질 기준이다.

버그가 전혀 없는 서비스를 만드는 것은 현실적으로 어렵다. 서비스가 커질수록 기능은 서로 연결되고, 사용 환경은 다양해지며, 외부 API나 결제사처럼 우리가 직접 통제하지 못하는 요소도 늘어난다. 중요한 것은 버그를 없다고 믿는 것이 아니라, 중요한 위험을 먼저 찾고 줄이는 것이다.

오해하기 쉬운 점도 있다. QA 담당자가 있으면 모든 버그를 찾아 줄 것이라고 생각하기 쉽지만, 품질은 한 사람의 역할이 아니다. 요구사항을 정하는 사람은 기준을 명확히 해야 하고, 개발자는 예외를 고려해야 하며, 운영자는 실제 사용자 문제를 잘 기록해야 한다. 자동 테스트가 있으면 수동 테스트가 필요 없다는 생각도 위험하다. 자동 테스트는 정해 둔 질문에는 빠르게 답하지만, 사용자가 느끼는 어색함까지 모두 판단하지는 못한다.

결국 오류, 버그, 테스트를 이해한다는 것은 개발의 현실을 이해하는 일이다. 좋은 서비스는 문제가 한 번도 생기지 않는 서비스가 아니라, 문제가 생길 가능성을 줄이고, 생겼을 때 빠르게 원인을 찾고, 사용자에게 안전한 길을 안내하는 서비스다.

책 목록

일반인이 쉽게 이해하는 개발 지식

전체 목차 보기

이 노트는 보도·비평·교육·연구 목적으로 작성되었습니다. 저작권 문의가 있으시면 에서 알려주세요.

틸노트는 사용자가 AI를 활용해 노트를 쉽게 작성하거나 편집할 수 있는 서비스입니다.

AI 스퀘어 단톡방에 함께해요

AI 활용과 틸노트 사용 팁을 나누는 오픈채팅방입니다. 입장 비밀번호는 tilnote입니다.

참여하기