Skip to content
뒤로가기

AI Native 환경에서 0→1을 만든 2개월의 기록

게시된 날짜:  at 
TainAI 인턴 경험기 인트로 이미지

회사의 요청에 따라 보안 및 정보 보호를 위해 민감한 내용은 일부 블러 처리하거나 생략하여 신중히 작성하였습니다. :)

들어가며

이 글은 AI 채팅 서비스 “러비더비”를 운영하는 TainAI에서 2개월간 인턴으로 일하며 경험한 내용을 정리한 글이다. 감정별 캐릭터 이미지 해금 시스템, 비주얼 노벨 모드 도입, 그리고 목표-보상-엔딩 구조로의 확장까지 세 개의 프로젝트를 직접 기획하고 설계하며 실제 유저들의 반응을 확인했다.

단순히 기능을 구현하는 역할이 아니라, 아이디어 단계에서 시작해 베타 테스트와 피드백 반영까지 이어지는 0→1 전 과정을 경험했다는 점이 이번 인턴의 가장 큰 성과였다. 특히 글로벌 베타 유저들을 대상으로 실험하며, 완성도보다 속도와 시장 검증이 더 중요할 수 있다는 실전 비즈니스 감각 또한 몸으로 배웠다.

따라서 이 글은 그 2개월 동안의 시도와 고민, 시행착오를 정리한 나만의 오답노트이자, AI Native 환경에서 프로덕트를 제작하며 배운 점을 공유하고 싶어 남긴다.


TainAI에서 얻어가고 싶었던 점

인턴을 시작하기 전, 스스로에게 하나의 질문을 던졌다.

인턴 기간 동안 나는 무엇을 얻어가면 좋을까?

TainAI는 AI 채팅 서비스를 운영하며, 채용 공고에서부터 AI Native 환경을 지향하는 회사였다. 나에게 AI Native 환경이란 단순히 AI 도구를 활용하는 것을 넘어, AI를 전제로 프로덕트를 설계하고 실험하는 구조를 직접 경험할 수 있다고 생각했다.

또한 글로벌 트래픽을 대상으로 실제 유저들의 반응을 확인할 수 있다는 점, 그리고 1인 1프로젝트 구조로 하나의 기능을 처음부터 끝까지 책임질 수 있다는 점 역시 큰 매력이었다.

따라서 나의 목표는 확고했다.

0→1을 온전히 경험하는 것

아이디어를 기획하고, 정책을 설계하고, 구현하고, 유저 반응을 확인한 뒤 다시 개선하는 전 과정을 직접 겪어보고 싶었다. 결과적으로 그 목표는 충분히 달성했다고 생각한다.


AI Native 환경에서 0→1을 만든 세 개의 프로젝트

앞서 말했듯, 인턴 기간 동안 총 세 개의 프로젝트를 진행했다.

이 세 프로젝트는 개별적으로 분리되지 않았고, 유저 피드백을 반영하며 유기적으로 연결된 마치 살아있는 프로덕트와 같았다. 프로젝트의 궁극적인 목적은 단순 기능 추가가 아니라, 기존 러비더비 유저를 넘어 미연시(비주얼 노벨) 유저와 라이트 유저를 동시에 확보하기 위한 실험적인 프로젝트였다.

무엇보다 내가 맡았던 영역은 회사의 핵심 서비스인 채팅 경험에 직접적으로 연결된 부분이었다. 그만큼 책임감이 컸고, 반드시 의미 있는 결과 만들어내고 싶다는 마음으로 임했다.


1. 감정별 캐릭터 이미지 해금 시스템

초기 아이데이션
초기 아이데이션

첫 번째 프로젝트는 캐릭터의 감정에 따라 프로필 이미지가 변화하는 해금 시스템이었다.

대표님과의 1:1 싱크 과정에서, 현재 러비더비는 캐릭터의 프로필 이미지가 고정되어 있어 감정 표현이 제한적이라는 점을 확인했다. 유저 입장에서는 대화 내용이 달라지더라도 캐릭터의 프로필이 변하지 않아 시각적인 자극이 부족했고, 이는 몰입도를 떨어뜨릴 수 있었다.

이 문제를 해결하기 위해 감정 기반 이미지 해금 시스템을 도입하게 되었다.

