AI로 사내 마니또 서비스를 만들었어요! (2편 DEV)

AI로 사내 마니또 서비스를 만들었어요! (2편 DEV)

Development

이창민, 안지윤

사내 첫 AI 스터디에서 ‘사내 칭찬 마니또’ 아이디어가 나왔을 때, 화면과 기능을 구현해야 하는 저희 파트의 머릿속은 이미 전체적인 시스템 아키텍처와 로직을 그리며 바쁘게 돌아가기 시작했어요. 저희가 세운 기술적 목표는 크게 두 가지였습니다.

  1. AI를 단순한 ‘코드 자판기’가 아닌, 시스템 구조를 함께 고민하는 ‘스파링 파트너’로 활용해 보자!

  2. 기획/디자인이 상상한 아이디어를 성능 저하나 버그 없이 완벽하게 구현해 내자!

마니또라는 친근한 게임으로 조직에 따뜻한 문화를 만드는 기획도 매력적이었지만, 개발자의 시선에서는 더 흥미로운 도전이 기다리고 있었어요. 실시간 데이터 동기화, 복잡한 라우팅과 상태 관리, 그리고 동전으로 복권을 긁는 듯한 인터랙티브 Canvas UI까지. 단순한 이벤트 페이지를 넘어 다양한 기술적 과제를 해결하며 완성도 높은 서비스를 구현하는 것이 이번 프로젝트의 핵심 목표였습니다.

그 과정에서 가장 중요했던 것은 코드를 작성하는 것이 아니라 구조를 설계하는 일이었습니다. 이번 글에서는 단순히 에러를 해결하는 것을 넘어, 서비스가 확장되어도 흔들리지 않는 아키텍처를 AI와 함께 고민하고 검증하며 완성해 나간 과정을 소개하려고 합니다.

1. 변수명 하나에도 논리를 담다: 이중 부정의 늪에서 탈출하기 😵‍💫

개발 초반, 쪽지함 목록의 정렬 기준을 세울 때의 일입니다. '안 읽은 쪽지를 최상단으로 올린다'는 기획은 단순해 보였지만, 실제 데이터베이스에는 수많은 경우의 수가 존재했어요. 예전에 만들어둔 테스트 데이터에는 '읽음 여부' 자체가 기록되지 않은 빈 값(Null/Undefined)도 섞여 있었거든요.

처음엔 "읽은 상태가 아닌 것"이라는 이중 부정을 써서 로직을 짰더니, 코드가 길어질수록 개발자인 저희조차 헷갈리는 복잡한 스파게티 코드가 되어버렸습니다. 이때 저희는 AI에게 정답을 묻는 대신, 우리가 가진 데이터의 모든 예외 상황을 나열하고 "이를 가장 명확하게 분류할 수 있는 코딩 컨벤션(기준)을 제안해 줘"라고 요청했습니다.

AI와 시뮬레이션한 끝에 도달한 결론은, 조건문을 억지로 엮는 것이 아니라 isRead(읽었는가?)라는 직관적이고 긍정적인 형태의 단일 기준을 세우는 것이었어요. 복잡했던 조건 로직이 마치 자연어처럼 술술 읽히는 클린 코드로 탈바꿈했고, 예기치 못한 빈 값이 들어와도 화면이 멈추지 않는 안전한 방어 로직을 확립할 수 있었습니다.


2. 복권 긁기 UI: 성능과 정확도의 황금 밸런스 찾기 🪙

이번 서비스의 핵심 재미 요소 중 하나는 화면을 문질러서 내 마니띠를 확인하는 기능입니다. 처음엔 단순히 사용자의 손가락 궤적을 따라 화면을 투명하게 지우면 끝날 줄 알았어요. 하지만 막상 기기에서 테스트해 보니 두 가지 큰 난관이 있었습니다.

첫째, 사용자가 손가락을 빠르게 움직이면 화면이 점선처럼 띄엄띄엄 지워지는 끊김 현상이 발생했습니다. 둘째, "전체 면적 중 얼마나 지워야 다 긁었다고 판별할 것인가?"를 계산해야 했죠. 저희는 AI에게 "캔버스 기능을 구현할 때, 기기의 메모리 과부하를 막으면서도 가장 부드러운 사용자 경험을 제공할 수 있는 방법들을 비교 분석해 줘"라고 질문했습니다.

AI는 저희의 고민을 바탕으로 흥미로운 그래픽 처리 기법을 제시했어요. 점선으로 지워지는 문제는 점과 점 사이의 빈 공간을 수학적으로 계산해 촘촘하게 메워주는 보간법(Interpolation)을 적용해, 아무리 빠르게 문질러도 부드럽게 지워지도록 해결했습니다.

