9년 동안 제품을 만들며 배운 것


나는 처음부터 AI 개발자는 아니었다.

웹 빌더와 쇼핑몰을 만들며 개발을 시작했고, 이후 모바일 앱과 백엔드, 교육 플랫폼, 데이터 파이프라인을 거쳐 지금은 AI 제품을 설계하고 운영하고 있다. 그동안 사용하는 언어와 프레임워크는 여러 번 바뀌었지만, 계속 붙잡고 있던 질문은 하나였다.

기술을 어떻게 실제 사용자가 쓰는 제품으로 만들 것인가.

돌이켜 보면 지난 9년은 더 많은 기술을 익히는 시간이기도 했지만, 제품을 끝까지 만든다는 것이 무엇인지 배워 온 시간에 더 가까웠다.

화면을 만드는 개발자에서 제품을 보는 개발자로

개발을 시작했을 때는 화면에 보이는 결과가 가장 중요했다. 웹 빌더와 쇼핑몰 제작 플랫폼의 프론트엔드와 백엔드를 개발하며 결제, 관리자 기능, SEO, 소셜 연동처럼 서비스에 필요한 기능을 하나씩 구현했다.

이후 영어회화 학습 서비스의 iOS 앱과 서버를 함께 개발하고 AWS 인프라까지 운영하면서 생각이 조금씩 달라졌다. 사용자가 보는 화면은 제품의 일부일 뿐이었다. API가 안정적으로 응답해야 했고, 데이터가 정확히 저장되어야 했으며, 장애가 발생했을 때 원인을 찾고 복구할 수 있어야 했다.

그때부터 나를 특정 영역의 개발자로 한정하기보다, 제품에 필요한 문제를 해결하는 개발자로 생각하기 시작했다.

교육과 채용 분야의 여러 서비스를 만들 때도 마찬가지였다. Next.js와 React로 사용자 화면을 만들다가도 데이터 처리가 필요하면 백엔드로 이동했고, 성능 문제가 생기면 로딩 구조와 캐시를 살폈다. 배포와 운영이 필요하면 인프라까지 내려갔다. 프론트엔드 성능을 개선해 Lighthouse 점수를 65점에서 91점으로 높였던 경험도, 결국 목표는 점수 자체가 아니라 사용자가 기다리는 시간을 줄이는 일이었다.

이 과정을 거치며 첫 번째 원칙이 생겼다.

기술의 경계보다 사용자가 겪는 문제를 먼저 본다.

AI 개발자로의 전환은 갑작스럽지 않았다

AI 개발로의 전환은 어느 날 직무 이름만 바꾼 사건이 아니었다. 기존 제품에 AI를 연결하는 작은 실험들이 쌓이면서 자연스럽게 시작되었다.

한국어 교육 플랫폼에서 OpenAI와 Gemini를 활용해 학습 콘텐츠를 만들었고, 채용 서비스에는 자동 번역과 자기소개서 첨삭 기능을 붙였다. OpenAI Realtime API와 LiveKit으로 음성 기반 AI 면접을 실험하고, CrewAI로 대화 내용을 평가하는 흐름도 만들었다.

RAG 기반 비자 챗봇을 만들면서는 AI의 응답 품질이 모델 하나로 결정되지 않는다는 사실을 배웠다. 문서를 어떻게 나누고, 어떤 메타데이터를 저장하며, 키워드 검색과 시맨틱 검색을 어떻게 조합하는지에 따라 결과가 크게 달라졌다. BM25와 임베딩 검색, cross-encoder reranking을 연결하고 캐싱을 적용하면서 빈번한 질의의 응답 시간을 80% 줄였다.

이때 AI 개발을 바라보는 관점이 바뀌었다.

좋은 모델을 선택하는 것만으로는 제품이 되지 않는다. 모델 앞에는 좋은 데이터와 검색 구조가 필요하고, 뒤에는 평가와 관측, 실패를 다루는 시스템이 필요하다. 무엇보다 사용자가 AI의 불확실성을 그대로 떠안지 않도록 제품이 안전장치를 제공해야 한다.

데모와 프로덕션 사이에는 긴 거리가 있다

AI 데모는 빠르게 만들 수 있다. 준비된 질문에 자연스럽게 답하고, 짧은 시연에서 인상적인 결과를 보여주는 것도 가능하다. 하지만 실제 사용자는 준비된 방식으로만 행동하지 않는다.

