SYDESYDE
SYDESYDE
  • 피드
  • 쇼케이스
  • 블로그
  • 모임
SYDESYDE© 2026 SYDE. All rights reserved.
SYDE 소개문의하기
Kakao
SYDE 오픈채팅
Instagram
Instagram
Threads
Threads
커뮤니티 가이드라인협업문의이용약관개인정보처리방침
커뮤니티 가이드라인협업문의이용약관개인정보처리방침

© 2026 SYDE. All rights reserved.

최신 모델이 늘 정답은 아니었다 — Refactor.me 3편

최신 모델이 늘 정답은 아니었다 — Refactor.me 3편

d손다은· 16시간 전· 해프닝·회고
목차
  • 한 줄 요약
  • 들어가며
  • 구조: 백엔드 서버 없이 Next.js 하나로
  • 구현한 API
  • 화면: 두 갈래 입구와 결과 화면
  • 내가 맡은 화면: 경험 입력과 /me
  • GitHub 저장소에서 경험 찾기
  • 1. 후보는 사용자가 확인해야 경험이 된다
  • 2. 같은 저장소는 다시 부르지 않는다
  • 3. 실제 API로 품질, 비용, 시간을 쟀다
  • 4. 모델은 같은 표본으로 비교해서 정했다
  • 5. 시연은 고정된 결과로
  • 정리하며

목차

  • 한 줄 요약
  • 들어가며
  • 구조: 백엔드 서버 없이 Next.js 하나로
  • 구현한 API
  • 화면: 두 갈래 입구와 결과 화면
  • 내가 맡은 화면: 경험 입력과 /me
  • GitHub 저장소에서 경험 찾기
  • 1. 후보는 사용자가 확인해야 경험이 된다
  • 2. 같은 저장소는 다시 부르지 않는다
  • 3. 실제 API로 품질, 비용, 시간을 쟀다
  • 4. 모델은 같은 표본으로 비교해서 정했다
  • 5. 시연은 고정된 결과로
  • 정리하며

사이드 프로젝트에 AI 기능을 붙여 놓고 "모델만 더 좋은 걸로 바꾸면 나아지겠지"라고 생각해 본 적이 있다면, 이 글에서 우리가 같은 생각을 숫자로 확인해 본 과정을 볼 수 있다.

원티드 AI Championship 2026에서 5명이 만들어 TOP 20에 선정된 Refactor.me의 기획부터 데모데이까지를 5편으로 정리했다.

  1. 기획 — 무엇을, 왜 만들기로 했나

  2. 구현 ① — 기술 블로그와 채용 공고 데이터 파이프라인

  3. 구현 ② — 화면, 그리고 GitHub 저장소에서 경험 찾기

  4. 검증 — AI가 만든 제안의 근거를 어떻게 믿을 것인가

  5. 데모데이 후기와 회고

한 줄 요약

백엔드 서버 없이 Next.js 하나로 화면을 만들고, GitHub 저장소에서 경험을 찾는 기능을 실제 API로 측정했다. 놓친 근거의 대부분은 모델이 아니라 모델에 파일을 고르는 선별기에서 빠지고 있었고, 같은 표본으로 비교해 보니 더 싸고 새로운 모델이 더 나은 선택은 아니었다.

들어가며

2편에서 만든 데이터는 결국 사람이 보는 화면으로 나가야 한다. 이번 글은 화면을 어떻게 구성했는지, 그리고 서비스에서 유일하게 실시간으로 LLM(대규모 언어 모델)을 부르는 기능인 GitHub 저장소 분석을 어떻게 만들고 확인했는지에 대한 이야기다.

구조: 백엔드 서버 없이 Next.js 하나로

부분

방식

회사 × 직무 결과 화면

파이프라인이 만든 JSON 파일을 빌드할 때 미리 읽어서 페이지로 만들어 둔다. 사용자가 들어올 때마다 서버가 다시 계산하지 않는다

경험 입력

브라우저에만 저장한다. 로그인은 없다

GitHub 저장소 분석

사용자가 요청할 때 서버에서 Claude API를 부른다

DB(데이터베이스)나 별도 백엔드 서버는 두지 않았다. 회사 데이터는 파이프라인이 미리 만들어 두므로, 미리 계산해 둘 수 있는 건 전부 미리 계산해 두는 쪽을 택했다.

