Algocare: Personalized Nutrition Supplement Dispenser

Multi-select
feature
Parent item
Sub-item

Overview

notion image
notion image

About Company

  • 사용자의 건강정보를 통한 개인별 맞춤 영양제를 제공하는 헬스케어 스타트업
    • 맞춤 기본용량 계산 : 모바일앱을 통한 문진 / 건강검진 이력, 복용약물 내역
    • 당일 추가 맞춤 : 당일 몸상태 선택, 전날 수면 리포트
  • CES 4년 연속 혁신상 수상
  • Series A 150억 투자

Responsibilities

  • 프론트엔드 개발: React, Next.js, React Native 활용
    • 메인 프로덕트 초기 개발부터 전담
  • 소프트웨어 아키텍처 설계 및 테크 리딩 (voluntary):
    • 프론트엔드 전 프로덕트의 코드 품질 관리
    • 비정기적 테크 세션 운영으로 챕터 내 기술 공유 및 개선
    • 대규모 태스크 사전 설계 및 구조적 방향성 제안
    • 서드파티 솔루션 도입 시 적합성 검토, 구현 방안 설계

Used My Skill

notion image
 

What I did

초기부터 맡아서 블라블라

개발환경 개선

notion image
제 입사 전 굉장히 비효율적인 방법으로 개발이 진행되고 있었습니다.

AS-IS

  • 별도 장비에서 개발 후 빌드S3 업로드 → 태블릿에서 다운로드 및 설치 후 테스트.
  • Hot-reload 및 개발모드의 이점을 활용하지 못함.
  • 태블릿 성능이 낮아 직접 디버깅 및 실시간 검증 불가.
  • 사소한 오류 수정도 빌드, 업로드, 설치 반복으로 비효율적.

TO-BE

  • 성능이 좋은 태블릿을 엔진과 연결하여 개발.
  • Metro bundler와 원격 통신을 활용해 실시간 개발 및 검증 가능.
  • Hot-reload 기능으로 개발 속도 및 이슈 대응 속도 대폭 향상.
 

통신 프로토콜 정의

notion image
제가 개발한 앱은 영양제 토출 엔진을 제어하는 책임이 있어, 펌웨어와 데이터를 주고받기 위한 프로토콜 설계가 중요했습니다.
UART 통신바이트 단위 비동기 통신으로, 메시지 구조와 동작 방식은 별도의 프로토콜 정의를 통해 협의해야 했습니다.
  • 메시지의 시작과 끝 구분 방식
  • 명령 기능 식별 및 데이터 구조(가변/고정 길이)
  • 데이터 무결성 검증 및 복구 로직
  • 시스템의 주종 관계 또는 대등 관계 정의
 
부팅 알림, 슬립모드, 재부팅, 버전 정보, 영양제 토출, 모터 구동, 커버 상태 알림, LED 및 팬 제어, 온도 정보 조회, 보틀 메모리 관리, 펌웨어 업데이트 등
위와 같이 엔진에게 요구할 다양한 명령어들에 대해서도 협의하며 구현하였습니다.
초기 외주 개발 단계부터 내부 개발자 채용 이후 온보딩 과정, 통신 방식의 지속적인 업데이트까지 모든 과정을 주도하며 개발을 진행했습니다.
 
바이너리 데이터를 주로 다뤄야 하며, 통신프로토콜비트연산 관련 처리 등 로우레벨을 다뤄야 하는 부분들 때문에 개발자 충원과 내부 팀원들이 작업을 기피했는데, 이 부분은 뒤에서 다룰 아키텍처 설계챕터 세션, 페어프로그래밍으로 풀어냈습니다.
 

사용자 건강정보 연동

회사의 핵심 비지니스는 사용자 맞춤 영양제 제공이므로 사용자의 건강관련 정보를 연동하여 사용자 맞춤 영양성분과 용량을 계산할 수 있도록 하는 것이 중요합니다.
그 중 건강검진내역, 복용약물정보를 얻어오는 것과, 수면측정 및 수면측정 결과를 바탕으로 몸상태 추천 알고리즘 구현을 맡아서 개발하였습니다.
주로 서드파티 기능 연동과 관련된 기능이었고, 서드파티 기능을 연동한 모듈 설계에 힘을 주었습니다.

1) 건강검진, 복용약물 정보 연동

notion image
사용자 인증 후 자신의 건강검진 이력, 처방받은 약물정보 등을 불러와 연동하는 기능입니다.
notion image
codef 라는 서드파티 스크랩핑 서비스를 이용했고, 서비스에서 제공하는 형태를 이해해야 했습니다.
심내혈관 질환예측, 진료받은 내역, 진료 및 투약정보, 건강나이, 건강검진결과 등 다양한 정보를 한 번의 인증으로 가져오고자 했으나, 서비스의 제공 방식이 일반적이지 않아 많은 고민을 하게 되었던 사례입니다.
 
