프로젝트의 시작
이번 프로젝트는 구름톤 유니브 시즌톤 시작 전, 미리 프로젝트를 진행해보면 좋겠다는 생각에 시작하게 된 팀 프로젝트다. 방학 기간 내 MVP 개발 완료를 목표로, 초기에는 디자이너 1명, 백엔드 5명으로 구성되었으나 이후 프론트엔드 팀원이 합류해 총 7명이 함께하게 되었다.
이번 프로젝트의 주요 목표는 MSA 아키텍처 도입과 함께, 팀원 모두가 기획 → 기능 명세 → API 명세 → ERD 설계 → 개발 → 배포 → CI/CD까지의 개발 전 과정을 경험하는 것이다. 백엔드는 5명이기 때문에 MVP 기능은 빠르게 개발할 수 있을 거라 판단했다. 개인적으로는 성능 최적화를 고려한 백엔드 설계를 중점적으로 목표 삼고 있다!
아이디어 기획
회의를 통해 영수증 기반 가계부 정리 프로젝트를 진행하기로 결정되었지만, 서비스 기획에는 명확한 문제 정의와 타겟 유저 설정이 중요하다고 판단해 각자 해결하고 싶은 문제와 서비스 아이디어를 정리해보자고 제안했다. 난 소상공인을 위한 지출장부 정리 서비스를 제안했지만, 팀원 모두가 공감할 수 있는 주제는 아니었기 때문에 아이디어를 다시 수집하고 투표를 통해 최종 주제를 선정했다.
그 결과, 내가 제안한 회계 관리 서비스가 최종 주제로 선정되었다!


다음으로 중요한 것은 타겟 유저 설정이었다. 팀원 모두가 대학생이기 때문에, 대학생 입장에서 공감할 수 있는 서비스라면 더 의미 있을 것이라 생각했다. 그러던 중, 문득 4년간 학생회 활동을 하며 느꼈던 불편한 회계 처리 경험이 떠올랐다.
학생회에서는 지출 및 수입을 수기로 관리해야 했다. 감사보고서 작성 시 영수증 누락은 감점으로 이어졌기 때문에 종종 잃어버린 영수증을 다시 받기 위해 해당 가게에 연락하거나, 멀리 있는 곳이라면 직접 찾아가야 하는 번거로움이 있었다. 또한, 지출 내역은 종이에 직접 기록해야 했기 때문에 여러 명이 더블체크를 해야하는 건 기본이고 누적 지출을 확인할 때도 매번 계산기로 일일이 합산해야 하는 불편함이 있었다. 또 매번 양식에 맞춰 수많은 영수증을 붙여야하는 것도 여간 불편함이 아니었다.
이러한 경험을 바탕으로, 실제 사용자의 입장에서 불편함을 해소할 수 있는 회계 관리 서비스가 필요하다고 느꼈다.
감사하게도! 다들 동의해주어서 해당 타겟을 대상으로 서비스 주제를 확정지을 수 있었다.


서비스명을 정하는 과정에서도 다양한 아이디어가 나왔다. 어카운튜던트, accountudent, 땡자비스, 어캐썻두?, seta, 분식회계 등 재미있고 창의적인 이름들이 제안되었다. 그중에서도 ‘분식회계’는 분식(음식)과 회계를 결합한 센스있는 네이밍으로 개인적으로 매우 마음에 들었지만, ‘경영 성과를 실제보다 좋게 보이도록 회계를 조작하는 행위’라는 부정적인 의미가 담겨 있어 아쉽게도 사용할 수 없었다. 아이디어는 정말 좋았지만, 의미 때문에 반려할 수밖에 없었다는 점이 아쉬웠다. 😢
그러던 중 무도키즈로서 ‘정총무가 쏜다!’라는 장면이 떠올랐고, 이를 모티브로 ‘정총무(정직한 총무)’라는 이름을 제안했다. 예상보다 팀원들의 반응이 매우 긍정적이어서 결국 정총무를 공식 서비스명으로 확정할 수 있었다!

