← 저널

단순한 인터페이스, 지켜지는 규칙: 만남 모바일 앱 개발하기

단 하나의 자리를 보장하고, 서버 시각을 따르며, 네트워크 단절을 견디고, API가 기밀성을 강제해야 하는 iOS 및 Android 모바일 앱의 설계 회고.

모바일 개발아키텍처React NativePostgreSQL기밀성

단순한 인터페이스, 지켜지는 규칙

공공장소 하나. 정해진 소요 시간. 참가자 두 명. 이 앱은 사진이나 자기소개를 훑어보지 않고도 가까운 곳의 활동을 제안하거나 참여할 수 있게 합니다. 의도적으로 축소한 이 형식 뒤에서, 우리는 단 하나의 자리, 시간표, 끊긴 연결, 그리고 모두에게 보여서는 안 되는 정보를 다루어야 하는 제품을 만들고 있습니다.

배경

커피 한 잔, 산책, 전시 관람: 출발점은 공통의 활동과 공통의 가능한 시간입니다. 한 사람이 제안하고 다른 사람이 참여합니다. 두 사람은 현장에서 서로를 알게 됩니다.

이 제품은 Scopes가 몽펠리에에서 설계하고 개발합니다. 작업은 사용자 흐름 설계, iOS 및 Android 앱, 업무 서비스, 관리 도구, 소개 사이트를 포함합니다. 제약은 덜 눈에 띄는 상황을 처리하면서도 경험을 읽기 쉽게 유지하는 것입니다. 두 사람이 같은 순간에 예약하고, 네트워크 응답이 로그아웃 뒤에 도착하며, 요청이 대기하는 동안 약속이 만료되는 상황입니다.

이러한 상황이 화면만큼이나 아키텍처를 결정합니다.

화면을 늘리기 전에 흐름을 모델링하기

제안의 생애주기는 명시적인 상태와 전이로 기술됩니다. 게시, 예약, 도착, 취소, 만료입니다. 규칙은 네트워크와 데이터베이스에 독립적인 TypeScript 모듈에 모여 있습니다. 이 모듈은 행위자의 신원과 서버가 제공한 시각을 받아, 그 행동이 가능한지 결정합니다.

참여, 잠금 하에시작 시각 경과취소참여 철회도착 없이 시작 경과 도착 신고게시됨예약됨만료됨취소됨현장

이 분리 덕분에 앱을 실행하지 않고도 규칙을 밀리초 단위로 검증할 수 있습니다. 또한 화면, HTTP 라우트, 자동 처리가 같은 상황을 서로 다르게 해석하는 일을 막습니다.

API는 Fastify와 PostgreSQL 위에 있습니다. 모듈형 모놀리스를 택하면 업무 연산이 하나의 트랜잭션 안에 머물고, 운영해야 할 서비스 수가 줄어듭니다. 검증 계약은 클라이언트와 공유하되, SQL 접근은 서버 쪽에 남습니다.

단 하나의 자리 보장하기

두 사람이 동시에 "참여"를 누르면 한 사람만 자리를 얻어야 합니다. 결정은 해당 제안을 잠그는 PostgreSQL 트랜잭션 안에서 내려집니다. 따라서 두 번째 요청은 이미 예약된 상태를 다시 읽게 됩니다.

시각은 잠금을 얻은 뒤에 검증합니다. 트랜잭션을 기다리는 동안 시작 시각이 지나버린 활동에 참여할 수 있어서는 안 됩니다.

생성 역시 네트워크 재시도를 처리합니다. 각 요청은 그 반복을 알아볼 수 있는 키를 지닙니다. 첫 생성이 성공했지만 응답이 유실되었다면, 새로운 시도는 같은 제안을 다시 찾아냅니다. 두 번째 활동을 게시하지 않습니다. 이 동작은 실제 PostgreSQL 데이터베이스에서 동시 트랜잭션으로 테스트합니다.

원할 때 주변 검색하기

앱은 React Native와 Expo를 사용하며, 네이티브 지도가 진입점입니다. 사용자는 영역, 검색 반경, 시간과 소요 시간 조건을 고릅니다. PostGIS가 서버 쪽에서 지리 검색을 수행하며, 거리는 미터 단위로 표현됩니다.

위치 정보는 명시적인 동작으로 요청됩니다. 영역을 수동으로 고를 수도 있습니다. 지도를 움직인다고 해서 매번 새로운 요청이 발생하지는 않습니다. 사용자가 표시된 영역에서 검색을 확인합니다. 이 흐름은 백그라운드에서 사용자의 이동을 추적할 필요가 없습니다.