서버에서 실행해야 하는 기능은 Next.js의 Route Handler(Next.js 프로젝트 안에 API 주소를 바로 만드는 기능)로 만들었다. 프론트엔드 프로젝트 안에 API를 함께 두는 방식이라, 따로 서버를 띄우지 않아도 된다.

구현한 API

API는 세 개다. 셋 다 POST이고, 전부 GitHub 저장소를 다룬다.

API

하는 일

LLM

담당

/api/repository-analysis

저장소에서 파일을 골라 Claude에게 보내고, 경험 후보를 검증해서 돌려준다

Claude 호출

팀원 A·B 중심, 나는 측정과 시연 결과 고정

/api/repo-keywords

저장소의 설정 파일(package.json 등)과 언어 정보에서 기술 키워드를 뽑는다

없음 (규칙)

팀원 D

/api/dev/repository-evidence

선별기가 어떤 파일을 골랐는지 미리 보는 개발용 API. 배포판에서는 404를 돌려준다

없음

팀원 A

/api/repo-keywords는 초기 경험 입력에서 쓰던 API다. 이후 Claude가 코드를 직접 읽는 /api/repository-analysis로 바뀌면서, 지금 화면에서는 부르지 않는다.

핵심인 /api/repository-analysis에는 실제 사용에서 생길 문제를 막는 장치가 여럿 붙어 있다. 토큰은 모델이 글을 읽고 쓰는 단위이고, 요금도 토큰 수로 매겨진다.

장치

내용

이유

호출 한도

IP(접속한 컴퓨터의 인터넷 주소)당 1시간에 15회. 넘으면 429와 함께 언제 풀리는지(Retry-After) 알려 준다

한 번 누를 때 저장소 3개까지 동시에 분석하므로, 정상 사용자는 닿지 않을 만큼 넉넉하게 잡았다

입력 토큰 상한

보내기 전에 토큰을 세어 6만 토큰을 넘으면 부르지 않는다

상한을 넘긴 걸 청구서로 알게 되면 상한이 아무 일도 안 한 것이다

재시도

유료 분석 호출은 재시도하지 않는다. 무료인 토큰 세기 호출만 SDK(API를 쉽게 부르게 해 주는 공식 라이브러리) 기본 재시도를 둔다

타임아웃도 재시도 대상이라, 켜 두면 같은 생성이 최대 세 번 청구될 수 있다

타임아웃

분석 60초, 토큰 세기 10초

실측 응답(평균 17초 안팎)의 몇 배 여유를 두되, 사람이 기다릴 수 있는 시간을 넘지 않게

실패 이유 구분

시간 초과, 잠깐 안 됨, 잔액 부족을 다른 이유로 돌려준다

"다시 해 보세요"와 "지금은 안 돼요"는 사용자가 할 일이 다르다

결과 재사용

같은 저장소, 같은 커밋, 같은 버전이면 다시 부르지 않는다

아래 2번에서 다룬다

화면: 두 갈래 입구와 결과 화면

서비스 시작 화면

1편에서 쓴 것처럼 입구는 두 갈래다.

  • 회사부터: 회사와 직무를 고르면 그 회사가 반복해서 다루는 영역과 프로젝트 제안이 나온다. 제안은 "새 프로젝트 아이디어"와 "내 프로젝트 업그레이드" 두 무리로 나뉜다.

  • 경험부터: 직무를 고르고 해 본 경험을 고르면, 회사를 "잘 맞아요 / 한 걸음 필요해요 / 지금은 거리가 있어요"로 나눠 보여 준다. 점수나 순위는 매기지 않았다.

전체 디자인과 경험 기준 회사 매칭은 팀원 B가, 단계 표시와 메인 화면 문구는 팀원 C가, 제안 상세 페이지와 연결 지도는 팀원 D가 만들었다.

내가 맡은 화면: 경험 입력과 /me

경험 입력 화면 - 체크박스

경험 입력 화면은 처음 맡은 화면이었다. 직무별 경험 항목을 체크박스와 라디오 카드로 고르게 하고, 세 섹션은 하나 이상 고르지 않으면 넘어가지 못하게 막았다. 팀원 D가 만든 저장소 키워드 추출 결과(README, 설정 파일에서 뽑은 기술 키워드)를 경험 카드의 초기 선택에 연결했다.

