불편함에서 시작된 효율화: QA 리포트 자동화하기
동으로 작성하던 QA 데일리 리포트의 비효율과 휴먼 에러 문제를 해결하기 위한 여정
불편함에서 시작된 효율화: QA 리포트 자동화하기
안녕하세요. 29CM QE(Quality Engineering)팀 정다정입니다.
29CM QE팀에서는 테스트 종료 시점뿐만 아니라 매일 업무 종료 시간에도 협업자들이 QA 진행 상황을 쉽게 파악할 수 있도록 데일리 리포트를 전달하고 있습니다. 그러나 초기에는 리포트의 항목과 형식이 통일되어 있지 않아 작성 방식이 제각각이었고, 이로 인해 작성자나 리포트를 확인하는 협업자 모두가 내용을 직관적으로 이해하기 어려운 경우가 종종 있었습니다.
이를 해결하기 위해 리포트 표준 템플릿을 마련했지만, 템플릿을 복사, 붙여넣기 하는 수작업은 비효율적이었습니다. 그래서 필요한 정보만 입력하면 자동으로 리포트를 생성해 주는 Slack Bot을 개발하게 되었습니다. 이번 글에서는 Daily Report Bot을 만들면서 마주쳤던 문제와 그 해결 과정을 공유하고자 합니다.
리포트 자동화를 위한 준비
가장 먼저 진행한 일은 리포트에 어떤 항목을 포함할지, 어떤 형식으로 보여줄지를 팀원들과 함께 정하는 것이었습니다. 이 과정에서는 단순히 형식을 맞추는 것뿐만 아니라, 실제 리포트 수신자가 어떤 정보를 가장 빠르게 확인해야 하는지에 초점을 맞췄습니다.
우선 리포트에 포함되어야 하는 핵심 항목
- 테스트 대상
- 테스트 진행률
- 이슈 개수
- 특이사항 등
을 구체화하고, 각 항목이 어떤 순서와 구조로 표시되어야 이해하기 쉬울지 논의했습니다.
결정된 내용을 바탕으로 UI 템플릿을 설계했으며, Bot이 어떤 값을 받아 어떻게 가공해 보여줄지를 함께 구상했습니다.
Slack Bot 개발 과정
리포트 자동화를 위해 Slack Bot을 직접 개발하기로 결정한 이후, 어떤 개발 방식을 사용할지에 대한 고민이 시작되었습니다. Flask를 기반으로 Slack API를 연동하는 방식과, Slack에서 제공하는 Python 라이브러리인 Slack Bolt를 사용하는 방식을 비교하며 저희에게 더 맞는 개발 방식을 찾아갔습니다.
고민 끝에 저희는 Slack Bolt의 Socket Mode를 활용하기로 했습니다. Socket Mode를 사용하면 외부에서 접근 가능한 Request URL 없이도 Slack과의 실시간 양방향 통신이 가능해져, 별도의 서버 환경 구성없이도 빠르게 개발을 시작할 수 있다는 장점이 있었습니다. 덕분에 보다 간단한 구조로 Bot을 설계할 수 있었고, 개발 및 배포에 드는 시간과 리소스를 줄일 수 있었습니다.
Report Bot 구조
Report Bot은 사용자가 Slack에서 슬래시 커맨드(/qa_report)를 입력하면서 동작을 시작합니다. 명령어 입력 시 모달이 열리고, 여기서 멘션할 협업자, 테스트 진행률, 이슈 요약, 특이 사항 등을 순서대로 입력합니다. 사용자의 응답은 미리 정의한 리포트 형식에 맞춰 자동으로 구성되도록 설계했습니다.