API가 기밀성을 강제하게 하기

로그인은 전화번호와 인증 코드에 기반합니다. 흐름은 다른 참가자에게 보여줄 사진, 자기소개, 실명을 요구하지 않습니다. 그렇다고 서비스가 익명이 되는 것은 아닙니다. 계정과 참여 데이터는 서비스 운영에 여전히 필요합니다.

현장에서 각자는 그 순간의 표식, 예를 들어 "노란 배낭"을 입력할 수 있습니다. 두 표식은 두 사람 모두 도착을 신고한 뒤에 공개됩니다. 이 규칙은 서버 응답에서 적용됩니다. 화면에서 필드를 가리는 것만으로는 충분하지 않기 때문입니다. 활동 목록에는 이 정보가 들어 있지 않습니다.

세션은 폐기할 수 있으며, 토큰은 데이터베이스에 해시 형태로 보관됩니다. 모바일 쪽에서는 비동기 응답이 그것을 요청한 세션에 묶입니다. 계정을 바꾼 뒤에 오래된 요청이 데이터를 다시 표시해서는 안 됩니다.

구축 단계부터 운영을 준비하기

지원 팀은 모바일 앱과 분리된 내부 인터페이스를 갖습니다. 별도의 서버, 별도의 인증, 전용 SQL 역할을 사용합니다. 요청은 추적, 배정, 해결될 수 있고, 사용자가 추가 정보를 제공하면 다시 열 수 있습니다.

민감한 조치는 이력으로 남깁니다. 사건 기록의 버전 덕분에 오래된 수정, 예를 들어 두 담당자가 같은 건을 다룰 때의 수정을 감지할 수 있습니다. 네트워크 단절 뒤의 재시도도 함께 고려됩니다.

개발은 완결된 기능 단위로 진행됩니다. 업무 규칙, API, 영속성, 인터페이스, 그리고 흐름 검증입니다. 단위 테스트는 결정을 다루고, 통합 테스트는 데이터베이스 제약을 검증하며, 인터페이스 테스트는 오류, 재시도, 연결 해제를 시험합니다. 모의 공급자를 사용하는 시나리오는 실제 서비스와 기기에서의 테스트와 구분해 둡니다.

남은 것

프로젝트에는 구현된 생성 및 참여 흐름, 지리 검색, 테스트 가능한 기밀성 규칙, 지원 도구가 있습니다. 이후 개발은 특히 알림, 외부 연동의 검증, 실제 기기에서의 흐름 검증, 그리고 모바일 배포 전 인터페이스 다듬기에 집중합니다.

제품 소개 사이트는 이미 공개되어 있습니다. 유럽연합의 24개 공식 언어로 정적 HTML로 생성됩니다. 사이트의 애니메이션은 두 대의 전화기를 동기화해 흐름을 설명합니다. 이는 제품의 표현이지 네이티브 앱의 화면 캡처가 아닙니다. 사이트는 광고 추적기나 방문자 쪽 분석 도구 없이 동작합니다.

이 글을 쓰는 시점에 모바일 앱은 아직 개발 중입니다. 따라서 대규모 사용이나 배포 결과는 아직 제시하지 않습니다. 이 작업은 더 당면한 요구를 기록합니다. 사용자에게는 단순한 동작을 만들되, 그 규칙을 네트워크, 시계, 인터페이스의 우연에 맡기지 않는 것입니다.

기술 요약

사용 기술: TypeScript, React Native, Expo, Fastify, PostgreSQL, PostGIS, 관리 도구에는 React와 Vite, Vitest와 Docker. 정적 사이트는 HTML, CSS, JavaScript로 구성하며, Node.js로 생성하고 Railway에 호스팅합니다.

범위: 제품 설계, 아키텍처, 모바일 및 서버 개발, 관리 도구, 테스트, 다국어 사이트.

상태: Scopes 제품, 2026년 모바일 앱 개발 중. 제품명은 이 글에서 밝히지 않으며, 요청 시 공유합니다.

네트워크에 의존해서는 안 되는 업무 규칙을 가진 모바일 앱을 준비하고 계십니까? Scopes는 몽펠리에에서 iOS와 Android 앱을 설계하고 개발합니다. 몽펠리에 모바일 개발 페이지를 보시거나 상황을 알려 주십시오.