일반적으로 사용자는 필요한 정보를 한 번의 API 요청으로 전달받을 수 있습니다.
하지만 codef 서비스는 아래와 같은 독특한 방식으로 처리되었습니다.
  1. 모든 정보는 개별적으로 API를 통해 요청해야 한다.
  1. 한 번의 인증으로 여러 정보를 가져오려면,
      • 사용자가 첫 번째 API 요청을 전송한 후,
      • 첫 API가 처리완료 되기 전 나머지 API 요청들을 각각 별도의 소켓으로 요청해야 한다.
  1. 첫 번째 API 요청이 처리 완료될 때까지는 모든 요청이 Pending 상태로 대기하며 응답이 없다.
  1. 첫 번째 요청이 완료된 후, 나머지 요청들도 순차적으로 처리 및 반환된다.
 
이에 대응하기 위해 첫번째로는 사용자가 스크래핑 하고자 하는 정보들을 개별로 요청한 후 리스폰스들을 직접 조합하는 것을 사용자 측에서 하는 게 아닌 서비스 측에서 처리하여 통상적인 방식으로 API를 사용할 수 있도록 서비스 동작방식 개선을 요청하였습니다.
다음으로 서드파티 서비스의 기능개선까지 기다릴 수 없으므로 별도의 간편인증 모듈과, 서비스에서 요구하는 형태의 데이터 형식으로 가공하여 요청을 보내고 수신된 결과에 대한 해석 및 예외처리를 담당하는 미들웨어로 나누어 구현했습니다. 기능을 필요로 하는 곳에서는 단순히 인터페이스만 참고하여 복잡한 내부 사정을 모른 채 기능을 사용할 수 있도록 모듈을 구성하였습니다.
 

2) 사용자 수면정보 연동

notion image
또 다른 사용자 정보 연동으로, 소리로 수면패턴을 분석하는 서비스를 제공하는 서드파티 기능을 연동하여, 사용자의 그 날의 수면분석 레포트를 바탕으로 당일 맞춤 영양제를 보다 세밀하게 조정해주는 기능입니다.
서드파티 사의 수면레포트 데이터를 바탕으로 맞춤 영양제를 조정하는 알고리즘은 약사분들이 고안해주셨습니다.
알고리즘에 대한 이해와 개발에 필요한 정보들을 추출 및 가공하는 과정은 여러차례 미팅을 거치며 확립했습니다.
 
notion image
서드파티 사의 수면측정 기능은 AndroidiOS Native Module만 제공하며, React Native 환경에서 사용하기 위해 포팅 모듈을 직접 구현해야 했습니다.

콜백 기반 구조

각 sdk 에선 성공,실패 시 동작할 callback 함수를 전달받아 처리하는 형태였는데, 우리는 javascript에서 로직을 처리하므로 javascript callback 로직을 native로 내려보낼 수 없습니다.
callback을 인자로 받아 적절히 호출하는 형태가 아닌, native module 측에서 처리결과를 반환하도록 튜닝하여 javascript의 promise 형태로 주고받을 수 있도록 별도의 모듈을 android, ios 각각 만들어서 해결하였습니다.

부가 기능 구현 위치

또한 sdk에서 제공기능 뿐만 아니라, 우리 서비스에서 다루고자 하는 추가 내용들이 있었는데, 이 기능을 각 native 모듈에서 구현할 지, 기능을 이용하는 react-native 단에서 구현할 지 결정이 필요했습니다.
저는 관리 포인트를 한 군데로 두기 위해 해당 부가 기능들은 react-native 단에서 구현하기로 결정했습니다.
따라서 구현방안은 다음과 같습니다.
  • Native 모듈들은 오로지 SDK의 메소드를 promise 형태로 React-native로 포팅하기만 한다.
  • 실제 SDK 활용 로직은 RN에서 작성함으로써 관리 포인트를 한 군데로 둔다.
결과 영상입니다. 사용자의 수면 리포트 결과에 따른 수면 관련 몸상태와 심각도가 달라집니다.
 

토출 기능 개발

유저 맞춤 토출 기능