/me 화면 - 토스

/me 화면은 회사 결과를 내 경험 기준으로 다시 보는 화면이다. 이 화면은 여러 번 바뀌었다.

  1. 처음에는 프로젝트를 "지금 바로 시작 / 다음 목표 / 도전해 보기" 세 칸으로 나눴다.

  2. 경험이 적은 사용자는 칸이 비어 버리는 문제가 있어서, 경험이 적어도 세 칸이 빠지지 않게 고쳤다.

  3. 이후 칸 이름을 없애고 "이미 해 본 경험으로 할 수 있는 프로젝트"와 "새 경험을 얻는 프로젝트" 두 묶음으로 바꿨다. 기존 문구는 어떤 경험이 있어야 프로젝트를 시작할 수 있다는 인상을 줬다. 우리 서비스의 방향은 "다양한 프로젝트를 시도하면서 여러 경험을 얻을 수 있다"였다.

GitHub 저장소에서 경험 찾기

사용자가 공개 GitHub 저장소를 넣으면, Claude가 코드를 읽고 "이 사람이 해 본 것 같은 경험"을 후보로 뽑는다.

예시 저장소 분석 결과

  • 선별기는 저장소에서 근거가 될 만한 파일 8개를 고른다. 비용 때문에 저장소 전체를 보낼 수는 없다.

  • 응답 검증은 모델이 낸 후보를 코드로 다시 확인한다. 고를 수 있는 경험 id인지, 인용한 파일을 실제로 보냈는지, 줄 번호가 파일 안에 있는지 본다.

선별기와 판정 품질 개선은 팀원 B가, 호출 한도와 타임아웃 같은 API 안정화는 팀원 A가 맡았다. 내가 한 일은 아래 다섯 가지다.

1. 후보는 사용자가 확인해야 경험이 된다

모델이 뽑은 후보를 그대로 경험으로 넣지 않았다. 후보마다 근거가 된 파일과 줄을 보여 주고, 사용자가 직접 확인한 것만 경험으로 센다. 모델의 판단은 어디까지나 제안이다.

2. 같은 저장소는 다시 부르지 않는다

같은 사람이 저장소 여러 개를 넣다가 하나가 실패해 다시 누르거나, 뒤로 갔다 돌아오는 경우가 많았다. 이미 분석한 저장소는 다시 모델을 부르지 않게 했다. 커밋과 프롬프트 버전이 같으면 결과도 같기 때문이다.

3. 실제 API로 품질, 비용, 시간을 쟀다

시연에서 "AI가 내 저장소에서 경험을 찾는다"를 보여 줄 예정이었는데, 그 결과가 실제로 맞는지 잰 기록이 거의 없었다. 그래서 제품이 실제로 부르는 경로 그대로 재는 측정 명령을 만들었다. 모델, 시스템 프롬프트, 출력 상한, 응답 해석, 검증이 모두 제품과 같다.

표본은 정답지(봐야 할 파일 목록)가 있는 저장소 중에서 팀원 저장소를 앞에 두고 10개를 골랐다. 정답지는 "봐야 할 파일"까지만 적혀 있어서, 뽑힌 경험이 맞는지는 저장소 주인이 직접 확인해야 했기 때문이다.

기준선 (Haiku 4.5, 표본 10개)

항목

결과

호출

10/10 성공, 출력 잘림 0건

비용

10개 합계 $0.245

시간

평균 17.4초, 최대 21.8초 (모델 호출만)

후보

75개 중 74개 통과

후보가 맞는지 확인

확인한 4개 표본에서 32개 중 32개 맞음 (저장소 주인 확인 3개, 코드 대조 1개)

정답지와 대조하면 이렇다. 정답지에 있는 요구사항 54개 중 선별기가 파일을 보낸 건 35개(64.8%), 모델이 실제로 인용한 건 31개(57.4%)였다.

놓친 23개가 어디서 빠졌는지 나눠 보니, 19개는 선별기가 애초에 파일을 보내지 않은 것이었다. 모델은 받은 것의 89%를 썼다. 품질을 올리려면 모델이 아니라 선별기를 고쳐야 한다는 뜻이었다.

