배터리가 없다고?

정다빈·2024년 12월 5일
7
post-thumbnail

아래 화면들은 키즈노트 앱에서 모바일 웹뷰로 개발된 페이지들이에요. 각 화면의 버튼을 눌러보면 수많은 웹뷰 페이지들을 만날 수 있어요. 🏃🏻‍♀️

이처럼 앱에서 모바일 웹뷰 활용도가 점점 높아지고 있는데요, 이에 따라 FE개발파트는 리액트 네이티브 도입을 검토하고 있어요.

그러던 중, 스터디 쿨타임이 딱 끝난 어느 날! 저는 리액트 네이티브 스터디 수요 조사를 진행했어요.

초반 2주는 문서를 읽는 이론 기간, 이후 1개월은 프로젝트를 만드는 실습 기간으로 정했어요.
이론 기간이 길어지면 스터디가 지루해질 수 있기 때문에, 문서는 빠르게 훑어보고 프로젝트를 만드는 데 집중하기로 했어요.

이번 포스트에서는 실습 기간 동안 제가 어떤 프로젝트를 만들었는지 소개해 볼게요!

☘️ 어떤 앱을 만들었나요?

저는 쓸데없지만 재미있는 것을 좋아하는데요, 예전부터 관심 있게 본 Die With Me 앱이 생각나서 비슷한 앱을 만들기로 했어요.

Die With Me와 비슷하게 핸드폰 배터리가 5% 이하일 때만 입장 가능한 채팅 앱을 만들되, 컨셉은 트렌디하게 가져가면 좋을 것 같아서 2024년 최고의 밈(제가 방금 정함) 럭키비키 컨셉을 사용했어요.

배터리가 없다고? 채팅방에 입장할 수 있다니 완전 럭키비키잖아~ → 럭키 5%잖아~ → Lucky Oky
이런 흐름으로 앱 이름을 정해보았어요. 🙄

앱의 시그니처인 클로버를 앱 아이콘에 넣어주었고, 클로버의 초록색과 어울리는 노란색으로 전체적인 컬러톤을 잡아주었어요. 로고는 Modak 폰트를 사용해서 동글동글하고 귀여운 느낌을 내주었습니다.

메인 페이지로 진입하면 행운을 가져다줄 것만 같은 요정이 배터리 잔량을 알려주고 있어요. 🧚🏻‍♀️
배터리 잔량은 expo에서 제공하는 expo-battery 라이브러리를 사용해서 구할 수 있었어요. 다만 시뮬레이터 환경에서는 항상 -1을 반환하기 때문에 핸드폰 기기에서 테스트가 필요했어요.

import { getBatteryLevelAsync } from 'expo-battery';

const getBatteryLevel = async () => {
  const initialBatteryLevel = await getBatteryLevelAsync(); // '0.759999'
  const batteryLevel = +initialBatteryLevel.toFixed(2) * 100; // 76
};

로고 이외의 폰트는 요즘 잘 나간다는 Pretendard 폰트를 사용했어요.

<TextInput>에 닉네임을 입력하고 입장하기 버튼을 누르면 채팅방으로 입장할 수 있어요.
닉네임은 최소 1글자, 최대 10글자 이외의 유효성 검사는 하지 않는데요, 블리자드의 배틀태그처럼 최대한 자유로운 닉네임을 허용하고 싶었어요.

블리자드 게임에 존재하는 수많은 중복 닉네임들... 👖

하지만 채팅방에서 나의 채팅과 다른 사람의 채팅을 구분해야 하기 때문에 각 유저마다 유니크한 어떤 값이 필요했는데요, 다른 유저와 중복되지 않는 랜덤 아이디를 생성해서 Firestore에 유저 정보를 저장하도록 했어요. (더 좋은 방법이 있을 것 같은데 시간 관계상 이렇게... 😵)

만약 배터리가 5%를 초과하면 채팅방에 입장할 수 없어요.

여기에 쓸데없는 기능을 하나 추가해 보았는데요, 나만의 메꾸(메인 페이지 꾸미기)를 할 수 있도록 요소를 드래그하는 기능을 넣어주었어요. 드래그는 react-native-draggable 라이브러리를 사용해서 구현할 수 있었어요.

<Draggable x={280} y={160}> // 요소의 초기 위치 설정
  <Text>🍀</Text>
</Draggable>

채팅방에 입장하면 배터리가 없는 사람들과 채팅이 시작돼요.

중복 닉네임을 허용하기 때문에 입력한 닉네임 뒤에 랜덤 아이디가 붙어서 노출돼요. 비니#3641
핸드폰이 죽기 직전인 유저는 배터리 잔량을 빨간색으로 표시해 위기감을 더해주었어요. 🚨

채팅을 전송하면 Firestore에 저장하는데요, 이때 화면을 업데이트해야 하기 때문에 @react-native-firebase/firestore 라이브러리에서 제공하는 onSnapshot 메서드를 사용했어요. 이 메서드를 사용하면 데이터 변경 사항을 구독해서 화면을 실시간으로 업데이트할 수 있어요.

// firestore 변경 사항 구독
useEffect(() => {
  const subscriber = collection.onSnapshot((querySnapshot) => {
    const docs = [];

    querySnapshot.forEach((docSnapshot) => {
      const chat = docSnapshot.data();
      docs.push(chat);
    });

    const newDocs = docs.sort((a, b) => Date.parse(a.timestamp) - Date.parse(b.timestamp));

    setChats(newDocs);
  });

  return subscriber;
}, []);

핸드폰을 충전하면서 앱을 사용할 수도 있을 것 같아서, 1분마다 배터리 잔량을 확인하는 기능을 넣었어요.
배터리가 5%를 초과하면 알럿을 띄운 뒤 메인 페이지로 이동시키도록 했어요.

🧚🏻‍♀️ 마무리

리액트 네이티브로 첫 프로젝트를 진행해 보았는데요, 전체적으로 리액트와 유사하지만 페이지 라우팅은 Next.js App Router와 비슷하다고 생각했어요. 그리고 리액트 네이티브 생태계가 생각보다 좋아서 개발이 크게 어렵지는 않았던 것 같아요.

가장 어려웠던 부분은 Firestore 연동이었어요. 문서가 잘 정리되어 있긴 했지만, 앱 환경에서 익숙하지 않아 수많은 에러와 싸워야 했어요.

그래도 스터디를 통해 두 번째 앱을 만들게 되어 뿌듯하고, 재미있는 아이디어가 떠오르면 그때는 저만의 앱을 만들어 보고 싶습니다. 🥳

profile
Frontend Developer

4개의 댓글

comment-user-thumbnail
2024년 12월 5일

우와 참신한 앱이네요!! 🍀🍀

답글 달기
comment-user-thumbnail
2024년 12월 13일

아이디어가 너무 귀여워요!!!!!!! 좋은 포스팅 잘 보고갑니다👍

답글 달기
comment-user-thumbnail
2024년 12월 18일

아이디어 너무 좋아요!😀

답글 달기
comment-user-thumbnail
2024년 12월 18일

너무 귀여워요~~~ ios 출시해주세요

답글 달기