Report Bot의 구조
Jira API 호출을 통한 자동 이슈 집계
Report Bot의 핵심 기능은 Jira API를 호출해 전체 이슈 개수와 오늘 등록된 이슈 개수를 자동으로 집계하는 기능입니다.
기존에는 담당자가 Jira 보드에서 이슈를 직접 세는 방식으로 리포트를 작성했습니다. 이 과정은 시간이 오래 걸릴 뿐만 아니라, 이슈 개수를 잘못 세는 휴먼 에러가 발생할 가능성이 높았습니다.
이를 개선하기 위해 Jira API를 호출하여 코드 레벨에서 자동으로 이슈를 집계하도록 구조를 설계했습니다. 특히, 단순히 전체 이슈 수를 불러오는 것이 아니라, 테스트 중인 기능에 대한 이슈만 필터링하여 집계할 수 있도록 했습니다.
사용자가 슬래시 커맨드(/qa_report)로 Bot을 호출할 때, 테스트 중인 ‘카테고리명'도 함께 입력 받고 있습니다. Bot은 이를 Jira API 쿼리 파라미터로 매핑하여 해당 카테고리에 등록된 이슈만 자동으로 집계합니다.

이를 통해 직접 필터를 설정하거나, 이슈 개수를 일일이 세지 않아도 테스트 대상 기능별로 최신 정보를 포함한 리포트를 빠르게 생성할 수 있게 되었습니다.
Testrail API 호출을 통한 테스트 진행률 자동화
기존에는 테스트 진행 상황을 리포트에 포함하기 위해 Testrail에서 진행률을 직접 확인하고 수동으로 입력한 뒤, 진행률 그래프의 스크린샷을 첨부하는 방식으로 리포트를 작성했습니다. 이 과정 단순한 반복 작업으로 매일 반복하다보니 효율성이 떨어지고 있었습니다.
이를 개선하기 위해 Testrail API를 호출하여, 테스트 진행률을 테이터로 응답받아 코드 레벨에서 연산화하고, 시각화하는 구조를 구축했습니다. Report Bot은 리포트 생성 시점에 TestRail API로 진행 중인 테스트 Plan의 완료/실패 케이스 수 등을 조회하고, 이를 바탕으로 전체 진행률과 Pass/Fail 비율을 계산합니다. 이후 matplotlib로 진행률 그래프를 자동 생성해 리포트 스레드에 업로드하도록 구현했습니다.

이를 통해 사용자는 더 이상 진행률을 수동으로 입력하거나 그래프를 캡처하지 않더라도 전체 진행률, Pass/Fail률 및 시각화된 진행 상태를 포함한 리포트를 생성할 수 있게 되었습니다.
한편, 실제 프로젝트에서는 모든 테스트가 항상 Testrail에서 관리되는 것은 아니었습니다. 이에 대응하기 위해, Report Bot에서는 테스트 관리 방식을 선택할 수 있는 옵션을 추가했습니다. Testrail을 사용할 때는 API를 통해 데이터를 자동 수집하고, 그렇지 않으면 사용자가 직접 진행률을 입력할 수 있도록 하였습니다.
이로써 Report Bot은 테스트 관리 도구에 종속되지 않고, 팀의 상황에 맞게 다양한 테스트 관리 방식을 지원할 수 있는 구조를 갖추게 되었습니다.

입력된 테스트 진행 방식에 따라 리포트로 전송되는 데이터의 변동
최종적으로 생성된 리포트는 지정된 Slack 채널로 전송되며, 누구나 같은 형식으로 정보를 빠르게 확인할 수 있어 반복 작업을 줄이고 실수를 방지하는 데 큰 도움이 되었습니다.