핵심은 단순 키워드 매칭이 아니라, 실제 채팅 맥락을 기반으로 감정을 판단하고 그에 맞는 이미지를 해금하는 구조가 필요했다. 감정은 통상적으로 사용되는 6가지 감정으로 제한했고, 이를 판단할 AI 프롬프트에는 관계 단계나 호감도 수치는 의도적으로 제외했다. 감정 해금의 기준은 관계나 호감도가 아니라, 캐릭터의 응답에서 드러난 감정 표현이었기 때문이다.

또한 감정 이미지가 지나치게 쉽게 해금되지 않도록, 일정 수준 이상의 신뢰도를 충족할 때만 해금되도록 설계했다. 동시에 하나의 메시지에서 여러 감정 이미지가 동시에 해금되지 않도록 반드시 하나의 감정만 반환하도록 제약을 두었다.

이렇게 설정한 이유는 채팅에 게임적인 요소를 더해, 유저가 자신이 좋아하는 캐릭터의 새로운 감정 이미지를 해금하며 보상을 받는 경험을 제공하고 싶었기 때문이다.

감정별 캐릭터 이미지 해금 결과물
감정별 캐릭터 이미지 해금 결과물
감정 해금 베타 테스트 공지
감정 해금 베타 테스트 공지

그렇게 베타 테스트를 진행한 결과, 유저들의 반응은 예상보다 흥미로웠다.

초기에는 UI 변화 폭이 크면 유저들이 어색함을 느껴 부정적인 피드백이 많을까 우려했었다. 하지만 실제 피드백을 살펴보니, 오히려 유저들은 캐릭터의 이미지를 더 크게 보고 싶어했고, 감정 변화가 시각적으로 드러나는 점을 긍정적으로 받아들였다. 감정에 맞게 캐릭터의 이미지가 변하니 몰입감이 더 높아졌다는 반응 또한 많았다.

이 피드백을 바탕으로 프로젝트의 방향을 바꿔 캐릭터 이미지를 더 크게 확인할 수 있도록 다음 스텝을 결정했다.


2. 비주얼 노벨 모드 도입

두 번째 프로젝트는 “캐릭터 이미지를 더 크게 보고 싶다.”는 1차 피드백을 반영해, 기존 채팅방 UI를 비주얼 노벨 모드로 확장하는 작업이었다.

비주얼 노벨 모드에서 가장 먼저 마주한 기술적 과제는 캐릭터의 대사(dialogue)와 속마음(thought)을 안정적으로 분리하는 것이었다.

LLM의 출력은 본질적으로 자유 형식이다. 이를 그대로 렌더링하면 대사와 속마음이 동일한 스타일로 출력되어 몰입감이 깨질 수 있었다.

이를 해결하기 위해 대사/속마음 분리 함수를 사용해 정규식 기반의 분리 방식을 적용했다.

*...*로 감싸진 텍스트를 속마음으로 간주하고, 나머지를 대사로 분류하는 방식이다. 이 구조는 의도적으로 단순하게 설계했다. 그 이유는 두 가지였다.

첫째, 비주얼 노벨 모드는 정식이 아닌 베타 기능이었다.

우선순위는 완성도 높은 파서를 만드는 것이 아니라, 빠르게 시장 반응을 검증하는 것이었다. 더 복잡한 파싱 로직을 도입할 수 있었지만, MVP 단계에서 이는 오버엔지니어링에 가까운 선택이라고 판단했다.

둘째, 기존 채팅 파싱 로직은 서비스의 핵심 중의 핵심이었다.

오랜 기간 안정적으로 사용되어 온 구조를 수정하는 것은 전체 시스템에 영향을 줄 수 있었다. 실험 기능을 위해 코어 로직을 변경하는 것은 리스크가 크다고 보았다.

따라서 기존 파싱 로직은 유지한 채, 비주얼 노벨 모드에 필요한 최소한의 분리 로직만 별도로 추가했다.

완벽한 구조를 만드는 대신, 빠르게 검증 가능한 형태를 만드는 것이 더 적절하다고 보았다. 그 판단 아래 다음과 같은 원칙을 적용했다.

적용한 원칙

  • 구현 복잡도를 최소화한다.
  • 기존 시스템을 수정하지 않는다.
  • 파싱 실패 시 안전하게 fallback 처리한다.

