프로젝트 경험 소개 : 코어 플랫폼 확장 본문
플랫폼 확장하기
나는 IoT 서비스를 운영하는 회사에서 일하고 있다.
개발자들이 인프라를 다루기 위해 AWS를 사용하듯, IoT 개발 역시 플랫폼을 사용하면 쉽게 기기를 관리할 수 있다.
기기 제어와 이벤트 처리를 플랫폼에 맡겨, 서비스 개발에 집중할 수 있게 하는 것이다.
대신 각 플랫폼마다 성향과 기능이 달라, 이에 서비스 방향이 의존되기도 한다.
지금까진 단일 플랫폼으로 운영되고 있었다.
나는 이를 확장하여 다른 여러 플랫폼을 함께 사용할 수 있도록 하는 프로젝트에 채용되었고,
지금은 세 개의 플랫폼을 지원할 수 있게 되었다.
그 결과로 회사에 중요한 사업을 런칭하는데 기여할 수 있었다.
무엇보다, 이후로 더 많은 플랫폼을 추가할 수 있는, 확장 가능한 시스템의 기반을 만들었다고 자부심을 갖고 있다.
이 글에선 그 과정에서의 재밌었던 문제들과 내 역할을 가볍게 정리해보려고 한다.

신규 개발
플랫폼마다 제공하는 기능과 Api 규격이 다르다.
팀의 방향은 '기존과 동일한 기능과 Api 규격을 갖는, 플랫폼 주변 서비스들을 개발하자'였다.
일반 사용자가 알지 못하게, 자연스레 전환하는 것이 우리의 목표였다.
플랫폼끼리 서로 달라서 필요했던 개발은 '기록 서비스'가 가장 좋은 예시일 것 같다.
이미 서비스되고 있던 플랫폼보다, 추가한 플랫폼들의 보관 기간이 적었다.
기존 플랫폼에서 분리하여, 공통의 기록 서비스를 따로 개발하였다.
데이터가 남아있는 기간 동안 양 쪽을 모두 조회하는 방향으로, 기존 데이터를 마이그레이션 없이 처리할 수 있었다.
Api 규격 통일에도 고생했다.
플랫폼 별로 Api 형태가 달라, 각 서비스들이 플랫폼을 직접 참조하는 게 아니라,
기기 관련 요청은 '기기 서버'에 전달하고, 기기 서버에서 기기의 플랫폼 정보를 읽어 해당 규격으로 요청을 파싱 하도록 했다.
각 서비스들은 기기에 상관없이 공통된 내부 규격으로 통신하고, 오직 기기 서버에서만 플랫폼에 의존하도록 하는 것이다.
물론 기기 서버가 단일 장애 취약점이 되지 않도록 다중화를 해두었다.
ALB로 요청이 들어오면, Url Path 규칙에 따라 ECS 서비스를 찾고, 헬스 체크에 성공한 Task만 라우팅 대상이 된다.
개선을 위한 개발
기존에 있던 기능이지만 이슈를 풀어야 했던 개선 문제도 있었다.
사용자의 기기 목록 조회 시, 전에는 단일 플랫폼만 조회하면 됐지만 이젠 여러 플랫폼에 요청을 던져야 한다.
여러 플랫폼을 병렬 처리를 위해 멀티 스레드를 썼었고, 스레드 풀을 신경 써야 했다.
다른 운영 이슈였지만, 스레드 풀 관리를 잘못해서 OOM이 터져버렸던 문제가 터졌었고,
이에 리액티브로 병렬 요청, 여러 응답을 조합하여, 더 적은 수의 스레드로 같은 속도를 만들 수 있었다.
물론 커넥션 풀의 제한은 있지만, 각 스레드가 응답을 블록킹 대기하여 스레드 풀이 고갈되는 위험에서 벗어날 수 있었다.
구조를 변경했던 건들도 있었다.
특히 회원 탈퇴 이벤트 처리가 재밌었는데, 탈퇴 이벤트 처리가 필요한 서비스가 늘었고, 처리 시간이 늘었다.
무엇보다 기존의 Http를 사용한 이벤트 전달보다 꼼꼼한 유실 관리, 재시도 처리가 필요하다고 느꼈다.
탈퇴 이벤트를 카프카 토픽으로 하고, 이벤트가 필요한 서비스에서 처리가 가능할 때 수신하는 식으로 구조적 안정성을 높였다.
가장 재밌었던 고민
새로운 플랫폼에서의 동적 페어링 개발 가장 흥미로웠다.
기존에는 SDK로 페어링하여, 서버 측에선 크게 신경 쓰지 않고 페어링 결과만 전달받아, 내부 동작 원리를 모르고 있었다.
새로운 플랫폼에선 직접 구현해야 해서, 모바일 / 펌웨어 팀과 시나리오를 소통해야 했다.
로컬 네트워크에 있는 기기로의 통신이 필요했다.
AP 모드를 공부했고, 앱과 기기 간 로컬 통신을 구현할 수 있었다.
페어링 시, 즉 서버와 연결 이전에, 인증을 위한 토큰을 앱에서 기기로 전달하는 과정에 로컬 통신이 쓰였다.
페어링 시도 주기와 타임아웃, 실패 시 미리 생성해 둔 데이터 삭제를 위한 스케줄링 등 놓치기 쉬운 예외가 있었다.