notion image
프로덕트의 주요 기능입니다.
사용자의 건강정보와 문진결과를 바탕으로 사용자 맞춤 섭취 권장량이 계산된 상태이고,
영양제 토출 엔진을 통해 사용자 맞춤 용량으로 영양제를 토출하여 섭취할 수 있습니다.
  1. 현재 엔진에 장착된 영양제 정보를 동기화하고,
  1. 유저의 데일리 수면결과와 몸상태 정보를 받아 세밀한 오늘의 토출량을 조정한다.
  1. 서버로부터 사용자의 맞춤 영양 정보를 요청하여 수신하고,
  1. 각 슬롯별 몇 알 씩 토출시킬 것인 지를 계산하여 변환하고,
  1. 엔진으로 토출 명령을 내린다.
  1. 결과를 수신하여 사용자에게 보여주고, 서버에도 기록한다.
 
notion image
간단하게 압축했으나, 기본 흐름 외에도 물리 기기와 작은 제형이 만나다보니 제형이 끼인다던지, 필요한 보틀이 장착되어 있지 않거나, 토출 도중에 제형이 소진되거나, 토출 도중에 보틀간의 접촉이 떨어지는 경우, 토출중인 영양제 카운팅을 제대로 하지 못해 과하게 토출되는 경우 등 다양한 이슈들에 대한 판단방법과 대응방법에 대해서도 협의하여 반영하였습니다.
 
단순히 주어진 기능만을 구현하는 것이 아니라,
  • 문제가 발생한 것을 어떻게 인지할 수 있고,
  • 사용자에게 어떻게 알릴 것이고,
  • 어떻게 해결해 볼 수 있을 지에 대해
하드웨어 파트CX 파트와도 긴밀히 협의하였고, 에러코드 정의 및 문서화도 진행하여 여러 파트들과 문제에 대한 이해수준을 맞추고 유저에게 일관된 대응이 가능하도록 하였습니다.
 

스페어 모드

notion image
주요 고객사에서 운영 과정에서 서버 또는 엔진 상의 이슈로 임직원이 당일 영양성분을 섭취하지 못하는 상황이 생기는 것에 대안 대비책으로, 서버, 네트워크 문제와도 상관없이 무조건 동작하는 기기를 원했습니다.
 
notion image
notion image
따라서 서버와의 통신 없이 오프라인 상으로 독립적으로 동작하는 별도의 기기설계해야 했고, 서버에서 수행하는 토출량 계산 알고리즘을 간소화 시켜서 엔진 내부로 탑재시키기로 했습니다.
자세한 알고리즘을 공개할 순 없지만 대략적으론 다음과 같습니다.
  1. 사용자가 선택한 성별&나이대의 기본용량을 가져온다.
  1. 사용자가 선택한 몸상태의 분류, 심각도, 개수 등을 고려하여 적정량을 증감량 한다.
  1. 증감량이 과도하게 적용되는 경우 최대최소 알고리즘을 통해 보정한다.
 
notion image
notion image
동일한 영양성분 이더라도 생산분에 따라 제형당 함유량을 다르게 생산하는 경우가 있으므로, 신규 생산 보틀에 대해서는 업데이트가 필요하다는 한계점은 있지만, TDD 방식과 적절한 로직 분리 설계로 빠르고 정확하게 고객사의 추가 요구사항에 대응할 수 있었습니다.

팩토리 모드

엔진 공정단계출하 전 검수과정, 회수 엔진 기능점검 등을 위한 기능점검 기능이 필요하다는 하드웨어 파트 측의 요청으로 진단도구를 개발했습니다.
엔진의 실시간 상태정보가 컨트롤러인 태블릿과 실시간으로 동기화 되며, 버튼을 통한 개별 제어도 가능합니다.
부품 수명 측정을 위해 하드웨어 파트의 구현 요청사항에 따라 부품들을 끊임없이 가동시키는 에이징모드 의 구현도 같이 진행하였습니다.
이 결과로 엔진 한대당 부품 교체까지의 평균수명과, 제품검수 외주업체의 검수 프로세스 확립을 도왔고, 점검인력의 점검 가이드라인의 확립으로도 이어져 어떤 부분에서 문제가 발생하는 것인지 구체적으로 파악하고 보고할 수 있게 되었습니다.
 

펌웨어 업데이트 기능 개발

엣지 케이스 대응 테스트 - 펌웨어 업데이트 진행 중에, UART 연결을 끊는 등 예외 상황을 발생시켜도, 재연결 됐을 때 펌웨어 업데이트가 정상적으로 동작한다.
하드웨어를 직접 제어하는 펌웨어와 같이 개발이 진행되므로 펌웨어 업데이트도 필요합니다.
메모리 데이터를 덮어쓰는 방식이기 때문에 펌웨어가 잘못 덮어쓰여지면 회수를 하지 않고는 복구가 어려운 문제가 있어 한번 전사적으로 큰 문제가 됐던 적이 있습니다.
이슈 문의가 쇄도했으며, 주요 고객사에선 “이러한 리스크 부담을 안고 향후 현재와 같은 방향으로 서비스를 운영하는 것은 무리한 것으로 보입니다”라는 메일까지 받으며 위기였던 순간입니다.
 
