기능을 만드는 개발자에서, 프로덕트를 고민하는 엔지니어로 – TainAI Labs 4기 회고

현서·2026년 2월 23일
post-thumbnail

지난 2개월간 TainAI Labs에서 프로덕트 엔지니어로 인턴십을 했다. 짧은 시간이었지만 한 명의 엔지니어로서 성장할 수 있는 기회였고, 앞으로의 커리어에서 충분히 돌아볼 만한 경험이기에 회고로 남겨보려 한다.

프로덕트 엔지니어?

프론트엔드, 백엔드라는 직무는 익숙하지만 프로덕트 엔지니어라는 타이틀은 생소했다. 프로덕트 엔지니어는 단순히 기술 구현에 그치지 않고, 제품의 기획부터 배포·운영까지 전 과정을 이해하며 서비스 성장을 최우선으로 두는 역할이다. 평소 기획과 개발을 병행하며 공부해왔지만, 실사용자를 받고 실제 서비스를 운영해보는 경험은 해본 적이 없었다. 풀스택 개발자로서 꾸준히 역량을 쌓아오던 중, 지원 공고에서 '창업에 관심 있는', '재밌어 보이면 지원하세요!'라는 문구를 보고 지원하지 않을 수 없었다. 기획도 좋아하고 개발도 좋아하는 나에게 딱 맞는 기회였다.


프로젝트 아이데이션 과정

아이데이션 단계에서는 직접 앱을 써보며 유저의 입장에서 만들고 싶은 기능을 고민했다. 대표님과 싱크를 맞추고 디벨롭하는 과정을 거쳐 도출한 첫 번째 아이템이 바로 '커플샷'이었다.

AI 채팅 앱을 사용하는 사람들의 심리는 무엇일까? 다양한 커뮤니티를 살펴본 결과, 유저들은 실제로 AI 캐릭터와 연애를 하고 있다고 느낀다는 인사이트를 얻었다. 그렇다면 사랑하는 상대와 사진을 찍고 싶은 마음도 있지 않을까? 이 지점에서 커플샷 프로젝트가 시작되었다.

기획을 해보고 난 뒤에는 간단하게 Gemini를 활용해서 내가 만든 기획의 세미 프로토타입도 제작해보고, 내부 구성에 대한 논의도 지속적으로 진행한 결과, 커플샷 프로젝트를 시작하게 되었다.

프롬프트 엔지니어링

AI를 활용해서 이미지를 생성하는 프로젝트이기 때문에, 프롬프트 엔지니어링의 구조를 이해하고 원하는 Output을 뽑아낼 수 있는 프롬프트를 작성하는 것이 프론트, 백엔드 구현을 하는 것보다 중요했다.

단순히 AI에게 "이런 그림 그려줘"라고 요청하는 수준이 아니었다. 캐릭터의 시각적 정체성을 유지하면서도 다양한 장면에 자연스럽게 녹아들게 하려면, AI와의 커뮤니케이션 자체를 정교하게 설계해야 했다.

이 과정에서 가장 많이 고민한 것은 일관성과 다양성의 균형이었다. 같은 캐릭터인데 장면이 바뀔 때마다 스타일이 흔들리는 문제, 장면의 분위기가 캐릭터의 본질까지 침범하는 문제 등 예상치 못한 충돌이 계속 발생했다. 예를 들어, 배경이 바다인 장면에서 캐릭터의 머리 색이 푸른 톤으로 변하거나, 밤 장면에서 캐릭터의 눈동자 색이 어두워지는 식이었다. 이를 해결하기 위해 프롬프트 내에 우선순위 체계를 세우고, 캐릭터의 고유 속성(머리색, 눈동자색, 체형 등)을 최상위에, 장면·배경·분위기를 하위에 배치하는 구조를 설계했다. 고정되어야 할 요소와 가변적인 요소를 명확히 분리하는 것이 핵심이었다.

또한 프롬프트의 순서와 강조 방식에 따라 결과물의 품질이 크게 달라진다는 것을 체감했다. 이론이 아니라 수십 번의 실험과 반복을 통해 AI의 행동 패턴을 파악하고, 미세한 표현 하나까지 튜닝해가며 원하는 수준의 결과물에 도달할 수 있었다. 이 경험을 통해 프롬프트 엔지니어링이 단순한 텍스트 작성이 아니라, 구조화·우선순위·조건 분기 등 프로그래밍적 사고가 필요한 시스템 설계에 가깝다는 걸 배웠다.

프로젝트를 통합하다