가장 치열하게 토론했던 부분은 '지워진 픽셀 비율 계산'이었습니다. 화면의 수만 개 픽셀을 매 프레임마다 검사하면 정확도는 100%겠지만, 스마트폰에 엄청난 연산 부하가 걸려 앱이 느려질 위험이 컸죠. 저희는 AI와 효율성을 시뮬레이션하며 타협점을 찾았습니다. 전체를 다 검사하는 대신 일정 간격의 픽셀만 추출하는 샘플링 기법을 도입하고, 검사 주기도 0.25초 단위로 제한했습니다. 결과적으로 성능 저하(프레임 드랍) 없이, 사용자가 '이 정도면 다 긁었다!'라고 체감하는 60%의 마지노선을 완벽하게 잡아낼 수 있었습니다.

3. 최악의 시나리오를 대비한 데이터 설계: 단일 진실 공급원 😣

서비스의 몰입도를 높이기 위해 '쪽지를 12번, 25번 보냈을 때 마니또의 정체를 맞히는 깜짝 히든 이벤트'를 추가할 때였습니다.
처음에는 직관적으로 "사용자의 DB에 '보낸 쪽지 개수'라는 항목을 만들어서 쪽지를 보낼 때마다 숫자를 1씩 증가시키자"라고 설계했습니다.

하지만 본격적인 개발에 들어가기 전, AI에게 "이 구조로 실제 런칭을 했을 때 발생할 수 있는 데이터 무결성 결함 시나리오를 예측해 줘"라고 질문을 던졌어요. AI는 통신이 불안정한 환경(예: 출근길 지하철)에서 사용자가 전송 버튼을 연타했을 때의 위험성을 짚어주었습니다. 실제 쪽지는 1개만 저장됐는데 카운트는 3개가 올라가는 등, 데이터의 앞뒤가 맞지 않는 '데이터 꼬임(상태 불일치)' 현상이 영구적으로 발생할 수 있다는 것이었죠.

이 분석을 바탕으로 저희는 숫자를 클라이언트에서 따로 기록하는 방식을 과감히 폐기했습니다. 대신 "필요한 시점에 파이어베이스를 조회해, 실제 전송 완료된 쪽지의 개수만 정확히 실시간으로 세어오는 방식"으로 구조를 완전히 바꿨습니다. '단일 진실 공급원' 원칙을 지킴으로써, 예측 가능한 데이터 오류를 사전에 완벽히 차단할 수 있었습니다.


4. 렌더링 무한 루프의 늪, 프레임워크의 원리를 파고들어 탈출하다 🧐

가장 큰 난관은 히든 이벤트 조건을 달성한 후 화면을 이동할 때 팝업을 띄우는 라우팅(Routing) 과정이었어요. 이동할 페이지에 '팝업을 띄워라'라는 상태 꼬리표를 넘겨주고, 팝업이 뜨고 나면 그 꼬리표를 지우도록 설계했죠. 그런데 콘솔 창에 "화면을 그리고 있는 와중에 상태를 변경하여 렌더링을 연쇄적으로 발생시키지 마라"라는 치명적인 에러가 발생했습니다.

단순히 "이 에러 어떻게 고쳐?"라고 물었다면 AI는 임시방편의 땜질용 코드를 줬을지도 모릅니다. 하지만 저희는 "현재 리액트의 렌더링 생명주기와 상태 변화의 흐름을 단계별로 분석해 줘"라고 요청했습니다.

분석 결과, 저희가 짠 코드는 리액트의 상태 관리 로직과 충돌하여 불필요한 렌더링 과부하를 일으키고 있었습니다. 저희는 프레임워크를 억지로 통제하는 대신, 인터넷 브라우저가 기본적으로 제공하는 고유의 기능(History API)을 활용해 리액트 엔진 몰래 꼬리표만 슬쩍 지워내는 우아한 우회로를 선택했습니다. 겉핥기식 해결이 아닌 근본적인 동작 원리를 파고든 덕분에, 에러 해결은 물론 화면 전환 속도까지 끌어올릴 수 있었어요.


마치며… 💻

이번 프로젝트를 통해 개발과 퍼블리싱을 담당하며 가장 크게 느낀 점은, AI는 '어떤 질문을 던지느냐'에 따라 그 가치가 무한히 달라진다는 것이었어요.

단순히 "코드를 작성해 줘."가 아니라, "이 방식과 저 방식 중 어떤 구조가 유지보수에 더 유리할까?", "우리가 놓친 예외 상황은 없을까?", "더 단순하고 읽기 쉬운 설계는 없을까?"를 끊임없이 질문하고 검증하는 것이죠. 그 과정에서 AI는 함께 설계를 고민하고 아이디어를 검증해 주는 시니어 페어 프로그래머와 같은 존재가 되어주었습니다.

기획과 디자인팀이 그려준 멋진 청사진을 AI와 함께 수없이 시뮬레이션하고 다듬으며, 안정적인 실제 서비스로 완성해 나가는 과정은 무척 즐겁고 의미 있는 경험이었습니다. 무엇보다 서비스를 공개한 뒤 임직원분들이 즐겁게 참여하고 서로 칭찬하는 모습을 보며 기술로 좋은 문화를 만드는 일의 보람을 다시 한번 느낄 수 있었습니다. 🌷