물론 이 방식에는 한계도 존재했다. LLM의 출력 형식을 엄격하게 강제한 구조는 아니었기 때문에, 프롬프트 예시에 일정 부분 의존하고 있었다. 또한 복잡한 텍스트 패턴이나 예상치 못한 형식이 등장할 경우 완벽하게 대응하지는 못한다는 점도 인지하고 있었다.

그럼에도 당시의 목표는 모든 예외를 처리하는 완벽한 구조를 만드는 것이 아니라, 빠르게 실험하고 검증 가능한 형태를 만드는 것이었다. 그 결과, 다시 진행한 베타 테스트에서 대다수의 유저들이 만족하며 5점 만점의 4점 이상을 기록하며 의미 있는 반응을 확인할 수 있었다.

대사(dialogue) 대화상자 예시
대사(dialogue) 대화상자 예시
속마음(thought) 대화상자 예시
속마음(thought) 대화상자 예시
비주얼 노벨 모드 베타 테스트 공지
비주얼 노벨 모드 베타 테스트 공지

3. 목표-보상-엔딩 루프 구조로의 확장

비주얼 노벨 모드를 도입한 이후 한 가지 근본적인 질문이 생겼다.

이 모드는 누구를 위한 것인가?

겉으로는 새로운 UI와 더 크게 표현된 캐릭터 이미지를 제공했지만, 구조적으로는 여전히 기존 채팅 경험을 크게 벗어나지 못하고 있었다. 결과적으로 기존 헤비 유저에게는 충분한 차별점이 되지 못했고, 라이트 유저에게는 여전히 높은 진입 장벽이 남아 있었다.

결국 이 구조는 미연시에 익숙한 유저와 라이트 유저 모두에게 충분히 매혹적이지 못했다. 엔딩 목표를 기대하는 유저에게는 구조가 부족했고, 처음 접하는 유저에게는 방향이 보이지 않았다. 그 결과 “무엇을 해야 하는지 모르는 상태”에서 이탈할 가능성이 높았다.

다시 한 번 대표님과의 1:1 싱크를 통해 방향을 정리했다.

비주얼 노벨 모드는 기존 채팅방의 기능을 확장하는 모드가 아니라,

엔딩이 존재하는 하나의 “게임”이어야 한다는 결론에 도달했다.

AI Native 환경이라면, 유저가 처음부터 거대한 서사를 설계하지 않아도 된다. 대신 시스템이 대목표(엔딩 목표)를 제시하고, 그 아래 중목표(챕터 미션)와 소목표(퀘스트)를 생성하며 자연스럽게 플레이를 이끌어야 한다. 유저는 “무엇을 해야 할지”를 고민하는 대신, 제시된 목표 안에서 선택을 이어가며 관계를 발전시킬 수 있어야 한다.

더불어 단순히 목표를 자동으로 생성하는 것만으로는 충분하지 않았다. 목표가 그럴듯한 문장에 그쳐서는 안 되었고, 유저가 실제로 재미를 느끼며 서비스를 계속 이용하고 싶다는 생각이 들어야 했다.

따라서 프로젝트의 방향을 목표-보상-엔딩 루프를 중심으로 재설계하는 쪽으로 전환했다.

이 문제를 구조적으로 풀기 위해 RPG 게임을 기준 모델로 삼았다.

RPG 게임 시스템

  • 대목표 → 엔딩 목표 → 마왕을 물리친다.
  • 중목표 → 챕터 미션 → 마왕을 상대하기 위해 충분히 레벨업하고 전직한다.
  • 소목표 → 퀘스트 → 레벨업을 위해 몬스터를 처치한다.

이 구조의 핵심은 목표가 단계적으로 연결되어 있다는 점이다. 유저는 작은 성취를 반복하며 점진적으로 큰 목표에 가까워진다.

이를 우리 서비스에 적용하면, 채팅이 단순히 대화를 주고받는 경험을 넘어 목표를 향해 진행되는 플레이 루프가 된다. 유저는 채팅을 통해 퀘스트를 수행하고, 챕터 미션을 달성하며, 궁극적으로는 하나의 엔딩에 도달하게 된다.

이를 구현하기 위해 목표 생성 과정을 세 단계로 분리했다.