처음에는 커플 사진 생성으로 시작했던 프로젝트가, 팀원이 기획한 또 다른 이미지 생성 프로젝트와 통합되면서 '러비포토부스'라는 하나의 서비스로 확장되었다. 각각의 프로젝트가 포토부스의 테마가 되었고, 프로젝트의 방향도 단일 기능 개발에서 하나의 완결된 서비스를 만드는 것으로 바뀌었다. 2인 팀으로 포토부스 전체를 설계하고 구현하는, 보다 도전적인 과제가 된 셈이다.

두 프로젝트를 하나로 통합하면서, 단순히 코드를 합치는 것이 아니라 앞으로의 확장성까지 고려한 구조를 설계해야 했다. 이 과정은 크게 두 번의 리팩토링으로 나뉘었다.

1차 리팩토링: 테마 기반 구조로의 전환

처음에는 각 프로젝트가 완전히 독립된 모듈로 동작하고 있었다. 로직도, 화면도, 서버 함수도 각각 따로 존재하는 구조였다.

이를 '테마'라는 상위 개념 아래로 묶으면서 공통 로직을 분리하고, 각 기능을 모듈화한 뒤 레지스트리 패턴으로 관리하는 구조로 전환했다. 새로운 테마가 추가되더라도 기존 코드를 건드리지 않고 모듈만 등록하면 되는 형태를 만드는 것이 목표였다.

2차 리팩토링: 서버 통합에 따른 전면 정리

1차에서 구조를 잡았다면, 2차는 실제로 중복을 걷어내는 작업이었다. 서버 쪽 함수들을 통합하면서 이에 맞춰 클라이언트 코드도 함께 정리했다. 결과 화면, 로딩 화면 등 테마 간 공통으로 쓰이는 컴포넌트들을 하나로 합치고, 생성 관련 로직도 개선했다. 예를 들어 생성 요청 후 화면을 이탈해도 백그라운드에서 처리가 이어지도록 수정하는 등, 구조 통합과 함께 사용자 경험까지 개선하는 방향으로 진행했다.

두 번의 리팩토링을 거치면서 느낀 것은, 리팩토링은 단순히 코드를 깔끔하게 만드는 작업이 아니라는 점이었다. 기존 구조를 분석하고, 공통점과 차이점을 파악하고, 확장 가능한 설계를 그린 뒤에야 비로소 코드를 옮길 수 있었다. 실무에서의 리팩토링이 왜 시간이 걸리고 또 왜 중요한지를 체감한 경험이었다.

구조 위에 테마를 얹다

리팩토링한 구조의 효과는 바로 확인할 수 있었다. 초기 테마들에 이어 '증명사진', '캐릭터 인형 만들기' 등 새로운 테마를 추가로 기획했는데, 나는 그중 인형 테마의 구현을 담당했다. 서버는 건드리지 않고 프론트엔드에 테마 모듈만 등록하는 것으로 확장이 가능했고, 처음 커플샷 하나를 만드는 데 약 2일이 걸렸던 것과 비교하면 리팩토링 이후에는 기획만 있으면 1~2시간 만에 테마 추가가 가능해졌다. "확장 가능한 구조"가 단순한 이상이 아니라 실제 생산성에 직결된다는 것을, 2일에서 2시간이라는 숫자로 체감한 순간이었다.

총 4개의 테마를 갖춘 러비포토부스는, 이 상태로 베타테스트에 들어가게 되었다.


베타테스트를 준비하며

4개의 테마를 갖추고 베타테스트를 앞두고 있었지만, 기능 구현을 마친 것과 실제로 유저에게 내보내는 것 사이에는 생각보다 많은 간극이 있었다. 단순히 '돌아가는 서비스'를 만드는 것과 실제 프로덕션 환경을 준비하는 것은 완전히 다른 일이라는 걸 이 시기에 가장 크게 체감했다.

프로덕션을 위한 준비

베타 환경에 맞는 정책과 기능을 새로 설계해야 했다. 베타 테스터만 접근할 수 있도록 제한하고, 과금 요소는 임시로 비활성화해 무료 생성만 가능하게 했다. 캐릭터 선택 흐름도 유저가 혼란 없이 사용할 수 있도록 2단계 모달 구조로 개선하고, 다국어 번역도 다시 한번 점검했다. 기능이 '동작하는 것'과 유저가 '자연스럽게 쓸 수 있는 것'은 다른 문제라는 걸 이 과정에서 실감했다.

베타 인증, 그리고 레거시와의 공존

준비 과정에서 예상치 못한 벽도 만났다. 베타 테스터만 접근할 수 있도록 인증 로직을 구현하는 과정에서 기존 코드베이스와 충돌이 발생한 것이다.