핵심 기능
| 소셜 로그인 | 카카오 등 OAuth 기반 로그인, 단독 총무 권한만 부여 |
| 영수증 이미지 업로드 + OCR | 실물/전자영수증 업로드 시 항목 자동 추출 |
| OCR 결과 수정 + 메타 수기 입력 | 행사명, 사용처 등 수기입력 필드 포함 |
| 원본 이미지 첨부 저장 | OCR 정보와는 별도로 원본 이미지 파일도 함께 저장 (감사용 증빙) |
| 수입 수기 등록 기능 | 회비 납부, 교비 지원 등 직접 입력 |
| 장부 내역 관리 + 검색 | 날짜/항목/카테고리로 검색 가능 |
| 통계 기능 | 월별/분기별 지출 요약, 항목별 비율, 평균 지출 등 |
| 장부 내보내기 (PDF/CSV) | 수정 불가 내보내기 양식으로 책임 분산 방지 + 제출 문서로 사용 |
우선 팀원들과 다 함께 핵심 기능을 정리했다. 이후 각자 하나의 기능을 개발해보면 좋을 것 같아 5개의 큰 카테고리로 나누고, 각자 맡아서 개발해보고 싶은 기능을 선택했다.
| 회원 서비스 | 사용자 | 로그인, 단위 설정, 마이페이지 |
| 통계 서비스 | 통계/집계 | 월별/카테고리별 지출, 내보내기 통계용 |
| 코어 서비스 | 장부 등록 전반 | 이미지 업로드 + OCR + 결과 저장 |
| 코어 서비스 | 장부 관리/검색 | 장부 목록, 필터 검색, 상세 조회 |
| 코어 서비스 | 내보내기 + 수입 등록 | 수입 수기 입력, PDF/CSV 내보내기 |
장부 관리/검색
이번 프로젝트에서 나는 ‘장부 관리 및 검색 기능’을 맡게 되었다.
처음에는 단순하게 생각했다. “그냥 리스트로 쭉 보여주기만 하면 되지 않을까?” 하지만 생각보다 고려할 게 많았다.
특히 무한로딩 방식으로 데이터를 보여줄 때는 어떻게 하면 성능을 최적화할 수 있을지, 그리고 사용자가 검색을 할 경우에는 어떤 기준으로, 어떤 방식으로 검색 결과를 노출할지를 고민하게 되었다.
검색 기능은 어떻게 구현하면 좋을까? 처음에는 그냥 상품명에 LIKE '%검색어%'를 걸면 되는 줄 알았다. 하지만 실제로 적용하려고 하니 아래와 같은 문제들이 발생할 수 있을 것 같았다.
- 검색 결과가 늦게 뜬다
- 검색어 오타 하나로 결과가 안 나온다
- 조건 필터를 조합하면 더 느려진다
- 연관 검색어나 자동완성, 정렬 기준도 고려해야 한다
특히 우리가 만드는 서비스는 지금은 우리 학교 내에서만 사용할 예정이지만, 장기적으로는 전국의 학교 단위로 확장하는 것을 목표로 하고 있었다. 즉, 지금 단순하게 구현하더라도 확장을 고려한 설계가 필요하다는 걸 깨달았다. 이쯤에서 단순한 RDB 기반 검색으로는 한계가 있다는 생각이 들었고, 자연스럽게 검색 전문 도구에 대해 찾아보기 시작했다.
Elasticsearch
그중 가장 많이 언급된 것이 바로 Elasticsearch였다.
Elasticsearch는 실시간 분산 검색 및 분석 엔진이다. 처음엔 그냥 단어 매칭 잘 해주는 도구겠지~하고 생각했지만, 알고 보니 이건 단순한 키워드 검색을 넘은 검색 품질 자체를 설계할 수 있는 플랫폼에 가까웠다. 보통 엘라스틱서치는 RDB와 함께 사용한다고 한다. 예를 들어, MySQL에 데이터를 저장하고, 검색에 특화된 색인은 Elasticsearch가 따로 맡는다.
이런 구조를 통해 데이터는 안정적으로 저장하면서도, 검색은 빠르고 유연하게 처리할 수 있다. 게다가 Elasticsearch는 REST API 기반으로 동작하고, 데이터는 JSON 형식으로 주고받는다. 덕분에 백엔드에서 직접 연동하기도 수월하다.
Elasticsearch는 내부적으로 Apache Lucene을 기반으로 만들어졌다. Lucene은 텍스트 기반 검색에 최적화된 라이브러리이고, 그 핵심은 바로 역색인(inverted index) 이다. 역색인은 “어떤 단어가 어떤 문서에 포함되어 있는지”를 기준으로 색인을 만든다.
예를 들어, 아래와 같은 문서가 있다고 해보자.
문서 1: 오늘은 날씨가 좋다
문서 2: 오늘은 밥을 먹었다
이 문서를 역색인하면 다음과 같이 구성된다:
"오늘" → 문서 1, 문서 2
"날씨" → 문서 1
"밥" → 문서 2이런 구조를 활용하면, 사용자가 “오늘”이라는 단어를 검색했을 때 관련된 문서를 빠르게 찾아낼 수 있다.
또한 역색인은 단어의 빈도와 희귀성까지 고려해서 관련성 점수(score)를 계산한다.
예를 들어, 너무 자주 나오는 단어는 중요도가 낮고, 적게 나오지만 특정 문서에 핵심적으로 포함된 단어는 높은 점수를 받는다.
Elasticsearch는 이런 방식으로 검색 결과를 정렬하고, 유의미한 결과를 빠르게 반환한다.
단순한 검색 기능이라고 생각했지만
검색이라는 행위에는 생각보다 많은 기술적 고려와 성능 최적화의 고민이 필요하다는 걸 느꼈다. 엘라스틱서치를 도입할 수 있다면 도입해보고싶다 !
https://techblog.woowahan.com/20161/
검색 성능 개선을 위한 Elasticsearch 인덱스 구조와 쿼리 최적화 | 우아한형제들 기술블로그
2023년 12월, 배달의민족 앱 상단 검색 기능에 장보기•쇼핑 탭이 추가되었습니다. 검색 창에 검색어를 입력하고 장보기•쇼핑 탭을 누르면 비마트와 배민스토어 상품만 검색할 수 있는 기능입니
techblog.woowahan.com