이 문제를 해결하기 위해 다음과 같은 작업들을 진행하였습니다.
  • 여러가지 엣지 케이스에 대한 처리
    • 업데이트 도중 엔진전원이 꺼지는 경우, 업데이트 도중 태블릿 전원이 꺼지는 경우, 메세지가 누락된 경우, 잘못된 데이터가 수신된 경우, 업데이트 명령어 외에 다른 명령어를 받은 경우, 헤더에 명시된 길이와 실제 펌웨어 길이가 다른 경우
  • 큰 펌웨어 파일을 손상없이 전송할 방법 (데이터 무결성, 리커버리)
    • xmodem-1k 프로토콜 도입 (패킷의 순서보장, 특정 패킷의 재전송 등)
      • 노이즈로 인해 3회씩 NAQ가 발생하는 경우 - 10회 까지는 해당 패킷을 재전송한다.
        노이즈로 인해 3회씩 NAQ가 발생하는 경우 - 10회 까지는 해당 패킷을 재전송한다.
  • 정상적인 펌웨어인지 검증방법 고안/적용
    • 펌웨어 바이너리 앞에 커스텀 정의한 헤더 데이터 추가 (대상 엔진의 종류, 버전, 무결성검증값 등)
  • 테스트 코드 작성
  • 여러 담당자들과 테스트 케이스 크로스체크
  • 엔진 종류별 펌웨어 관리 방안 도입
    • API 설계 협의
 
notion image
최종적으로 대응에 필요한 태스크 플래닝 뿐만 아니라 TC를 정의하여 발생할 수 있는 모든 케이스들에 대해 정의하고 검증하고자 했습니다. 모든 테스트 케이스는 문제, 원인, 해결, 검증 방법, 기대 결과 틀에 맞춰 작성하여, 모든 테스터가 동일한 테스트와 기준으로 판단하도록 하였습니다.
펌웨어 업데이트 관련한 이슈 발생률 자체도 현저하게 줄어들었고, 이 사건 이후로 펌웨어가 잘못 덮어쓰여져서 복구가 불가능 했던 사례는 제가 일하는 기간 동안은 단 한건도 없었습니다.
 

POC 런칭

notion image
저희는 단계적 런칭을 진행했습니다.
기본적인 기능들조차 완성되지 않았던 상태에서 입사했는데, POC 런칭일자가 몇달 이내로 잡혀 있었습니다.
 
엣지케이스들까지 고려한 안정화까지 완료한 후 POC를 돌리긴 어렵다는 말을 경영진 분들께 충분하게 설명을 드렸고, 경영진들의 니즈가 “완성된 프로덕트”가 아닌 “우리가 사기꾼이 아니다. 실제 아이디어가 개발되고 있다”를 보여주는 것이 더 중요하다는 목표에 대해 싱크를 맞췄습니다.
이후 당시 엔진 개발 담당자가 저 혼자였기 때문에, 목표에 맞게 MVP 수준의 기본적이고도 필수적인 기능과 알고리즘에 대해서만 개발하는 것으로 목표를 추리고, 밤낮 공휴일 가리지 않고 시간을 태우는 두 가지를 선택하였고 정상적으로 POC 런칭을 진행할 수 있었습니다.
 
위 갤러리 사진은 POC 런칭 준비 시 회사에서 밤을 새고 휴게공간에서 잠들어있던 모습입니다.
이후 경영진들 통해 “덕분에 POC를 진행할 수 있게 되었다. 오웬(본인)님 없었으면 할 수 없었다” 라는 말을 들었고, 입사 6개월만에 연봉협상과 2년간 약정을 낀 리텐션 보너스 계약을 추가로 하게 되었습니다.
 

태블릿 변경 대응

USB 연결 권한 이슈

notion image
개발 초창기에는 커스텀된 태블릿을 사용해서 OS를 튜닝하여 태블릿과 엔진 연결에 대한 이슈가 없었지만, 성능, 노이즈, 외주업체 관리 등의 이유로 기성품 태블릿으로 교체하게 되면서 권한 이슈가 발생했습니다.
권한을 승인해주면 해결되는 단순한 문제이지만 사용자가 이를 알지 못하여 혼란을 겪었고, CX 파트의 인력도 많이 낭비되었습니다.
 
저는 단계적으로 해결하는 것으로 의견을 냈고, 문제는 해결되었습니다.
  1. 사용자에게 가이드를 준다. (in the short term)
    1. → 사용자가 권한승인 팝업을 누르도록 가이드하고 참여를 유도한다.
      → 디자이너, 개발자 모두 몇시간 내로 구현 가능한 대응방안.
  1. 권한을 자동으로 승인하도록 개발한다. (in the long term)
    1. → 문제가 생기면 사용자는 단순히 엔진을 껏다 키면 해결된다.
 
