ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [2026 ABC 프로젝트 멘토링 8기] 프로젝트 7주차
    ABC 프로젝트 2026. 7. 19. 06:36

     

    프로젝트 7주 차 — 백엔드 다듬기, RAG 품질 끌어올리기, 라벨링의 함정들

    00

    들어가며

    7주 차는 새로운 기능을 얹는 대신, 있는 것을 다시 다듬어 최종 프로덕트를 만드는 주였다. 다음 주 발표를 앞두고 큰 개발은 지난주에 마감했고, 이번 주는 시연 중 어디서 깨질지 모르는 약한 고리들을 찾아 보강하는 데 시간을 썼다. 대상은 세 곳 — 백엔드, RAG, 그리고 이미지 라벨링이다.

    다행인 부분은 이번 주에 부딪힌 문제들이 모두들 개발을 하며 겪는 문제들이었다는 점이다. 검색해 보면 다들 같은 곳에서 같은 문제를 겪고 있었다. 이번 글은 그 흔히 문제들을 우리가 어떻게 겪고, 어떤 점을 배웠는지에 대해 정리할 것이다.

    이번 주 태스크: 백엔드 보완 → RAG 품질 보완 → 이미지 라벨링 보완 → 발표 준비

    01

    백엔드 보완 — 목록이 커지자 서버가 무거워졌다

    백엔드에서 가장 먼저 손댄 건 5주 차 태스크로 올려 두었던 페이지네이션이었다. 개발 중에는 데이터가 몇십 건 뿐이라 몰랐는데, 라벨링 결과와 문서가 쌓이면서 목록 API가 매번 전체 데이터를 통째로 긁어오고 있다는 게 드러났다. 데이터가 수백 건을 넘어가자 목록 화면 하나 여는 데 응답이 눈에 띄게 느려졌고, 라즈베리파이의 한정된 메모리에 전체 결과를 올렸다가 버리는 낭비도 반복됐다.

    1목록 API가 전체 조회 — 데이터가 늘수록 느려지는 구조
    해결

    모든 목록성 API에 page / size 파라미터를 넣어 필요한 만큼만 잘라 가져오도록 바꿨다. DB 쿼리도 LIMIT/OFFSET 기반으로 정리하고, 응답에 전체 건수와 페이지 정보를 함께 실어 프런트가 페이지 UI를 그릴 수 있게 했다. 응답 크기가 줄어들자 목록 화면 체감 속도가 확실히 달라졌다. 데이터가 적을 때는 티가 안 나는 문제가 가장 중요한 것을 파악했다.

     

    2긴 AI 호출이 서버 전체를 붙잡는 문제

    또 하나는 비동기 서버에서 흔히 밟는 함정이었다. FastAPI는 비동기(async) 기반인데, 그 안에서 동기(blocking) 방식의 AI 호출과 무거운 이미지 처리가 그대로 돌고 있었다. AI 응답을 기다리는 몇 초 동안 이벤트 루프가 통째로 묶여서, 그 사이 들어온 다른 요청들—심지어 가벼운 상태 조회까지—전부 대기하는 현상이 있었다.

    해결

    무거운 동기 작업들을 스레드 풀로 넘겨 이벤트 루프 밖에서 돌게 하고, 오래 걸리는 배치성 작업은 요청-응답에서 분리해 백그라운드로 처리한 뒤 결과를 대시보드 이벤트로 알리게 했다. 5주 차에 붙인 Redis Pub/Sub 구조가 여기서도 그대로 쓰였다. async를 쓴 것과 async 답게 동작하는 것은 전혀 다른 얘기였다.

    많은 데이터가 있을 때 아래와 같은 응답을 보여주었다.

    02

    RAG 보완 — 한국어와 표, 그리고 쌓이는 중복

    RAG는 3~4주 차에 청크 설계와 하이브리드 검색으로 한 차례 다듬었지만, 실사용 데이터가 늘어나자 새로운 층의 문제들이 올라왔다. 셋 다 RAG를 만들어 본 사람이라면 고개를 끄덕일, 아주 전형적인 문제였다...

    1한국어 조사 때문에 BM25 키워드 검색이 어긋난다

    하이브리드 검색의 한 축인 BM25는 단어 단위 매칭인데, 한국어는 ‘포트홀이 / 포트홀을 / 포트홀에서’처럼 조사가 붙는 순간 전부 다른 단어가 돼 버린다. 공백 기준으로 토큰을 자르니 분명히 문서에 있는 단어인데도 키워드 점수가 0에 가깝게 나오는 경우가 잦았다. 영어 예제 코드를 그대로 가져오면 반드시 밟게 되는, 한국어 RAG의 대표적인 함정이다.

     

    BM25는 사용자가 입력한 쿼리와 문서 간의 연관성을 평가하는 키워드 기반 검색 랭킹 알고리즘을 의미한다.

    해결

    BM25에 들어가는 토크나이저를 공백 분리 대신 형태소 분석 기반으로 교체해, 조사를 떼고 어간 단위로 색인·검색하도록 바꿨다. ‘포트홀이’든 ‘포트홀을’이든 같은 ‘포트홀’로 매칭되기 시작하면서 키워드 축의 재현율이 눈에 띄게 올라왔다. 검색 엔진은 그대로인데 토크나이저 하나로 품질이 갈린다는 점을 조심해야 할 거 같다.

     

    2 같은 문서를 다시 올리면 중복 청크가 쌓인다

    사용자가 수정한 문서를 다시 업로드하면, 기존 청크가 남은 채 새 청크가 추가돼 같은 내용이 두 벌씩 인덱스에 쌓였다. 검색 상위가 사실상 같은 문단의 구버전·신버전으로 도배되면서 다양성이 죽고, 심하면 옛 버전 내용이 답변에 섞여 나왔다.

    해결

    청크에 원본 문서 ID를 메타데이터로 박고, 재업로드 시 같은 문서 ID의 기존 청크를 먼저 지운 뒤 새로 색인하는 upsert 방식으로 바꿨다. 단순한 방식이지만 이를 추가하여, 새 문서를 기반으로 하는 업데이트된 정보를 제공할 수 있었다.

     

    03

    이미지 라벨링 보완 — 임계값의 딜레마와 fallback

    이미지 라벨링 파트는 4주 차에 남겨 둔 대규모 배치 처리 보완을 이번 주에 마저 진행했다. 여기도 객체 탐지를 해 본 사람이라면 누구나 아는 함정들이 기다리고 있었다.

    1confidence threshold의 딜레마 — 낮추면 오탐, 올리면 누락

    탐지 모델은 결과마다 신뢰도(confidence) 점수를 주고, 어느 점수 이상만 채택할지 임계값을 정해야 한다. 문제는 이 값이 양쪽으로 다 위험하다는 것이다. 임계값을 낮추면 그림자나 얼룩까지 포트홀로 잡는 오탐(false positive)이 늘고, 올리면 저해상도·역광 사진에서 진짜 객체를 놓치는 누락(false negative)이 는다. 특히 멀리서 찍혀 작게 나온 객체는 애초에 점수가 낮게 나와서, 임계값을 조금만 올려도 통째로 사라졌다.

    해결

    임계값 하나로 판단하여 라벨링 작업을 end to end로 끝내는 생각을 버렸다. 채택 기준은 보수적으로 유지하되, 그 아래 애매한 점수 구간의 결과는 버리지 않고 ‘검토 필요’ 상태로 따로 표시해 사람이 확인하는 흐름으로 바꿨다. 자동 라벨링의 목적이 사람을 대체가 아니라 사람의 검수량을 줄이는 것이기 때문에 프로젝트의 원래 취지와도 맞는 방향이었다. 겹친 박스가 중복 검출되는 문제는 NMS 기준을 함께 손봐 정리했다. threshold에 기준을 잡는 것은 정말 주관적인 모델 정확도 목표를 기준으로 잡는다고 배웠기 때문에 이 부분에서 어려움을 느꼈다ㅎㅎ...

    2대량 이미지를 한 번에 처리하면 라즈베리파이가 버티지 못한다

    배치 라벨링에서 이미지 수백 장을 한꺼번에 밀어 넣자 메모리가 치솟고 처리 도중 프로세스가 죽는 일이 있었다. 죽고 나면 어디까지 처리됐는지도 몰라 처음부터 다시 돌려야 했다.

    해결

    배치를 작업 큐에 쌓아 순차·소분 처리하도록 바꾸고, 이미지별 처리 상태를 기록해 중단돼도 이어서 재개할 수 있게 했다. 작업의 진행 속도가 다소 낮아지더라고 진행 상황이 초기화되는 것과 트레이드 오프 했다고 생각하면,, 어쩔 수 없는 선택이었다.

     

    04

    마무리하며

    이번 주는 배운 것들이 많은 주였다. 이제 백엔드로써 온프레미스를 관리하며 알아둬야 할 것들에 대해 중요성을 알게 되었고, 어떤 것이 품질을 좌우하는지도 알게 되었다. 이러한 부분들을 기록하고 보완하며 성장해야겠다고 느꼈다.

    7주 차를 마치며

    이번 주 부딪힌 문제들은 하나도 특별하지 않았다. 한국어 토크나이징, PDF 표 파싱, 중복 인덱스, 임계값 딜레마, 배치 메모리 — 모두가 같이 겪은 비슷한 문제였다. 그런데 글로 읽어 아는 것과 내 서비스에서 직접 밟아 보는 건 전혀 달랐다. 흔한 문제를 직접 겪고 나서야, 그 흔한 해법들이 왜 표준이 됐는지 이해가 됐다.

    그리고 보완 작업 내내 기록의 중요성을 느꼈다. 프로젝트 후반부의 속도는 결국 전반부에 깔아 둔 구조에서 나온다는 걸 실감한 주였다.

    #ABC프로젝트멘토링 #유클리드소프트 #고용노동부 #대한상공회의소 #미래내일일경험사업
Designed by Tistory.