2023년 7월 ~ 12월 동안 진행되었던 모바일 어플리케이션 팀 프로젝트 회고입니다.
💡 Project Info프로젝트명: KnockKnock
팀명: 4-Others
기간: 5월 21일 ~ 7월 말 (약 2개월)
플랫폼: iOS / Android (React Native)
한 줄 소개: 실사용이 가능한 개인화된 일정 관리 앱 (To-Do List 개선 프로젝트)
1. 기획 및 초기 세팅
화면 기획서

📅 기획 배경
기존의 To-Do List 프로젝트는 미완성 상태로 배포조차 되지 않은 상황이었다. 우리 팀(4-Others)은 이를 개선하여 실제 마켓에 배포 가능한 수준의 앱으로 발전시키기로 결정했다.
🛠 기술 스택 선정: React Native CLI
Expo 대신 React Native CLI를 선택했다. 초기 세팅이 까다롭지만 다음과 같은 확실한 이점이 있었다.
⚙️ 환경 설정 (Troubleshooting)
프로젝트 시작부터 환경 설정 오류와 맞서 싸워야 했다. 특히 Mac 환경에서의 의존성 관리가 핵심이었다.
sudo gem install cocoapods → pod setup$ npm install typescript @types/react @types/react-native --save-dev $ react-native init front
2. 핵심 기능 구현

Splash Screen을 활용한 자동 로그인
앱의 아이덴티티를 보여주면서 백그라운드에서 로그인 프로세스를 처리하는 방식을 택했다.
AsyncStorage에 Access/Refresh Token 저장 → 스플래시 화면 진입 시 토큰 유효성 검사 → 자동 로그인Code: authUtil.ts (AsyncStorage 모듈)
import AsyncStorage from '@react-native-async-storage/async-storage'; // 데이터 접근 const storageGetValue = async (key: string) => { try { const value = await AsyncStorage.getItem(key); return value !== null ? JSON.parse(value) : null; } catch (e: any) { console.log(e.message); return null; } }; // 데이터 저장 const storageSetValue = async (key: string, value: any) => { try { if (value !== null) { await AsyncStorage.setItem(key, JSON.stringify(value)); } } catch (e: any) { console.log(e.message); } }; // ...삭제 및 리셋 함수 포함
🤔 Retrospective간단한 방법이지만, 보안이 중요한 실무에서는
EncryptedStorage나 키체인 같은 더 보안성이 높은 저장소를 고려해야 할 것 같다.

회원가입 프로세스 리팩토링 (Stack → Tab)
Before (Stack Navigation)
초기에는 약관 동의 → 이메일 → 비밀번호 순의 단일 흐름이었다. 하지만 백엔드 API 구조상 '이메일+비밀번호'를 먼저 보내 인증번호를 받는 방식이 필요했고, Stack 방식으로는 데이터 유지와 컴포넌트 언마운트 관리가 까다로웠다.
After (Material Top Tabs)
Material Top Tabs를 활용해 회원가입 단계를 탭으로 구성하고, navigation.setParams를 통해 상위 레벨에서 입력 데이터를 관리하도록 구조를 변경했다.
// SignUpTab.tsx
const SignUpTab: React.FC<onLoginProps> = ({onLogin}) => {
// ...Progress Bar 로직 생략
return (
<SafeAreaView style={{flex: 1}}>
<Tab.Navigator tabBar={props => <></>}> {/* 탭 바 숨김 */}
<Tab.Screen name="SignAgree" component={SignAgree} />
<Tab.Screen name="SignPassword" component={SignPassword} />
<Tab.Screen name="SignEmail" component={SignEmail} />
{/* ... */}
</Tab.Navigator>
</SafeAreaView>
);
};
3. 소셜 로그인 (OAuth2) 도전과 실패, 그리고 해결

실패: React Native Webview
초기에는 웹 개발 방식처럼 Webview를 띄워 Redirect URL을 가로채는 방식을 시도했다.
성공: Firebase SDK
Google이 제공하는 모바일 SDK인 Firebase Authentication을 도입하여 해결했다.
google-services.json 등록 및 SHA1 키 설정GoogleService-Info.plist 설정
const socialLogin = async (providerType: 'GOOGLE' | 'KAKAO') => { try { if (providerType === 'GOOGLE') { const userInfo = await GoogleSignin.signIn(); // 백엔드에 ID Token 전달 postId(userInfo.user.id, providerType); } // ... Kakao 로직 } catch (error) { console.log('Login Failed', error); } };
4. 앱 배포 (Google Play Store)
개발만큼이나 복잡했던 배포 과정을 정리한다.
1. Package Name 변경
RN CLI로 프로젝트를 생성하면 기본 패키지명이 설정되는데, 배포 전 이를 고유한 이름으로 변경해야 한다. MainActivity.java, AndroidManifest.xml, build.gradle 등 여러 파일의 수정이 필요했다.
2. Keystore (서명 키) 생성
안드로이드 앱의 신원 증명을 위한 키 생성 작업.
keytool -genkey -v -keystore my-release-key.keystore -alias my-key-alias -keyalg RSA -keysize 2048 -validity 10000
3. 빌드 및 최적화
android/app/build.gradle에서 enableSeparateBuildPerCPUArchitecture와 enableProguardInReleaseBuilds를 true로 설정하여 용량을 최적화하고 난독화를 적용했다.
cd android && ./gradlew bundleReleasecd android && ./gradlew assembleRelease4. 스토어 등록 및 심사
마치며
이번 프로젝트를 통해 기획부터 개발, 그리고 스토어 배포를 위한 빌드 설정까지 앱 개발의 A to Z를 경험했다. 특히 백엔드 API 명세에 맞춰 프론트엔드 구조를 갈아엎었던 리팩토링 과정과, Webview 보안 이슈를 Firebase로 해결한 과정이 기억에 남는다.