최종적으로 전송된 데일리 리포트
개발 중 겪었던 문제와 해결 과정
Bot을 개발하는 과정에서 예상하지 못한 크고 작은 문제들이 발생했고, 그때마다 원인을 분석하고 해결책을 찾아야 했습니다.
카테고리명 입력 오류로 인한 신뢰성 문제
가장 먼저 마주친 문제는 휴먼 에러였습니다. Report Bot은 Jira API를 호출하여 등록된 이슈 수를 자동으로 집계하는데, 이때 필요한 핵심 정보 중 하나가 바로 이슈를 등록할 때 함께 입력되는 ‘카테고리명’입니다.
문제는 사용자가 카테고리명을 잘못 입력하는 경우였습니다. 예를 들어, “UI_UX”를 “UI-UX”처럼 다르게 입력하거나 특수문자를 포함하여 작성할 경우, Bot이 해당 카테고리를 인식하지 못해 Jira API 호출이 실패하거나, 이슈의 개수가 잘못 확인되어 실제와 다르게 표시되는 문제가 발생했습니다. 리포트 자동화가 잘 작동하더라도 잘못된 정보를 전달하게 되면서 결과의 신뢰성이 떨어지는 상황이었던 것이죠.
이 문제를 해결하기 위해 다양한 방법을 검토했습니다. 가장 먼저 고려했던 방법은 입력한 카테고리명에 매핑되는 이슈의 개수가 0개일 경우, 경고 메시지를 전달하는 방법이었습니다.
하지만 이 방법에는 한 가지 문제가 있었습니다. 카테고리명이 정확히 입력되었더라도, 해당 카테고리에 실제 등록된 이슈가 없거나 이미 모두 처리된 경우에도 경고 메시지가 발생할 수 있다는 점입니다. 정상적인 입력임에도 불필요한 경고가 노출될 수 있기에 이 방법은 제외했습니다.
이에 따라 다음과 같은 두 가지 개선을 적용했습니다.
- 사용자가 카테고리명을 입력한 후 바로 추가 확인 모달을 띄워 올바른 카테고리명인지 한 번 더 검증하도록 했습니다.
- 입력 단계에서 특수문자나 허용되지 않은 문자열이 포함되면 경고 메시지를 전송하여 Jira API 호출이 실패하지 않도록 했습니다.

카테고리명 더블 체크하기
이 개선을 통해 잘못된 카테고리 입력으로 인한 API 호출 오류가 크게 줄었고, 리포트에 표시되는 이슈 통계도 더 안정적이고 정확한 정보를 전달할 수 있게 되었습니다.
Jira API 호출 속도 지연으로 인한 리포트 전송 실패
두 번째로 마주한 문제는 Jira API 호출 속도 지연이었습니다. 매일 QA 리포트에 포함될 이슈 통계 데이터를 Jira API를 통해 실시간으로 집계합니다. Report Bot 초기 구현에서는 단순한 동기 방식으로 Jira API를 호출했습니다. 사용자가 모달에서 리포트 데이터를 입력하고 전송 버튼을 누르면, 봇이 Slack 채널로 리포트를 전송하기 전에 Jira API를 호출해 필요한 데이터를 응답받을 때까지 기다리는 구조였습니다.
하지만 등록된 이슈가 많아지면서 Jira API가 모든 데이터를 조회하고 응답을 반환하는 데 3초 이상 소요되는 경우가 발생했습니다. 이때, 문제는 Slack API의 타임아웃 제약이었습니다. Slack의 인터랙티브 컴포넌트(ex. 모달 오픈, 버튼 클릭 등)은 요청 이후 3초 이내에 응답이 없으면 연결을 끊어버리는 구조를 가지고 있습니다. 따라서 Jira API 응답이 늦어지는 경우, Slack 측에서는 “Bot이 응답하지 않는다”고 판단해 리포트 전송 프로세스가 도중에 실패하는 상황이 발생했습니다.