DB 적재 성능 개선을 위한 배치 처리 작업도 재밌었다.
기록 서비스에선 기기 상태 이벤트를 쉴 새 없이 저장해야 하는데, 그 유입량이 점점 늘어 개선이 필요했다.
처음엔 리액티브로 풀어보려고 했지만, 이벤트가 들어오는 족족 저장해야 했기에, 연산량이 높아져 DB의 Cpu가 치솟았다.
이를 이벤트를 큐에 쌓았다가 간격을 두고, Bulk insert 하여, 네트워크 비용과 DB I/O를 줄이고, 처리량을 크게 개선하였다.
배치 사이즈와 주기 설정에 대한 꼼꼼한 검토가 중요했다.
그 값이 적절하지 않으면 처리량이 밀리거나, DB 적재를 위한 시간이 너무 오래 걸릴 것이다.
안전한 종료를 위해 진행 중인 배치 처리, 이미 큐에 적재된 이벤트를 비우는 로직에 대한 고민과 테스트가 필요했다.

소통
플랫폼을 직접 배포하고 인프라를 관리하며, 운영에 바로 사용하는 것은 무리가 있을 수 있다.
서비스 개발에 집중하기 위해 사용한 플랫폼 때문에, 오히려 배보다 배꼽이 더 큰 상황이 벌어지는 것이다.
우리도 마찬가지였다.
배포 가이드도 있었고, helm처럼 yaml 기반의 쉬운 배포 설정 값 조정 방법도 있었지만, 아무래도 위험하다고 평가했다.
그래서 처음 플랫폼을 개발사로부터 가져올 때, 개발자로서 함께 검토해야 하는 것들을 소통하기도 했다.
이를테면 기술 지원 범위를 구체화하고 배포 리소스는 적정한지, 빠진 가이드 문서가 없는지 검토했다.
비슷한 이유로 두 번의 출장을 다녀왔는데, 다녀올 때마다 아주 진이 쭉 빠져 돌아오곤 했다.
출장 시간을 헛되이 쓰지 않기 위해, 출장 전부터 소통 거리와 자료를 꼼꼼히 준비해 가야 했고,
영어로 대화가 잘 안 될 땐 칠판을 써가며 손짓 발짓으로 대화하는 경우도 많았다.
처음엔 3박 4일이었던 출장이, 풀이가 안되니 점점 길어져, 예정에도 없이 8박 9일로 늘어난 적도 있었다.
비행기 표가 계속 바뀌어서, 수수료도 많이 나왔다. 😅
예상치 못한 일정 변화에 이사님이랑 속옷을 샀던 사진인데, 그 극한 출장을 추억하기 가장 재밌는 사진이 되어버렸다.

가시화
이 프로젝트를 하면서 몰랐던 내가 좋아하는 것을 발견했다.
난 어떤 작업을 하기 전에, 데이터 흐름이나 큰 그림을 그려보는 걸 좋아하더라.
뭐랄까, 지금 어떤 방향을 갖고 일하고 있고, 내가 그 그림에서 어느 부분을 맡고 있구나를 아는 걸 즐기는 것 같다.
레고를 맞추기 전, 대강의 결과물을 미리 알고, 지금 내가 어떤 부품 만들고 있는지를 알면 재밌는 것처럼 말이다.
주변 팀원들, 이사님들이 유독 칭찬해 준 포인트였다.
팀의 현 상황을 그리는 것도 있었지만, 서로의 생각을 가시화할 때 사용되는 스케치로 쓰일 때도 있었다.
말, 글로만 설명하는 것보다, 도식화하는 것이 우리 팀이 생각 싱크를 맞추는데 가장 효과적이었던 것도 같다.
블로그 글쓰기가 큰 도움이 되었다.
도식화는 그저 생각 정리, 공부 정리를 위해 쓰던 블로그 정리 습관 중 하나였던 것도 같다.
'어떻게 이렇게 깔끔하게 그리지'라는 칭찬이 가장 듣기 좋았던 말이었고,
그래서 더 신나서 연습했는지도 모른다.

정리
대학 생활, 우테코 생활을 통틀어, 가장 재밌고 열심히 했던 프로젝트가 아니었나 싶다.
배울 수 있는 팀원들이 있었던 것도 크고,
그로 인한 비즈니스 성과가 바로 보여서 더 재밌었던 것도 같다.
사람은 능동적으로 일할 때 가장 아웃풋이 좋다는 것을 또 한 번 느낀다.
참 감사한 시간이었다.
'KimJinHwan > Project' 카테고리의 다른 글
| 논 블록킹 처리 : 스레드 사용 효율 개선 경험과 주의할 점 (0) | 2025.09.04 |
|---|---|
| 캐시 도입 : 이벤트 파이프라인 처리량 높이기 (1) | 2025.08.28 |
| 클라우드 비용 절감기 : 월 천만 원을 절약한 스케일 다운 (0) | 2025.04.05 |
| S3 업로드 프로세스 개선 : Pre-signed url과 Thumbnail 처리 (0) | 2024.05.31 |
| simple-auth : 토큰 인증 시나리오를 대신해주는 라이브러리 (0) | 2023.11.26 |