notion image
단기 대응방안 이후, usb 연결을 자동으로 승인해주는 기능을 android native module로 구현하였습니다.
삼성 태블릿은 knox sdk 에서 권한 관련 기능을 제공하여 비교적 쉽게 해결하였습니다.
다만, 최초 한번은 knox 관련 권한을 승인하는 페이지에 동의를 해주어야 하는데, 공정단계 프로세스로 이 작업이 진행되어 출고되도록 하여 문제를 해결하였습니다.

UI 깨짐 이슈

notion image
태블릿의 해상도가 변경되면서 UI가 모두 깨지는 현상이 생기게 되었고, 대응이 필요했습니다.
이 과정에서 해상도에 따라 두 가지 선택지가 있다는 것을 알게 되었고,
  • 동일한 비율을 유지하도록 대응할 것인지,
  • 동일한 크기를 유지하고 유연한 UI가 되도록 할 것인지
저는 관련된 내용들을 서치하고 정리하여 프론트엔드와 디자이너 파트간 세션을 열어서 내용을 공유하고 해결책을 결정하였습니다.
🔑
아래는 챕터 세션 공유자료로, 디테일한 내용을 볼 수 있습니다.
 

아키텍처 설계

notion image
기존 프로덕트들이 Screen-Based로 컴포넌트들이 설계되고 있고, container-component 폴더구조를 사용하고 있었습니다.
  • 아무 기능도 하지 않는 껍데기 컴포넌트들
  • 너무 과한 기능을 하고 있는 컴포넌트들
  • 어디에 두어야 할 지 애매한 컴포넌트, 로직들
위와 같은 문제점으로 코드 관리, 코드 해석, 코드 작성 시에 병목이 된다고 판단하여 폴더구조를 Feature-Based로 개편하였고, 단계적 컴포넌트 설계를 새로 정의하였습니다.
이후 챕터 세션을 진행하였고, 구성안이 채택되어 프로덕트 전체에 반영하였습니다.
 
notion image
하드웨어 엔진을 제어하는 기능들을 상속 기반으로 체계적으로 구성하였습니다.
기존의 문제점은 바이너리 데이터를 직접 다뤄야 했고, 각 로직에서 메세지 송수신 또한 직접 핸들링 했습니다.
당연히 전반에 대한 이해 없이는 코드를 작성조차 할 수 없었고 이는 다른 개발자들에게 진입장벽이 되었습니다.
  • 개발 속도가 현저히 낮았고,
  • 이슈가 자주 생길 수밖에 없었고,
  • 디버깅도 어렵고,
  • 코드 변경에도 전체 코드를 항상 손봐야하는 등 유연성확장성 측면에서도 문제가 많았습니다.
 
체계적인 설계와 상속을 기반으로 폭발적인 속도안전하고도 빠르게 개발을 진행할 수 있었습니다.
이는 정식런칭을 앞둔 상태에서 출시 기기가 완전히 새롭게 바뀌는 큰 변화 속에서도 빠른 속도로 개발하며 런칭 일자를 미루지 않고 성공적으로 런칭할 수 있게 되는 원동력이 되었습니다.
또한 개발자 진입장벽이 허물어져 회사의 메인 프로덕트임에도 기피시 되던 프로덕트로 서브 프로덕트에 개발자가 더 많던 기이한 현상에서, 프론트엔드 챕터로 통합하고 개발 가용인원을 늘려 모두가 엔진 개발에 동참할 수 있는 발판이 되기도 했습니다.
 
notion image
환경과 요구사항에 따라 화면구성이 바뀌어야 하는 경우도, 엔진이 버전업 되며 변경되는 경우도 있습니다.
따라서 엔진 제어부와 화면부가 강결합 되지 않도록 레이어를 나누고 이를 철저하게 지킴으로써, 양쪽의 변화 모두에 유연하게 대처할 수 있도록 아키텍처를 구성하였습니다.
  • 고객사와의 특정 이벤트에 맞춤화된 화면을 만드는 경우는 하드웨어가 변경될 필요가 없고 (CES용, 현대건설 시연용, 자판기모드, 스페어모드 등)
  • 엔진이 업그레이드 되는 경우는 화면이 바뀔 필요가 없습니다.
  • 하드웨어 변경 시에도 펌웨어와 함께 정의한 프로토콜을 준수하도록 개발되므로 하드웨어 제어부도 변경될 필요가 없습니다.
 