리포트 전송 중 타임아웃 에러 발생
이 문제를 해결하기 위해 우리는 Jira API 호출 로직을 별도의 스레드에서 비동기적으로 처리하도록 구조를 변경했습니다. 변경된 로직의 주요 포인트는 다음과 같습니다.
- 메인 프로세스는 즉시 Slack에 응답하여 타임아웃을 피한다.
- Jira API 호출은 별도의 백그라운드 스레드에서 실행해, 메인 프로세스를 블로킹하지 않는다.
import threading
def request_jira_api():
# 오래 걸릴 수 있는 Jira API 호출을 별도의 스레드에서 처리
thread = threading.Thread(
target=request_jira_api,
args=(client, body, user_id, channel_id, feature_name)
)
thread.start()
이 구조에서는 Slack이 먼저 빠르게 응답받고, 첫 번째 문제 해결 과정에서 추가된 카테고리명 확인 모달이 즉시 표시됩니다. 그 사이 백그라운드 스레드에서 request_jira_api() 함수가 실행되어 Jira API를 호출 및 응답받도록 하여 타임아웃을 피하고 있습니다.
이 변경을 통해 타임아웃 문제를 해결할 수 있었고, 등록된 이슈가 많더라도 안정적으로 리포트가 전송되는 구조를 갖추게 되었습니다.
현재는 Python의 기본 threading 모듈을 이용해 비교적 단순한 수준의 비동기화를 구현했지만, 추후에는 asyncio 기반의 비동기 처리 구조로 확장할 계획입니다. 이후, 이 확장을 통해 Jira 외에도 여러 외부 API를 동시에 호출할 때 성능을 더 안정적으로 유지할 수 있을 것으로 기대하고 있습니다.
여러 사용자가 Bot을 동시에 호출할 수 없는 문제
동시에 여러 사용자가 봇을 호출할 경우 데이터 충돌이 발생하기도 했습니다. 예를 들어, A 채널과 B 채널에서 동시에 리포트 봇을 실행했을 때, A 채널에 전송되어야 할 리포트가 B 채널로, B 채널의 리포트가 A 채널로 뒤바뀌어 전송되는 현상이 발생했습니다.
원인을 분석해보니, 봇이 여러 사용자의 요청을 공통된 전역 변수에 저장하는 구조로 되어 있어, 동시에 여러 요청이 들어올 경우 각 사용자의 입력 데이터가 서로 덮어 씌워지고 있었습니다. 즉, Bot은 “누가 어떤 채널에서 호출했는지”를 명확하게 구분하지 못하고 있었습니다.
이 문제를 해결하기 위해, Bot이 호출될 때마다 사용자 정보와 채널 정보를 하나로 매핑하여 관리하도록 구조를 변경했습니다.

바뀌면 안되는 정보를 사용자 정보와 매핑
이제는 각 사용자의 입력 데이터가 사용자별로 독립적으로 관리되며, Bot이 리포트를 생성할 때 해당 사용자와 연결된 채널로만 메시지를 전송하도록 로직을 수정했습니다.
이 개선 이후에는 동시에 여러 사용자가 Bot을 실행하더라도 리포트가 서로 섞이거나 잘못된 채널로 전송되는 문제가 해소되었습니다. 팀원 누구나 언제든지 독립적으로 봇을 사용할 수 있게 되었고, 안정성이 크게 향상되었습니다.
Report Bot 도입 이후 변화
Report Bot을 업무에 적용한 이후, 가장 큰 변화는 리포트 작성 및 공유 시간의 단축이었습니다. 이전에는 매일 15분 정도 소요되던 작성 과정이, 이제는 몇 번의 클릭과 입력만으로 완료됩니다. 그 결과 팀 내 업무 효율이 크게 개선되었고, 협업자들도 QA 리포트를 빠르고 일관된 형식으로 확인할 수 있게 되었습니다.
Report Bot을 사용하기 전에는 리포트의 모든 내용을 수기로 작성해야 했습니다. 이 과정에서 등록된 이슈의 개수를 사람이 직접 세다 보니 카운팅 오류(휴먼 에러)가 종종 발생했습니다. 또한 리포트 내에 이슈의 우선순위를 명시하지 않았던 구조여서 협업자들이 빠른 확인이 필요한 이슈의 개수를 한눈에 파악하기 어려웠습니다.
Report Bot을 도입한 이후에는 이러한 문제가 크게 줄었습니다. 봇이 Jira API를 통해 자동으로 이슈 수를 집계하고 각 이슈의 우선순위 정보를 함께 리포트에 포함하면서, 이전보다 훨씬 정확하고 직관적인 리포트를 전달할 수 있게 되었습니다. 결과적으로 휴먼 에러는 감소하고, 협업자들은 중요한 이슈를 빠르게 인지하고 대응할 수 있는 환경이 마련되었습니다.
이 경험을 계기로 저희는 파이프라인 수행 봇, 스프레드시트 자동화 봇 등 다른 반복 업무 자동화에도 도전하고 있습니다.