생성된 에이전트

  1. 엔딩 목표 생성 에이전트
  2. 챕터 미션 분해 에이전트
  3. 퀘스트 구체화 에이전트

각 에이전트는 이전 단계의 출력을 다음 단계의 입력으로 사용하도록 설계해, 목표 간 인과관계를 유지했다. 그 결과 목표는 서로 단절된 문장이 아니라, 단계적으로 이어지는 구조가 되었다. 퀘스트는 특정 챕터 미션을 달성하기 위한 행동으로 제시되고, 여러 챕터 미션이 축적되면서 최종적으로 엔딩 목표에 도달한다.

구현을 진행하는 과정에서 AI Native 환경에 맞춰 Claude Code의 도움을 적극적으로 활용했다. 프롬프트 초안을 빠르게 생성해 주는 점은 분명 강점이었지만, 어떤 제약을 두고 어떤 구조를 강제할지는 결국 설계자의 몫이었다. 내가 구조를 충분히 이해하지 못하면, AI 역시 의도한 방향으로 활용할 수 없다는 사실을 체감했다.

잠시 분위기를 환기하고자, 아이언맨 영화를 비유로 들자면, 우리에게 자비스가 있다고 해서 곧바로 아이언맨 슈트를 만들 수 없다. 토니 스타크처럼 물리학과 기계 공학을 이해하고 있어야 자비스가 제대로 보조할 수 있듯이 개발자에게 주어진 AI도 역시 마찬가지라는 생각이 든다.

그래서 프롬프트 설계를 보다 체계적으로 이해하기 위해 다양한 레퍼런스를 참고했다. 단순히 문장을 잘 쓰는 것이 아니라, 제약 조건과 판단 구조를 어떻게 설계해야 하는지에 집중했다.

참고한 레퍼런스

참고한 레퍼런스의 공통적인 부분을 요약하자면 다음과 같다.

요약

  1. 명확하고 구체적인 지시가 가장 중요하다 — 원하는 작업이 무엇인지, 결과물 형태까지 명확하게 적어야 좋은 결과가 나온다.
  2. 맥락과 배경 정보를 충분히 제공해야 한다 — 단순한 질문보다, 맥락(Context)과 배경/역할 정보가 포함된 프롬프트가 결과 품질을 높인다.
  3. 예시(examples) 또는 출력 구조 지정이 효과적이다 — JSON, 불릿, 특정 필드 등 형식을 지정하면 구조화된 결과를 얻기 쉬워진다.
  4. 테스트 → 반복 → 개선이 필수적이다 — 처음 작성한 프롬프트는 완벽하지 않다. 여러 번 시도하며 반복적으로 수정해야 원하는 결과에 가까워진다.
  5. 간단하지만 핵심 요소만 유지하되 과설계는 피하라 — 불필요하게 길거나 복잡한 프롬프트는 오히려 해석을 혼란스럽게 할 수 있다.

결과적으로 구현된 구조는 의도한 플레이 경험을 만들어냈고, 직접 사용해보았을 때도 긍정적인 체감을 얻을 수 있었다.

엔딩 목표 UI
엔딩 목표 UI
퀘스트 대시보드 UI
퀘스트 대시보드 UI
대표님의 다음 액션
대표님의 다음 액션

완벽하지 않았기에 더 많이 배웠다

완성도보다 빠른 검증

이번 인턴을 통해 가장 크게 배운 점은, 완성도 그 자체보다 빠른 검증과 시장 반응이 더 중요할 수 있다는 실전 비즈니스 감각이었다.

예전에 항공 우주 산업의 두 축인 스페이스X와 보잉의 차이에 대한 이야기를 들은 적이 있다. 스페이스X는 완벽한 로켓을 한 번에 선보이기보다, 빠르게 발사하고 실패하고 개선하는 방식을 택했다. 반면 완벽을 추구하며 출시를 미루는 전략을 택한 보잉은 오히려 기회를 놓치게 만들기도 했다.

이 관점은 프로덕트 개발에도 그대로 적용된다는 것을 체감했다.

아무리 내부에서 공을 들여 설계하고 개발한 기능이라도, 실제 유저 니즈를 충족시키지 못한다면 그 기회비용은 매우 크다. 내부 평가에서 “괜찮은데?” 수준의 판단은 시장에서 통하지 않을 수 있었다. 결국 답은 유저에게 있었다.