병원 AI 제품을 만들고 운영하면서 그 차이를 매일 마주했다. 사용자는 말이 끝나기 전에 끼어들기도 하고, 아무 말 없이 전화를 내려놓기도 한다. 자동응답기가 전화를 받을 수 있고, 외부 시스템이 늦게 응답하거나 상담원 연결이 실패할 수도 있다. 모델은 같은 입력에도 예상과 다른 도구를 선택할 수 있다.

그래서 단일 에이전트에 모든 책임을 넣는 대신 역할에 따라 에이전트를 분리했고, 실시간 통화 처리와 통화 후 분석을 비동기 파이프라인으로 나눴다. 재시도와 fallback, 상담원 연결, 구조화 로그와 모니터링, 오토스케일링까지 함께 설계했다. AI 응답을 만드는 코드뿐 아니라 그 응답이 실제 전화망과 운영 환경에서 안정적으로 전달되는 전체 흐름을 제품으로 보게 되었다.

100곳이 넘는 병원에서 매일 수천 건의 AI 통화가 처리되는 시스템을 운영하며 분명해진 것이 있다.

제품은 정상적으로 동작할 때가 아니라, 예상과 다르게 동작할 때도 운영할 수 있어야 완성된다.

지금의 나를 만든 네 가지 개발 원칙

1. 기술보다 문제를 먼저 정의한다

새로운 기술은 흥미롭지만, 기술 자체가 제품의 목적이 될 수는 없다. 사용자가 어떤 순간에 어려움을 겪는지, 운영자는 무엇을 반복하고 있는지, 실패했을 때 어떤 비용이 발생하는지를 먼저 살핀다. 기술 선택은 그다음이다.

2. 좋은 아키텍처는 실패를 없애는 것이 아니라 다룰 수 있게 한다

복잡한 시스템에서 실패를 완전히 제거하는 것은 어렵다. 대신 책임을 명확히 나누고, 상태를 관찰할 수 있게 만들고, 실패 이후의 경로를 준비할 수 있다. Multi-Agent 구조나 비동기 파이프라인도 유행하는 기술이라서가 아니라, 복잡성과 실패의 범위를 통제하기 위해 선택한다.

3. 배포는 개발의 끝이 아니라 제품 학습의 시작이다

로컬에서 잘 동작하는 것과 실제 환경에서 오래 동작하는 것은 다른 문제다. 배포 이후에야 진짜 사용 패턴과 예외 상황이 보인다. 로그, 지표, 사용자 피드백을 통해 가설을 수정하고 다시 제품에 반영하는 과정까지 개발의 일부라고 생각한다.

4. 기록은 판단을 더 정확하게 만든다

문제를 해결한 뒤 결과만 기억하면 다음 프로젝트에서 같은 고민을 반복하게 된다. 왜 그 구조를 선택했는지, 어떤 접근이 실패했는지, 당시의 제약은 무엇이었는지를 기록하면 경험은 재사용할 수 있는 지식이 된다.

앞으로 이곳에 기록할 것

Dan.log에는 AI와 LLM 애플리케이션을 실제 제품으로 만들며 배운 내용을 기록하려 한다. 에이전트 아키텍처, RAG와 검색, 실시간 AI, 데이터 파이프라인, 백엔드와 인프라뿐 아니라 사용자의 경험을 결정하는 프론트엔드와 운영의 문제도 함께 다룰 것이다.

완성된 결과만 정리하기보다 다음 질문에 답하는 글을 쓰고 싶다.

  • 왜 이 구조를 선택했는가
  • 무엇이 예상대로 동작하지 않았는가
  • 프로덕션에서 어떤 문제가 새롭게 드러났는가
  • 다시 만든다면 무엇을 다르게 할 것인가

지난 9년 동안 내가 배운 개발은 코드를 많이 작성하는 일이 아니었다. 불확실한 문제를 구체적인 제품으로 바꾸고, 실제 환경에서 오래 작동하도록 끊임없이 다듬는 일이었다.

앞으로도 새로운 기술을 빠르게 배우되, 기술 그 자체보다 그것이 사용자에게 어떤 경험을 만드는지 끝까지 살펴보려 한다. 그리고 그 과정에서 얻은 판단과 시행착오를 이곳에 솔직하게 남기려 한다.