레이어를 나누고 이를 철저하게 지킴으로써 여러 비지니스 이벤트에도 확장성있고 유연하고 빠르게 대처할 수 있었습니다.
또한 하드웨어에 대해 하나도 모르는 일반적인 React 개발자도 엔진 개발에 진입할 수 있게 되어, 개발 가용인원도 늘어났고 채용도 쉬워졌습니다.
 

성능개선

notion image
엔진에 대한 변경사항을 즉각적으로 알 수 있는 요소는 하드웨어를 직접 제어하는 펌웨어 밖에 없습니다.
인터럽트를 통해 즉각적으로 변화를 감지할 수 있습니다.
하지만 기존에는 태블릿에서 펌웨어로 주기적으로 polling 방식으로 request 하도록 되어 있어서 즉각적으로 반응할 수 없었고, 이는 유저 입장에서도 렉이 걸린다 또는 이질적이다 라는 느낌을 줄 수밖에 없었습니다.
인터럽트와 구독 기반으로 처리되어야 한다는 지속적인 설득 끝에 interrupt + event 기반으로 설계를 변경하여 주기적으로 전송하던 불필요한 통신을 없애고 변화에 즉각적으로 반응할 수 있게 되었습니다.
 
notion image
notion image
알고케어는 사용자의 그날의 컨디션에 따른 맞춤화도 제공합니다. 몸상태 선택 이라고 칭합니다.
장점을 극대화 시키고자 몸상태들을 더 구체화하고 늘리는 몸상태 고도화 작업이 진행됨에 따라 렌더링 최적화가 되어 있지 않던 것낮은 성능의 태블릿과 결합되면서 사용불가 수준의 렌더링 속도를 내게 됩니다.
 
성능개선으로 풀어야 할 지, 제품에 탑재된 태블릿을 고성능으로 교체해야 할 지 결정이 필요했고, 제가 내린 판단에 따라 비즈니스 임팩트가 많이 바뀌는 상황이었습니다.
기존에 유저가 하나의 몸상태를 선택할 때마다 1100ms의 렌더링 시간이 걸리던 상황에서, 100ms 아래로 내리는 것을 목표로 최적화 작업을 시작했습니다.
 
체계적인 메모이제이션 최적화와, 이후 구조개선으로 불필요한 연산 자체를 제거시킬 수 있는 방안을 고려하는 단계적 최적화를 통해 1100ms → 220ms → 40ms렌더링 타임을 96%를 개선시키며 최적화에 성공했습니다.
그 결과 회사는 기존의 제품 마진율을 그대로 가져갈 수 있었고, 기존의 부품 재고처리신규 태블릿 구매, 부품 교체에 들어가는 시간과 인력을 모두 아끼는 비지니스 임팩트를 가져올 수 있었습니다.
 
기타 최적화로는 아래와 같은 사례들이 더 있습니다.
  • 펌웨어 업데이트 시간 개선
  • React 상태 관리 최적화 - makeState (커스텀 정의)
  • 캐싱 전략 수립
 

모니터링

주요기능들이 완성된 이후에는 UX개선이슈대응, 비지니스 개선을 위해 모니터링이 중요해졌습니다.
특히 이슈대응 관련하여 사용자의 행동, 엔진의 상태, 서버의 상태, 펌웨어와의 통신문제오류가 발생할 수 있는 곳이 너무 많았기 때문에 에러를 분석하기 위한 모니터링 세팅이 가장 중요했습니다.

Amplitude

notion image
notion image
가장 먼저 도입했던 건 앰플리튜드 입니다.
  • 기본적으로 사용자의 행동 플로우를 참조하기 위해 화면 진입 관련 기본적인 이벤트 로깅이 추가 되었고,
  • 저는 여기에 사용자가 진입한 화면별 이슈가 될 수 있는 부분들은 디버그 이벤트, 에러 이벤트로 구체적인 상황을 이해할 수 있도록 로깅을 추가 하였습니다.
  • 앰플리튜드는 이벤트가 발생한 그 순간을 남기는 것이 기본입니다. 하지만 우리는 일련의 과정을 통틀어서 하나의 이벤트로 봐야하는 순간들도 있었으나 그러한 방식은 앰플리튜드에서 지원하지 않아서, 저는 일련의 이벤트를 쌓아놓고 하나의 이벤트로 처리할 수 있도록 커스텀 클래스를 만들어 해결했습니다.
앰플리튜드는 유저의 행위를 추적하는 것이 목적이므로, 유저 중심으로 로그가 관리됩니다.
 
