픽닥 병원 추천 서비스 앱

프로젝트 유형
앱서비스
날짜
2023년 2Q
역할
앱 프론트 개발 및 API연동 작업, SNS로그인 연동, 모바일 사용자 결제 시스템 연동으로 해외 결제 기능 추가
기술스택
Flutter, GetX
프리미엄 의료 서비스를 위한 모바일 앱 앱 프론트 개발1. 프로젝트 개요PickDoc은 대한민국 의료 관광 플랫폼으로, 해외 환자와 국내 병원/의사를 연결하는 모바일 애플리케이션이다.한국어, 영어, 중국어(간체) 3개 언어를 지원하며, 글로벌 시장을 대상으로 진료 예약, 실시간 상담,결제, 회복 관리까지 의료 관광의 전 과정을 통합 제공한다.핵심 가치:- 다국어 기반의 글로벌 의료 관광 접근성 제공- 실시간 상담 채팅을 통한 환자-병원 간 원활한 소통- 예약부터 결제, 회복 추적까지 원스톱 의료 관광 프로세스- 6종 소셜 로그인 지원으로 글로벌 사용자의 간편한 접근2. 시스템 구성본 프로젝트는 단일 모바일 클라이언트 앱으로 구성되며, Android 및 iOS 플랫폼을 지원한다.2.1 모바일 클라이언트 앱역할: 해외 환자용 의료 관광 서비스 앱기술: Flutter 크로스 플랫폼 프레임워크언어: Dart규모 지표:- API 엔드포인트 수: 115개 (19개 API 클래스)- 화면(라우트) 수: 60개 (활성 라우트 기준)- 화면 컨트롤러-페이지 쌍: 53개- 데이터 모델 수: 203개 (서버 연동 모델) + 12개 (앱 레이어 모델)- 재사용 위젯 컴포넌트: 27개- 다국어 번역 키: 392개 (3개 언어)- 디자인 스타일 정의 파일: 14개3. 핵심 기술 스택3.1 모바일 프레임워크Flutter - 크로스 플랫폼 모바일 앱 프레임워크 (Android/iOS)Dart - 애플리케이션 개발 언어GetX - 상태 관리, 라우팅, 의존성 주입, 다국어 처리 통합 프레임워크3.2 서버 연동Swagger Codegen - OpenAPI 스펙 기반 API 클라이언트 코드 자동 생성HTTP - RESTful API 통신DDP (Distributed Data Protocol) - 실시간 채팅 WebSocket 통신3.3 인증 및 소셜 로그인OAuth 2.0 - 소셜 로그인 인증 프로토콜JWT (JSON Web Token) - 액세스 토큰 및 리프레시 토큰 기반 인증WebView 기반 OAuth - Google, Naver 소셜 로그인 처리Apple Sign-In - Apple ID 기반 인증WeChat SDK (fluwx) - WeChat 로그인 연동3.4 Firebase 서비스Firebase Cloud Messaging (FCM) - 푸시 알림Firebase Dynamic Links - 딥링크 및 공유 링크Firebase Analytics - 사용자 행동 분석3.5 결제Eximbay - 해외 환자 대상 국제 결제 게이트웨이WebView 기반 결제 - 인앱 결제 처리3.6 실시간 통신Rocket.Chat - 실시간 상담 채팅 서버dart_meteor - Meteor/Rocket.Chat DDP 클라이언트3.7 이미지 처리extended_image - 네트워크 이미지 로딩, 메모리/디스크 캐싱, 에러 핸들링multi_image_picker - 다중 이미지 선택image_downloader - 이미지 디바이스 저장3.8 로컬 저장소SharedPreferences - 인증 토큰, 사용자 설정, 로케일 등 경량 데이터 영속화LocalStorage - API 응답 캐싱3.9 기타Google Cloud Translation API - 사용자 생성 콘텐츠 실시간 번역flutter_svg - SVG 벡터 이미지 렌더링intl - 날짜 포매팅 및 로케일 유틸리티uni_links - 유니버설 링크 및 인텐트 처리loggy - 구조화된 로깅4. 핵심 기능4.1 비즈니스 기능4.1.1 병원/의사/시술 검색- 카테고리별 검색 (성형, 피부, 치과, 여성의원, 한의원)- 키워드 기반 통합 검색 (병원, 의사, 시술)- 추천 시술 목록 제공- 인기 검색어 제공- 병원/의사/시술 상세 정보 조회- 의사 목록 및 시술 목록 조회4.1.2 즐겨찾기- 병원, 의사, 시술 별 즐겨찾기 등록/해제- 즐겨찾기 목록 조회 (병원/의사/시술 각각)- 즐겨찾기 상태 실시간 확인4.1.3 진료 예약- 시술 선택, 날짜 선택, 환자 정보 입력의 단계별 예약 프로세스- 예약 상세 조회 및 목록 관리- 예약 취소 (취소 수수료 정책 적용: 당일 전액, 1일 전 50%, 2일 전 이상 무료)- 예약 상태 변경 추적4.1.4 결제 시스템- Eximbay 국제 결제 게이트웨이 연동- 인앱 WebView 기반 결제 처리- 결제 완료 및 검증 프로세스- 전액 환불 및 부분 환불 지원- 개발 환경 결제 우회 기능 (테스트 지원)4.1.5 실시간 상담 채팅- Rocket.Chat 기반 실시간 채팅- WebSocket(DDP 프로토콜) 기반 메시지 송수신- 텍스트 메시지 및 이미지 파일 전송 지원- 채팅방 생성, 조회, 종료 관리- 메시지 이력 조회4.1.6 일정 및 회복 관리- 진료 일정 캘린더 관리- 회복 기록 작성, 수정, 삭제- 회복 시술 등록 및 관리- 대표 회복 기록 설정- 병원/의사/시술 검색 연동 일정 추가4.1.7 리뷰 시스템- 시술 리뷰 작성 및 조회- 리뷰 상세 조회- 리뷰 삭제- 리뷰 신고 기능- 작성 가능 여부 확인- 사용자별 리뷰 목록 조회4.1.8 홈 화면 콘텐츠- 오늘의 Pick, 베스트 시술, 오늘의 의사, 파트너 병원 등 큐레이션 콘텐츠- 카테고리별 홈 콘텐츠 제공- 카로셀 슬라이더 기반 배너4.1.9 마이페이지- 프로필 편집 (연락처 변경, 이메일 인증)- 비밀번호 변경 및 비밀번호 변경 알림 연기- 알림 설정 (상담 푸시 알림 ON/OFF)- 즐겨찾기 목록 조회- 작성 리뷰 목록 조회- 공지사항, 고객 서비스, 파트너십, 이용약관, 개인정보처리방침 (WebView)- 언어 변경- 회원 탈퇴4.2 기술 기능4.2.1 다국어 지원 (i18n)- 한국어, 영어, 중국어(간체) 3개 언어 지원- 392개 번역 키 기반 앱 전역 다국어 처리- 런타임 언어 변경 및 영속화- Google Cloud Translation API 기반 사용자 생성 콘텐츠 실시간 번역- 160개 이상 국가의 전화번호 국가코드 지원 (한국어/영어 이중 표기)4.2.2 푸시 알림- FCM 기반 푸시 알림 수신- 앱 포그라운드/백그라운드/종료 상태별 분기 처리- 로컬 알림 채널을 통한 포그라운드 알림 표시- 알림 탭 시 해당 상담 화면으로 딥링크 네비게이션- 동일 채팅방 재방문 시 알림 억제 로직- FCM 토큰 자동 갱신 및 서버 동기화4.2.3 딥링크 및 공유- Firebase Dynamic Links 기반 딥링크 수신 및 라우팅- 병원, 의사, 시술 상세 페이지로의 딥링크 연결- 공유용 단축 링크 생성 (소셜 메타 태그 포함)- 앱 종료 상태에서의 초기 딥링크 처리4.2.4 API 응답 캐싱- LocalStorage 기반 HTTP 응답 캐싱- 요청 파라미터 기반 고유 캐시 키 생성- 선택적 캐싱 (상세 페이지 등 특정 API에만 적용)- 앱 시작 시 만료 캐시 자동 정리4.2.5 네트워크 이미지 최적화- 메모리 캐시 및 디스크 캐시 이중 캐싱- 로딩 중 플레이스홀더 이미지 표시- 로딩 실패 시 대체 이미지 표시- 자동 재시도 (3회, 100ms 간격)5. 아키텍처 설계5.1 전체 아키텍처GetX 프레임워크 기반의 MVVM 유사 패턴을 채택하였다.모든 화면은 Controller(비즈니스 로직)와 Page(UI 표현)로 분리되어 있으며,반응형 상태 관리를 통해 데이터 변경이 UI에 자동 반영된다.5.2 화면 구조 (Controller + Page 패턴)모든 화면은 아래의 일관된 구조를 따른다:- Controller (GetxController): 비즈니스 로직, API 호출, 상태 관리 (.obs 반응형 변수)- Page (StatelessWidget): UI 렌더링만 담당, Get.find()로 Controller 참조총 53개의 화면이 이 패턴으로 구현되어 있으며,모든 Controller는 라우트 등록 시 BindingsBuilder를 통해 의존성 주입된다.5.3 라우팅 설계GetX 네임드 라우트 기반으로 63개의 라우트 상수가 정의되어 있다.각 라우트는 GetPage 엔트리로 등록되며, 페이지 위젯과 바인딩을 함께 선언한다.네비게이션 인자는 별도 상수 클래스를 통해 키 이름을 중앙 관리한다.5.4 하단 네비게이션 구조앱의 메인 화면은 5개 탭(홈, 검색, 일정, 상담, 마이)으로 구성된다.탭 전환은 라우팅이 아닌 인덱스 기반 위젯 교체 방식으로 동작하며,일정 및 상담 탭은 로그인 필수로 미인증 시 로그인 화면으로 리다이렉트한다.5.5 API 계층 구조Swagger Codegen으로 자동 생성된 API 클라이언트를 기반으로 하며,19개의 도메인별 API 클래스가 115개의 엔드포인트를 제공한다.203개의 서버 연동 모델이 요청/응답 데이터 직렬화를 처리한다.자동 생성 코드는 프로젝트 요구사항에 맞게 수동 적용 규칙을 거쳐 통합되어 있다:- 모든 속성 및 함수 인자의 nullable 처리- DateTime을 String으로 치환하여 유연한 날짜 처리- 응답 역직렬화 시 바이트 배열 기반 처리- 선택적 API 응답 캐싱 지원5.6 중앙 집중식 API 호출 패턴모든 API 호출은 safeApi() 래퍼 함수를 통해 실행된다.이 함수는 아래 에러 유형을 자동으로 처리한다:- 인증 만료 (401): 토큰 자동 갱신 후 원래 요청 재시도- 서버 오류 (500): 서비스 오류 페이지로 이동- 네트워크 오류: 네트워크 오류 페이지로 이동, 사용자 재시도 시 원래 요청 재실행또한 현재 로케일 정보를 자동으로 API 요청에 주입하여 서버 측 다국어 응답을 지원한다.5.7 확장 함수 기반 DSLKotlin 스타일의 확장 함수를 광범위하게 활용하여 선언적 UI 구성을 지원한다:- 스코프 함수: let(), also(), takeIf(), takeUnless()- 위젯 래퍼: wrapContainer(), wrapInkWell(), wrapColumn(), wrapRow() 등- 텍스트 스타일 체이닝: .bold, .medium, .fontSize(), .colors()- 간격 헬퍼: 숫자.width, 숫자.height (SizedBox 단축)- 컬렉션 유틸: mapNotNull(), sortedBy(), unique()이를 통해 중첩 생성자 대신 빌더 패턴과 유사한 가독성 높은 UI 코드를 작성한다.5.8 상태 관리GetX의 반응형 상태 관리를 사용한다.Controller 내에서 .obs로 선언된 변수는 UI에서 Obx() 위젯을 통해 자동 갱신된다.전역 텍스트 스케일 팩터를 1.0으로 고정하여 시스템 글꼴 크기 변경에 의한레이아웃 깨짐을 방지한다.6. 인증 및 보안 아키텍처6.1 인증 방식JWT 기반 액세스 토큰/리프레시 토큰 이중 인증 체계를 사용한다.지원하는 로그인 방식:- 이메일/비밀번호 로그인 (8~33자 비밀번호 검증, 이메일 정규식 검증)- Google OAuth 로그인 (서버 사이드 OAuth, WebView 기반)- Naver OAuth 로그인 (서버 사이드 OAuth, WebView 기반)- Apple Sign-In (Apple ID 인증, WebView 기반)- WeChat 로그인 (WeChat SDK 네이티브 연동)- Kakao 로그인 (구현 완료, 현재 비활성 상태)6.2 토큰 관리- 로그인 성공 시 액세스 토큰과 리프레시 토큰을 로컬에 안전하게 저장- API 호출 시 Bearer 토큰 자동 주입- 401 응답 수신 시 리프레시 토큰으로 자동 갱신 후 원래 요청 재시도- 토큰 갱신 실패 시 로그아웃 처리6.3 소셜 로그인 흐름소셜 로그인 완료 후 서버에서 반환하는 등록 상태에 따라 분기 처리:- REGISTERED: 기존 회원, 즉시 로그인 완료- NOT_REGISTERED: 신규 회원, 이용약관 동의 화면으로 이동- ALREADY_REGISTERED_EMAIL: 동일 이메일로 기존 가입, 안내 메시지 표시6.4 회원 가입- 이메일 중복 확인- 이메일 인증번호 발급 및 검증- 이용약관 동의 (필수/선택 분리)- 상세 정보 입력 (연락처, 국가 등)6.5 비밀번호 관리- 비밀번호 찾기: 이메일 인증 후 비밀번호 재설정- 비밀번호 변경: 마이페이지에서 현재 비밀번호 확인 후 변경- 비밀번호 변경 알림 연기 기능6.6 민감 정보 보호- 안드로이드 키스토어 및 서명 설정 파일은 GPG 암호화하여 저장소에 보관- GPG 공개키 기반의 접근 권한 관리7. 데이터 관리7.1 로컬 데이터 영속화SharedPreferences를 통해 아래 데이터를 영속적으로 관리한다:- 인증 토큰 (액세스 토큰, 리프레시 토큰)- FCM 푸시 토큰- 로그인 방식 (이메일/소셜 구분)- 사용자 로케일 설정- 예약 준비 상태 (만료 시간 기반 자동 폐기)- 임시 예약 정보7.2 API 응답 캐싱LocalStorage 기반의 HTTP 응답 캐싱 시스템을 구현하였다.- 요청 경로, 쿼리 파라미터, 폼 파라미터, 인증 정보를 조합한 고유 캐시 키 생성- 캐시 적중 시 네트워크 요청 없이 즉시 응답 반환- 병원, 의사, 시술 상세 조회 등 자주 접근하는 API에 선택적으로 적용- 앱 시작 시 유효하지 않은 캐시 엔트리 자동 정리7.3 이미지 캐싱extended_image 라이브러리를 통해 이중 캐싱 전략을 적용한다:- 메모리 캐시: 앱 실행 중 빠른 이미지 접근- 디스크 캐시: 앱 재시작 후에도 캐시 유지- URL 기반 고유 캐시 키 생성7.4 파일 관리- 채팅 이미지 업로드: 디바이스 갤러리에서 선택한 이미지를 임시 파일로 변환 후 서버 업로드- 채팅 이미지 다운로드: 수신된 이미지를 디바이스 갤러리에 저장- 프리사인드 URL: 서버에서 발급받은 임시 URL을 통한 안전한 파일 업로드8. 테스트 전략단위 테스트와 위젯 테스트를 지원하며, Flutter 표준 테스트 프레임워크를 사용한다.API 연동 테스트를 위한 Mock 데이터가 상담, 홈, 마이페이지, 검색, 일정 등주요 도메인별로 준비되어 있다.테스트 실행:- flutter test: 전체 테스트 실행- flutter analyze: 정적 분석9. 배포 환경9.1 환경 분리빌드 타임 환경 변수(dart-define)를 통해 개발/운영 환경을 분리한다:- dev (개발): 개발 서버 연동, 결제 우회 테스트 버튼 활성화- prod (운영): 운영 서버 연동, 결제 우회 불가환경 설정값은 앱 초기화 시 싱글톤 객체로 로드되어 앱 전역에서 참조된다.9.2 빌드 방식- Android App Bundle (AAB): Google Play Store 배포용- Android APK: arm64 아키텍처 대상 직접 배포용- iOS IPA: App Store 배포용Android 빌드 시 dart-define 값은 Base64 인코딩되어 네이티브 Gradle 빌드에 전달되며,릴리스 빌드 시 GPG 복호화된 키스토어 파일로 앱 서명을 수행한다.9.3 코드 생성- json_serializable + build_runner: VO 클래스의 JSON 직렬화 코드 자동 생성- Swagger Codegen: OpenAPI 스펙으로부터 API 클라이언트 코드 생성- 에셋 경로 상수: 자동 생성된 Assets 클래스를 통해 타입 안전한 에셋 참조10. 기술적 우수성10.1 아키텍처 강점- Controller + Page 분리 패턴의 일관된 적용으로 53개 화면 전체가 동일한 구조를 유지하여높은 코드 일관성과 유지보수성을 확보하였다- safeApi() 중앙 집중식 에러 핸들링을 통해 인증 갱신, 서버 오류, 네트워크 오류 처리를한 곳에서 관리하여 개별 화면의 에러 처리 부담을 제거하였다- Swagger Codegen 기반의 API 클라이언트 자동 생성과 체계적인 수동 적용 규칙을 통해서버 API 변경에 신속하게 대응할 수 있는 구조를 갖추었다10.2 개발 생산성- Kotlin 스타일 확장 함수 DSL을 통해 Flutter 위젯의 중첩 구조를 평탄화하여코드 가독성과 작성 속도를 향상시켰다- GetX 프레임워크의 통합 기능(상태 관리, 라우팅, DI, 다국어)을 활용하여별도 라이브러리 간 연동 복잡성을 최소화하였다- 개발 환경에서의 결제 우회 기능으로 결제 관련 기능의 빠른 개발 및 테스트를 지원한다10.3 확장성- 19개의 도메인별 API 클래스 분리로 기능 단위의 독립적 확장이 가능하다- 재사용 위젯 컴포넌트(27개)와 도메인별 스타일 정의(14개)를 통해새로운 화면 추가 시 일관된 디자인 적용이 용이하다- 다국어 키 기반 번역 시스템으로 신규 언어 추가 시 번역 맵만 확장하면 된다- 소셜 로그인 아키텍처가 WebView 기반의 서버 사이드 OAuth로 통일되어 있어신규 소셜 로그인 추가가 용이하다10.4 사용자 경험- 실시간 WebSocket 채팅으로 지연 없는 상담 경험 제공- 이미지 이중 캐싱(메모리 + 디스크)과 자동 재시도로 원활한 이미지 로딩- FCM 푸시 알림의 상태별 분기 처리로 앱 사용 중에도 적절한 알림 제공(동일 채팅방에서는 알림 억제)- Firebase Dynamic Links를 통한 외부 공유 시 원클릭 앱 진입- 캘린더 기반 일정 관리와 회복 기록 추적으로 진료 전후 관리 지원- 시스템 글꼴 크기 변경에 영향받지 않는 일관된 레이아웃 유지
픽닥픽닥픽닥_검색화면픽닥_나의예약픽닥_카테고리별픽닥