특히 AI 코딩 에이전트가 보편화된 지금은 상황이 더 달라졌다고 느꼈다. 과거에는 기능 하나를 구현하는 데도 많은 시간과 인력이 필요했다. 그래서 “한 번에 잘 만들어야 한다”는 압박이 컸다. 하지만 이제는 AI의 도움을 받아 소규모 인력으로도 빠르게 프로토타입을 만들고, 실험하고, 개선할 수 있는 환경이 되었다.

이 시대에 완성도에 과도하게 집착하는 것은 오히려 기회를 늦추는 선택일 수 있다. 빠르게 아웃풋을 만들고, 실제 유저 반응을 확인하며 방향을 조정하는 것이 더 합리적인 전략일지도 모른다.

완벽함은 목표가 아니라 과정 속에서 점진적으로 다듬어지는 결과물이라는 생각을 하게 되었다.


실험은 과감하게, 구조는 신중하게

또 하나 배운 점은, 아이디어는 과감하게 실험하되 기존 구조는 함부로 흔들어서는 안 된다는 것이다.

겉으로 보기에는 획기적이고 잘 될 것처럼 보이는 아이디어도, 기존 유저 경험을 해칠 수 있다. 특히 B2C 서비스에서는 작은 변화 하나가 사용자 이탈로 직결될 수 있었다. 실제로 몇 개월 전 카카오톡이 대규모 UI 업데이트를 진행하면서 “왜 이렇게 바뀌었느냐”는 반응이 나오는 것을 보면, 유저가 익숙해진 경험을 바꾸는 일이 얼마나 민감한지 알 수 있다.

결국 실험의 속도와 서비스의 안정성 사이에서 균형을 잡는 것이 중요했다. 새로운 시도를 하더라도, 기존 유저가 쌓아온 경험을 충분히 존중해야 했다.


비용과 성능은 기능만큼 중요하다

기술적인 측면에서도 배운 점이 많았다.

AI 기반 서비스를 운영하면서 API 호출 비용과 Firebase 쿼리 비용은 무시할 수 없는 요소였다. 단순히 “동작한다”에서 끝나는 것이 아니라, 얼마나 효율적으로 동작하는지, 그리고 장기적으로 확장 가능한 구조인지까지 고민해야 했다.

특히 감정 기반 이미지 해금 기능을 구현하면서 데이터 모델링에 대한 시야가 크게 넓어졌다.

초기 설계에서는 감정 매핑, 해금 통계, 분석 결과 등을 챗봇 정보 문서와 대화 스레드 문서에 직접 추가하는 구조를 고려했다. 이렇게 하면 한 번의 조회로 대부분의 정보를 가져올 수 있어 구현은 단순해지고, 클라이언트에서도 접근이 편리하다는 장점이 있었다.

그러나 코드 리뷰 과정에서 중요한 피드백을 받았다.

챗봇과 스레드 문서에 직접 업데이트하지 말고, 서브컬렉션으로 분리하는 것이 좋겠다. 문서 사이즈가 커질 수 있다.

이 피드백은 단순한 구현 스타일의 문제가 아니었다. Firestore는 문서 크기에 제한이 있고, 상위 도큐먼트에 필드를 계속 추가할 경우 장기적으로 확장성과 유지보수 측면에서 부담이 될 수 있다. 특히 통계나 해금 이력처럼 점점 누적되는 데이터는 상위 구조를 비대하게 만들 가능성이 있었다.

이에 따라 데이터 구조를 다음과 같이 재정의했다.

재정의한 데이터 구조

  • 감정별 이미지 정보는 별도의 하위 컬렉션으로 분리
  • 메시지 단위 감정 분석 결과는 각 메시지 문서에 저장
  • 통계 및 재계산과 관련된 필드는 MVP 단계에서 제외
  • 상위 도큐먼트에는 최소한의 활성화 정보만 유지

이 과정을 통해 한 가지를 분명히 깨달았다.

데이터 구조는 기능 구현이 끝난 뒤에 정리하는 문제가 아니라, 기능과 동시에 설계되어야 한다는 점이다.