notion image
개발자와 CX 파트에서 확인해야 하는 주요 이벤트 추적과 관련된 대시보드들주로 제가 만들어서 공유했습니다.
대표적으로는 회사에서 가장 큰 문제가 됐었던 이슈 중 하나인 펌웨어 업데이트가 잘못되어 엔진이 망가지는 경우와 관련된 것으로, 이벤트 시퀀스를 이용하여 전체 다운로드 시도 중에 몇 건이 정체중인지를 파악하고 추적 관찰 할 수 있도록 하였습니다.

슬랙 연동

계절이 바뀌면서 온도변화에 따라 결로 현상이 생겨 엔진에서 굉음이 나는 등 문제가 되었습니다.
원인을 찾아야 했고, 온도와 관련될 거라는 추측이 있어서 급하게 모니터링이 되어야 했습니다.
 
앰플리튜드는 사용자별 행동 추적 용도이므로, 유저가 아닌 기기별 냉장상태를 지속적으로 관찰하는 것에는 적합하지 않았고, 장기적으로는 appsync를 통해 엔진에 대한 실시간 로그를 DynamoDB에 쌓고 Kibana로 시각화 하기로 했지만, 아직 구현방안이 구체화 되지 않았던 시점에서 임시 대책으로 기기별 냉장과 관련된 것들을 슬랙을 이용한 실시간 모니터링을 구현하였습니다.
notion image
냉장온도, 펠티어 온도, 외내부 팬 동작 유무결로 발생여부를 관찰하며 상관관계를 찾아내고, 하드웨어 파트에서 결로 대안을 마련할 수 있었습니다. 엔진별 실시간 모니터링 체계가 확립되기 전 적절한 조치였다고 생각합니다.

Appsync + DynamoDB / Kibana

notion image
사용자별 로그 추적 뿐만 아니라 엔진별 모니터링의 필요성도 느껴서 대안을 마련하게 됩니다.
데이터 파트에서 위 그림과 같은 아키텍처로 로그를 모으고 시각화 하기로 하였고, 저는 맞춰서 대응할 수 있도록 펌웨어 개발자와 협의하여 엔진의 실시간 모니터링에 필요한 정보들을 주기적으로 확인하고 전송할 수 있도록 구성하였습니다.
notion image
결과로 엔진별 기록을 바탕으로 통계를 낼 수 있어, 기기별 토출횟수토출 시간대, 보틀 소진 주기 등을 시각화 하여 대시보드를 만들 수 있었습니다.
notion image
수많은 엔진 정보가 실시간으로 모니터링 되고 있는 모습입니다.
앰플리튜드사용자별 로그를 볼 수 있었다면, appsync를 통해 엔진별 로그를 볼 수 있게 되었습니다.
notion image
특정엔진에서 이슈가 발생한 경우 엔진 시리얼로 필터를 걸어 오류 발생 전후 상태 변화 등을 확인할 수 있습니다.
예시로 위 그림은 토출 오류가 발생한 상황에서 확인해보니 7번 슬롯오메가3 보틀의 제형이 소진되어 맞춤용량을 온전히 다 토출하지 못했다는 사실을 확인할 수 있습니다.

결론

이로써 오류 발생 시의 사용자 행동과, 엔진의 상태변화를 각각 구체적으로 확인할 수 있게 되었고, 구체적인 상황 정보를 바탕으로 버그픽스적절한 CX 대응이 가능하게 되었습니다.
 

공식 런칭

notion image
2023.03년 출시 일정으로 기사들까지 이미 쭉 뿌려진 상태였고, 롯데헬스케어와도 분쟁중인 상태로 공식 런칭일자는 차질 없이 반드시 이행 되어야만 했습니다.
 
notion image
저의 체계적인 아키텍처 설계를 기반으로 팀원들과 함께 밤낮 가리지 않는 개발 끝에, 런칭 직전 출시 엔진이 변경되는 급박한 상황 속에서도 런칭 일자를 미루지 않고 성공적으로 공식런칭을 할 수 있었습니다.
 

그 밖의 프로덕트 개발

📌
기본적으로 저는 프로덕트의 코드품질 관리 책임을 맡아, 프론트엔드 전체 프로덕트에 대해 상세 코드리뷰를 진행하였고, 메인 프로덕트는 제 approve를 필수로 받아야만 병합할 수 있는 정책이 있었습니다. 또한 주니어들의 비교적 큰 태스크의 경우 사전설계를 맡거나 같이 설계하는 형태로, - 코드리뷰 후 너무 큰 변화로 여러번 개발하게 되는 것과 같은 현상을 막았고, - 주니어들의 설계 역량도 높히고자 했습니다. 위와 같은 형태로 전체 프로덕트에 기여하였고, 아래는 직접 구현한 것들 중 주요한 부분을 다룹니다.

결제 (Webview)