처음에는 별도의 인증 로직을 새로 만들어 적용했는데, 알고 보니 기존 앱에 이미 유사한 베타 체크 로직이 존재했다. 그대로 가져다 쓰려 했지만 환경 차이로 인해 그것도 쉽지 않았고, 결국 기존 로직의 구조를 따르되 포토부스 환경에 맞게 다시 구현하는 방향으로 정리했다. 팀원과 인증 흐름에 대해 논의하면서 더 가벼운 접근 방식을 제안받기도 했고, 라우트 구조도 함께 조정했다.

돌아보면 기능 자체는 단순한 접근 제한이었지만, 기존 코드베이스를 충분히 파악하지 못한 채 새로운 로직을 만들었다가 롤백하는 과정을 거치면서 "먼저 기존 코드를 충분히 이해하고, 그 위에 쌓아야 한다"는 교훈을 얻었다. 실무에서 레거시 코드와 공존하는 법을 배운 경험이었다.

베타테스트, 그리고 실사용자의 목소리

베타테스트는 대만·일본·태국·한국·중국 등 다양한 언어권에서 모인 수십 명의 테스터를 대상으로 이틀간 진행되었고, 그 기간 동안 수천 장의 이미지가 생성되었다. 전체 만족도는 5점 만점에 약 4점에 가까운 수준이었으며, 과반수 이상이 4점 이상을 주었고 심각한 불만족 응답은 없었다.

테마별로 보면 커플 인생샷이 가장 높은 이용률을 보였고, 인형 만들기도 근소한 차이로 뒤를 이었다. 모든 테마가 고르게 높은 이용률을 기록한 건 긍정적이었지만, 테마 간 품질 편차가 존재한다는 피드백도 있었다. 프롬프트 구조는 동일한 체계를 따르고 있었지만, 테마마다 요구되는 세부 튜닝의 깊이가 달랐던 것이다. 모든 테마에 같은 수준의 프롬프트 최적화를 적용하지 못한 부분은 시간 제약 속에서의 아쉬움으로 남는다.

특히 인상 깊었던 것은 유저들의 피드백이 예상과 다른 지점에서 나왔다는 것이다. 개발하면서 가장 공을 들였던 이미지 생성 품질보다, 정작 유저가 불편해하는 건 캐릭터 선택 흐름이나 이미지 저장 방식 같은 UX 디테일이었다. 실제로 UX 관련 피드백에서 가장 많이 언급된 키워드는 '캐릭터 선택/관리', '이미지 저장', '프롬프트 입력', 'UI/버튼 배치' 순이었다. 스타일 선택 옵션 추가는 전체 개선 요청 중 가장 많은 빈도를 차지했는데, 이건 개발 과정에서 전혀 예상하지 못한 요구사항이었다. 우리는 프롬프트로 스타일을 조절할 수 있다고 생각했지만, 유저 입장에서는 웹툰·실사·애니메이션 등 직관적인 선택지가 필요했던 것이다.

반면 예상 밖의 긍정적 반응도 있었다. 내가 구현한 인형 만들기 테마의 로딩 문구("솜을 채우는 중...")에 대해 "귀여운 진행 문구들이 인상적"이라는 피드백이 여럿 달렸다. 기능적으로는 단순한 로딩 인디케이터였지만, 포토부스라는 콘셉트에 맞는 감성적 디테일이 사용자 경험에 생각보다 큰 영향을 준다는 걸 알게 되었다.

"만드는 사람의 시선"과 "쓰는 사람의 시선"은 정말 다르다는 걸 데이터로 확인한 경험이었다. 그리고 이 피드백들이 다음 단계의 방향을 잡는 데 가장 큰 근거가 되었다.


정식 런칭

베타 피드백을 반영한 개선 작업을 거쳐 러비포토부스는 정식으로 런칭되었다. 앞서 진행했던 서버 리팩토링 덕분에 피드백 기반의 수정 사항들을 빠르게 반영할 수 있었고, 테마 추가 시에도 서버 재배포 없이 프론트엔드만 수정하는 구조가 실제로 효과를 발휘했다.

정식 런칭 이후에는 테마를 더욱 적극적으로 확장했다. 베타 때 4개였던 테마는 최종적으로 11개까지 늘어났는데, 실사 커플샷, 캐릭터 시간여행, 부적 만들기 등 콘셉트의 범위도 점점 넓어졌다. 초기의 커플샷과는 결이 전혀 다른 테마들도 같은 구조 위에서 만들 수 있었다는 점에서, 리팩토링의 효과를 다시 한번 실감했다. 이 과정에서 테마 추가 작업 자체를 더 효율화하는 시도도 했다. 테마 추가에 필요한 가이드를 마크다운 문서로 정리하고, AI 에이전트를 활용해 손쉽게 테마를 생성할 수 있는 워크플로우를 구축한 것이다. 구조화와 자동화를 거듭하면서 테마 확장의 허들이 점점 낮아졌다.