또한 통계 필드와 같은 확장 요소는 당장 필요하지 않다면 과감히 제외하는 것이 맞다고 판단했다. 미리 모든 가능성을 반영하는 것은 오히려 복잡도와 비용을 높일 수 있기 때문이다. MVP 단계에서는 지금 필요한 최소한의 구조만 남기는 것이 더 합리적인 선택이었다.


클라이언트-서버 역할 분리

감정 분석 결과를 메시지에 저장하는 방식 역시 코드 리뷰를 통해 한 차례 개선되었다.

초기 구현에서는 클라이언트에서 감정 조건을 다시 검사하고, 그에 따라 상태를 업데이트하는 구조였다. 그러나 리뷰 과정에서 역할을 보다 명확히 나누자는 제안을 받았다. 감정 판단과 조건 필터링은 서버에서 처리하고, 클라이언트는 그 결과를 그대로 렌더링하는 구조가 더 적절하다는 방향이었다.

이에 따라 서버에서 confidence 기준을 먼저 적용해 필요한 경우에만 감정 분석 결과를 저장하도록 수정했다. 클라이언트는 별도의 재검증 없이, 전달받은 데이터를 기반으로 UI를 그리는 역할에 집중하도록 구조를 단순화했다.

그 결과 불필요한 상태 업데이트가 줄어들었고, 클라이언트 리렌더링 횟수도 감소했다. 또한 메시지 단위로 감정 정보를 함께 저장함으로써, 이후 설정이 변경되더라도 당시의 감정 상태를 스냅샷처럼 보존할 수 있게 되었다. 이를 통해 성능 측면뿐 아니라 맥락 유지 측면에서도 더 합리적인 구조를 설계할 수 있었다.


다음 단계로 가기 위해

인턴 마무리 전, 대표님이 해주신 조언을 통해 한 가지 방향은 분명해졌다.

AI는 더 이상 도구가 아니라, 성장을 가속시키는 레버리지라는 점이다. 중요한 것은 AI를 사용하느냐가 아니라, 어떻게 전략적으로 활용하는냐였다.

이번 인턴 경험을 바탕으로, 나는 다음과 같은 기준으로 다음 단계를 준비하고자 한다.

첫째, AI를 보조 수단이 아니라 레버리지로 활용한다.

단순히 코드를 빠르게 작성하는 수준이 아니라, 설계 → 실험 → 검증 사이클을 압축하는 데 AI를 활용할 것이다. 내가 혼자라면 몇 달이 걸릴 작업을, AI와 함께라면 몇 주 혹은 며칠 단위로 줄일 수 있는 사고 방식과 작업 방식을 훈련하고자 한다.

둘째, 실전 프로젝트를 통해 압축 성장한다.

이론이나 강의가 아니라, 실제 유저와 마주하는 프로젝트를 꾸준히 쌓아갈 생각이다. 프로젝트 수가 곧 실험 횟수이고, 실험 횟수가 곧 학습 속도로 이어진다는 것을 이번 인턴을 통해 다시 한 번 체감했다. 예상치 못한 엣지 케이스와 성능 이슈, 비용 문제는 결국 실전에서만 배울 수 있다.

셋째, 트랙레코드를 남긴다.

“AI를 사용해봤다”는 경험이 아니라, “AI를 활용해 실제 결과를 만들어냈다”는 기록을 남기고 싶다. 회사가 평가하는 것은 이제는 가능성이 아니라 검증된 경험이라는 점을 이번 경험을 통해 배웠다.

넷째, 작더라도 직접 수익을 만들어보는 실험을 해보고 싶다.

AI × 광고 수익 모델을 소규모로라도 실험해보고, 실제 트래픽과 데이터를 기반으로 개선해보는 경험을 쌓고 싶다. AI를 활용해 실제 수익을 만들어본 경험은 단순 개발을 넘어 비즈니스 감각을 증명하는 사례가 될 것이라 생각한다.


이 2개월은 나에게 어떤 개발자가 되고 싶은지에 대한 기준을 남겼다.

빠르게 시도하고, 빠르게 실패하고, 빠르게 개선하며 빠르게 축적하는 사람.

AI Native 환경에서 개발자로 살아남기 위해, 이제는 이 기준을 바탕으로 다음 단계를 향해 나아가리라 다짐하며 글을 마친다.


수정 제안하기


다음 게시글
아니요, React Context는 너무 많은 렌더링을 유발하지 않습니다