notion image
notion image
기존 B2B 솔루션에서는 매달 고객사로부터 엑셀 이용자 명단을 전달받아 관리하며,
  1. 모집 기간 외 신청자는 다음 달까지 대기
  1. 고객사의 명단 관리 부담이 있었습니다.
이를 개선하고자, 앱 내 구독/결제 모델로 전환하여 각 사용자가 직접 결제하도록 시스템화 했습니다.
 
저는 결제 심사용 서비스 개발결제 모듈 설계/구현을 담당했습니다.
TossPayments를 결제 모듈로 채택하고, React-Native 환경에서 빠른 도입을 위해 웹뷰(WebView) 방식을 활용했습니다.
  • 웹뷰 기반 결제 플로우
    • 웹뷰로 결제 페이지를 띄우고, JavaScript Injection으로 명령 전달.
    • 결제 성공/실패 시 redirect를 캐치하고 필수 파라미터를 추출해 앱 내에서 후속 작업 처리.
  • 간소화된 추상화
    • 단건 결제는 requestPayment(), 정기 결제는 requestBillingAuth() 등 배경지식 없이 인터페이스만 참조하여 간단한 메서드로 쉽게 사용 가능하도록 설계.
    • 결제 심사 및 정식 서비스에서 코드 변경 없이 재사용.
 

B2B Admin (Web)

기존까지는 사업장별 영양제 보틀 재고현황 파악 및 보충 작업알고케어 내부에서 파악하고, 주기적으로 정기점검을 가서 확인하는 형태로 관리되어 왔습니다.
하지만 고객사가 점점 늘어나면서 이전의 형태를 유지하는 것이 어렵고, 주요 프로덕트 기능 개발도 완료된 상태였으므로 보틀 관리 및 주문 관련 기능도 고객사의 관리자가 직접 관리할 수 있도록 하고자 했습니다.
 
저는 B2B Admin 페이지 중에서도 보틀 재고 관리, 보틀 주문 기능을 맡아서 개발하였습니다.
기존에는 Styled-component로 개발해왔는데, 빠른 구현을 위해 B2B Admin에선 Tailwind-css로 개발하였습니다.
notion image
회사 전체 이용량을 월별로 확인하고, 회사 내 사업장 별로도 재고 현황을 확인할 수 있습니다.
 
notion image
영양제가 소진된 경우 고객사 내 관리자가 직접 보틀을 주문할 수 있고, 주문 내역도 확인할 수 있습니다.
 

디자인시스템

notion image
사용자에게 통일된 UI를 제공하고, 빠른 개발유지보수를 위해 디자이어와 협의하여 디자인 시스템을 구축하게 됩니다.
디자이너와 개발자 모두 디자인시스템이 무엇이고, 디자인시스템의 범위에 대한 싱크가 맞지 않아서 종종 혼란이 있었고, 이 문제를 해결하고자 아래의 공유자료를 준비하고 소프트웨어 파트 세션을 열어 싱크를 맞췄습니다.
저는 주로 재사용가능한 컴포넌트 사전설계 부분을 맡았고, 페이지 스켈레톤 등 일부 요소들은 직접 구현하였습니다.
 

보안지식 접목

graphql 스키마 덤핑 방지

notion image

환경변수 분리/관리

엔진 인증안 마련

 
 

맺음말

하나의 별에서 같이 빛나기까지
하나의 별에서 같이 빛나기까지
알고케어에서 저는 기술적 성장뿐만 아니라 정신적 성장까지 이뤘습니다.
하드웨어, 헬스, CX 등 다양한 파트 구성원들과 협력하며 폭넓은 커뮤니케이션 능력을 쌓았고, 비즈니스 아이디어를 기술로 실현하고 주요 기능과 목표를 경영진과 조율,설득하며 핵심 일정 준수와 문제 해결에 기여한 경험은 제게 큰 자신감을 주었습니다.
비즈니스의 급격한 성장 속에서 팀워크의 중요성을 깨닫고, 가용 인원 확보와 원활한 협업을 위해 진입장벽을 허물며 프론트엔드 챕터 통합을 이뤄냈고, 챕터세션사전설계, 페어프로그래밍 등으로 팀원들과 함께 성장하며 비지니스에 기여할 수 있는 환경을 조성했습니다.
그 후로는 단순 기능 개발을 넘어 모든 프론트엔드 프로덕트의 품질 관리 책임을 주도적으로 맡았고, 챌린지를 주로 맡으며 서비스 안정화, 사용자 경험 향상에 기여하였고, 비즈니스 방향에 따른 유연하고 확장성 있는 아키텍처 설계하며 조직의 기술적 비전과 방향성을 이끌었습니다. 저는 알고케어에서 회사의 성장을 함께하며 키 멤버로서 팀과 협업의 가치를 실현해왔음을 자부합니다.