불편한게 있으면 한번 만들어보자
마무리
작은 불편함에서 출발한 이 프로젝트는 단순한 리포트 자동화를 넘어 일하는 방식을 주도적으로 바꿀 수 있다는 것을 보여주었습니다. Slack Bot을 직접 개발하면서 “필요한 것은 스스로 만들 수 있다.”라는 자신감도 얻었고, 자동화를 통해 반복적인 작업에 쓰이던 시간을 줄이고, 다른 주요한 업무에 더 집중할 수 있는 환경을 마련했습니다.
이번 경험을 토대로 29CM QE팀은 앞으로도 효율을 높이는 방법을 스스로 설계하고 실행할 수 있는 팀이 되겠습니다.
TEAM MUSINSA CAREER
무신사는 2001년 온라인 커뮤니티로 시작해 2005년 무신사 매거진, 2009년 무신사 스토어를 오픈하며 빠르게 성장하고 있는 국내 대표 온라인 패션 스토어입니다. ‘입점 브랜드와 동반성장’이라는 경영 철학을 바탕으로 브랜드가 안정적으로 사업을 전개할 수 있도록 무신사가 보유한 노하우와 인프라를 지원합니다. 고객에게는 풍성한 패션 콘텐츠와 패션에 특화된 차별화된 서비스로 최상의 온라인 쇼핑 경험을 제공하고 있습니다. 글로벌 №1 패션 기업으로 성장할 무신사와 함께 새로운 도전과 혁신을 만들 인재를 기다립니다.
29CM는 ‘고객의 더 나은 선택을 돕는다’라는 미션으로 출발했습니다. 우리는 우리만의 방식으로 콘텐츠를 제공하며, 브랜드와 고객 모두에게 대체 불가능한 커머스 플랫폼을 만들어가고 있습니다. 이 미션을 이루기 위해 우리는 흥미로우면서도 복잡한 문제들을 해결하고 있습니다. 만약 우리와 함께 이 문제들을 해결해 보고 싶다면, 주저하지 말고 29CM에 합류하세요!
🚀 팀 무신사 채용 페이지 (무신사/29CM 전체 포지션 확인이 가능해요)
메타데이터
- post_id
- bd6d1eba4e4d
- slug
- 불편함에서-시작된-효율화-qa-리포트-자동화하기-bd6d1eba4e4d
- url
- https://techblog.musinsa.com/%EB%B6%88%ED%8E%B8%ED%95%A8%EC%97%90%EC%84%9C-%EC%8B%9C%EC%9E%91%EB%90%9C-%ED%9A%A8%EC%9C%A8%ED%99%94-qa-%EB%A6%AC%ED%8F%AC%ED%8A%B8-%EC%9E%90%EB%8F%99%ED%99%94%ED%95%98%EA%B8%B0-bd6d1eba4e4d
- canonical_url
- https://techblog.musinsa.com/%EB%B6%88%ED%8E%B8%ED%95%A8%EC%97%90%EC%84%9C-%EC%8B%9C%EC%9E%91%EB%90%9C-%ED%9A%A8%EC%9C%A8%ED%99%94-qa-%EB%A6%AC%ED%8F%AC%ED%8A%B8-%EC%9E%90%EB%8F%99%ED%99%94%ED%95%98%EA%B8%B0-bd6d1eba4e4d
- author_url
- https://medium.com/@dajjeong
- status
- ok
- fetched_at
- 2026-06-27 07:40:21