측정하다 세 번째 경우도 찾았다. 파일을 보내긴 했는데 파일당 글자 상한에 걸려 앞부분만 잘려 간 경우다. 한 표본에서는 동시성 제어의 실제 근거(SELECT … FOR UPDATE)가 잘린 부분에 있었는데, 모델은 다른 파일을 근거로 경험만 맞혔다. 그래서 "보냄 / 잘려서 보냄 / 안 보냄"을 나눠 세도록 선별기 개선 이슈에 넣었다.

4. 모델은 같은 표본으로 비교해서 정했다

기본 모델은 팀원 B가 Haiku 4.5로 시작해 둔 상태였다. 다른 모델로 바꾸면 나아지는지 확인하려고, 기준선과 같은 표본 9개, 같은 선별기와 프롬프트로 다른 모델을 돌렸다.

모델

응답 성공

보낸 요구사항 31개 중 인용

9개 합계 비용

평균 시간

Haiku 4.5

9/9

27 (87%)

$0.219

17.1초

Haiku 5.5

7/9

15 (48%)

$0.029

12.4초

Sonnet 5.5

9/9

20 (65%)

$0.467

13.1초

Haiku 5.5는 훨씬 싸고 빨랐지만 두 번 실패했고 인용이 절반에 그쳤다. Sonnet 5.5는 두 배 넘게 비싸면서 인용은 더 적었다. 시연 저장소에서도 Haiku 4.5가 맞는 후보를 가장 많이 냈다(8/8). 그래서 Haiku 4.5를 그대로 두기로 했다.

시연에서만 다른 모델의 결과를 쓰는 방법도 있었지만 택하지 않았다. 그러면 실제 제품보다 좋은 결과를 보여 주게 되기 때문이다.

흥미로운 차이도 있었다. 시연 저장소에서 파일이 잘려 모델이 import 줄만 볼 수 있었던 경험이 있었는데, Haiku 4.5는 "구현했다"고 썼고 5.5 모델 둘은 "import만 보인다"며 확인 필요로 뒀다. 결과는 Haiku 4.5가 맞혔다. 하지만 import 줄만 보고 "구현했다"고 단정했으니, 본 것보다 많이 말한 셈이다. 사용자 확인 단계를 둔 이유가 여기 있다.

5. 시연은 고정된 결과로

배포판은 서버 인스턴스가 요청마다 달라질 수 있어서, 메모리 캐시만으로는 시연 직전에 돌려 둔 결과가 남는다는 보장이 없었다. 그러면 시연 중에 후보가 조금씩 바뀌거나, 17초를 기다리거나, 모델 쪽 사정으로 실패할 수 있다.

그래서 시연 저장소 하나의 결과를 코드에 고정해 두고, 저장소, 커밋, 직무, 버전이 정확히 같을 때만 그 결과를 쓰게 했다. 넣기 전에 시연 커밋 코드와 하나씩 대조해 8개 후보가 모두 맞는 것을 확인했다. 커밋이 쌓이거나 버전이 오르면 키가 맞지 않아 평소처럼 모델을 부른다. 시연이 멈추지는 않고 고정 효과만 사라진다.

정리하며

품질을 올리려면 모델을 바꿔야 한다고 생각했지만, 숫자를 보니 병목은 모델 앞단의 선별기에 있었다. 또 여러 모델을 직접 비교해 보니 더 싸고 새로운 모델이 늘 나은 선택은 아니었다.

사이드 프로젝트에서 AI 기능의 품질이 아쉽다면, 모델부터 바꾸기 전에 같은 표본으로 어느 단계에서 빠지는지부터 세어 보길 권한다. 우리도 놓친 23개를 단계별로 나눠 보고 나서야 고칠 곳이 모델이 아니라는 걸 알았다.

다음 글에서는 이 프로젝트에서 가장 오래 붙잡고 있었던 문제, AI가 만든 제안의 근거를 어떻게 믿을 것인가를 다룬다.


이 글은 벨로그에 연재한 Refactor.me 해커톤 회고 시리즈의 3편입니다. 원문: [벨로그 링크]

  • #llm
  • #모델비교
  • #nextjs
  • #사이드프로젝트
  • #해커톤
9
손
손다은

손다은님의 다른 글

  • 긁어 온 데이터, 그대로 믿어도 될까? — Refactor.me 2편2일 전
  • 다음 사이드 프로젝트 주제, 회사 기술 블로그에서 찾기로 했다 — Refactor.me 1편5일 전

댓글 0

My avatar