또한 서비스의 네이밍과 방향성도 다듬었다. 단순히 AI가 이미지를 '생성'하는 기능적인 느낌에서, '러비가 사진을 찍어주는 사진관'이라는 감성적 몰입을 유도하는 콘셉트로 전환했다. 기술이 아니라 경험을 전달하는 것, 그것이 프로덕트 엔지니어로서 마지막까지 고민한 지점이었다.

그렇게 러비포토부스는 실제 프로덕트에 반영되었다.

런칭 이후에는 커뮤니티에서 유저들이 자발적으로 포토부스 결과물을 공유하는 모습도 볼 수 있었다. 내가 만든 기능이 유저의 일상 속에서 즐겨지고 있다는 걸 눈으로 확인한 순간이었다.

돌아보며

그동안 만들어왔던 사이드 프로젝트나 해커톤 결과물은 '만드는 것'에서 끝나는 경우가 대부분이었다. 하지만 이번 인턴십에서는 처음으로 진짜 프로덕트를 만들었다. 내가 기획한 기능을 팀과 함께 디벨롭하고, 코드 리뷰를 받고, 실사용자에게 출시하는 전 과정을 경험한 것이다.

기술적으로도 새로운 도전의 연속이었다. 앱 개발은 처음이었고, 서버 구조도 그간 익숙했던 방식과는 달랐다. 처음 보는 코드베이스 위에서 기능을 만들어야 하는 상황이 낯설었지만, 하나씩 파악하고 부딪히며 결국 해낼 수 있었다. 2인이라는 작은 팀이었기에 대표님과의 커뮤니케이션이 곧 의사결정이었고, 기획 의도를 코드로 옮기는 과정에서 서로의 생각을 맞춰가는 법도 배웠다.

2개월간의 경험을 압축하면 이렇다.

프롬프트 엔지니어링은 시스템 설계다. AI에게 원하는 결과를 얻기 위해서는 구조화된 사고와 반복적인 실험이 필요했다. 배경에 캐릭터의 고유 속성이 침범당하는 문제를 우선순위 체계로 해결하면서, 프로그래밍적 사고가 코드 밖에서도 통한다는 걸 배웠다.

확장 가능한 구조는 생산성이다. 리팩토링에 투자한 시간이 이후 테마 확장 속도로 고스란히 돌아왔다. 테마 하나를 만드는 데 2일 걸리던 것이 2시간으로 줄었고, 4개에서 11개로 테마가 늘어나는 과정이 그 증거였다.

만드는 사람과 쓰는 사람의 시선은 다르다. 베타테스트에서 가장 많이 나온 피드백은 이미지 품질이 아니라 캐릭터 선택 흐름과 스타일 옵션이었다. 유저의 목소리가 서비스의 방향을 결정한다는 걸 실제 피드백 데이터로 확인했다.

기존 코드를 이해하는 것이 먼저다. 새로운 로직을 만들기 전에 이미 있는 코드베이스를 충분히 파악해야 한다는 교훈을, 베타 인증 구현에서의 롤백이라는 값비싼 경험으로 배웠다.

2개월이라는 짧은 시간이었지만, 아이디어가 기획이 되고, 코드가 되고, 서비스가 되어 유저의 손에 닿는 한 사이클을 온전히 경험했다. 이 과정에서 '개발자로서 일한다'는 것이 어떤 의미인지를 처음으로 체감할 수 있었다.

인턴십 이전의 나는 기술을 익히고 기능을 구현하는 데에 집중하는 개발자였다. 이번 인턴십 이후 달라진 게 하나 있다면, 이제는 코드를 쓰기 전에 "이 기능은 유저가 어떤 맥락에서 쓰게 될까"를 먼저 떠올린다는 것이다. 로딩 문구 하나에도 유저가 반응한다는 걸 직접 확인한 뒤로는, 기술과 경험 사이의 접점을 고민하는 일이 자연스러워졌다. 기술과 제품 사이에서 사고할 수 있는 엔지니어, 이번 인턴십이 그 방향의 출발점이었다.

profile
LLM부터 풀스택까지, 만들면서 기록합니다

1개의 댓글

comment-user-thumbnail
2026년 2월 25일

요즘 AI 서비스 개발 중인데 인사이트 있는 글 잘 읽었습니다! 앞으로도 좋은 글 기대하겠습니다 ㅎㅎ

답글 달기