
1.인증/인가
- 카카오 소셜 로그인
- 로그아웃
- 회원탈퇴
2.가이드 영상 시청
- 영상 배속 설정
- 영상 볼륨 조절
3.피드백 영상 녹화
- 촬영 기능
- 사이드/오버레이 버전
- 투명도 조절
- 미러 모드
- 전/후면 모드 설정
4.가이드 영상 업로드
- 영상 장르 선택
- 영상 하이라이트 구간 설정
5.마이페이지
- 홈화면
- 피드백 영상 탭
- 숏츠 탭
- 랭킹 및 개인정보 표시
6. 피드백 영상 확인
- 디테일 피드백 영상 구현
- 틀린 구간, 하이라이트 구간 표시
7. 숏폼 영상 생성
- 영상 편집
- 영상 공유
REACT pwa로 개발하여 모바일 환경에서도 춤을 쉽게 배우고, 촬영하고, 편집까지하는 앱을 만들도록 기능을 구현하였다.
필자는,
인증, 인가 / 가이드 영상 시청 / 피드백 생성 / 마이페이지 / CSS 총괄의 기능을 담당하여서 개발을 하였으며, REACT와 three.js를 이용하여 개발하였다.
해당 프로젝트는 초반에 ReactNative를 이용하여 개발하였는데, 동영상 편집 및 촬영부분에서 너무 많은 제약이 있다보니 react pwa로 개발하게 되었다. ios와 안드로이드 두 환경이 상이하다는 것을 앞선 개발을 통해 느끼게 되었고, 특히 ios는 촬영 관련해서 규약이 정말 많다는것을 느꼈다. 예를 들어, 영상 촬영과 같은 경우 ios에서 보안 정책으로 인해서 촬영을 막아두어서 우회해서 라이브러리를 이용해서 구현을 했다. 또, 숏폼 공유와 같은 경우나 css도 두 환경이 많이 상이해서 개발할때 힘들었다...
모바일 앱 개발은 학부 때, react native로 한번 개발해보고 말았어서, 쉽게 봤다가 큰 코 다친 셈이다..
다음에 제대로 공부해봐서, react native로 프로젝트를 한번 진행해보고싶다.
어찌됐든, 개발을 맡았던 기능에 대해서 조금 자세히 적어보고자 한다.
1.인증/인가
- 카카오 소셜 로그인
- 로그아웃
- 회원탈퇴


React Native와 Expo를 사용하여 카카오 로그인을 구현할 때, 가장 큰 차이점은 모바일 환경의 특성과 리다이렉트 URL 설정 방식이다. 특히, React Native에서는 Expo를 사용하기 때문에 웹에서처럼 고정된 URL을 사용하지 않는데, 카카오는 리다이렉트 url 설정을 해서, 코드를 받아서 그 코드를 백엔드쪽에 api로 쏴줘서 로그인 완료를 하는 식의 구현을 하기 때문이다... Expo에서는 Redirect URI를 설정하는 데 있어 고유한 방식이 필요했다.
Expo와 WebView 사용: 그렇게 최종적으로 React Native에서는 Expo와 WebView를 사용하여 카카오 로그인 페이지를 띄우고, OAuth 인증 코드를 받아오는 방식으로 구현하였다.
리다이렉트 URL 설정: Expo 앱에서는 웹과 달리 고정된 URL이 없기 때문에, Redirect URI를 https://auth.expo.io/@your-username/your-app-slug와 같이 Expo의 고유한 URL 형식을 사용하여 설정하였다.
AsyncStorage 활용: 로그인 후 받은 토큰을 저장할 때 AsyncStorage를 사용하여 로컬에 저장한 것도 다른점 중 하나.
React PWA에서는 웹 기술을 활용하여 보다 간단하게 카카오 로그인을 구현할 수 있다.
PWA에서는 OAuth URL을 통해 카카오 로그인 페이지로 리디렉션하고, 인증 코드가 포함된 URL을 받아 처리하는 방식으로 구현한다.
쿠키 사용: 로그인 후 받은 토큰을 쿠키에 저장하여 관리 하였다.
RN에서 또 expo환경을 사용하여 개발하였기 때문에 굉장히 열심히 구글링 해서 구현하였던 기억이 있다.
2.가이드 영상 시청
- 영상 배속 설정
- 영상 볼륨 조절
해당 기능을 구현하기 위해서 ReactPlayer라는 영상을 재생하기 위한 라이브러리를 통해 구현하였다.
근데 이 라이브러리 단점이,, 긴 영상 렌더링을 한번에 읽는 데 시간이 걸린 다는 점이었다. 특히, 영상이 서버에서 스트리밍되는 경우 초기 버퍼링과 메타데이터 로드 시간이 필요했다. 그래서 커스텀 하는 것 이외에는 별로 좋지 않았어서 이후에 코드를 조금 수정하였다.
어쨋든 해당 기능에서
영상 재생/일시정지: 영상 재생과 일시정지 기능을 제공합니다.
볼륨 조절: 사용자가 볼륨을 조절할 수 있는 기능을 제공합니다.
배속 설정: 사용자가 배속을 설정할 수 있는 기능을 제공합니다.
영상 정보 표시: 영상의 제목, 가수, 생성일 등의 정보를 표시합니다.
뒤로 가기 버튼: 이전 페이지로 이동할 수 있는 버튼을 제공합니다.
영상 끝났을 때 동작: 영상이 끝났을 때 재생 상태를 관리합니다.

3.피드백 영상 녹화
- 촬영 기능
- 사이드/오버레이 버전
- 투명도 조절
- 미러 모드
- 전/후면 모드 설정
두 가지 모드, 사이드(Side-by-Side)와 오버레이(Overlay)를 제공하는데, 사이드 모드에서는 비디오 플레이어와 웹캠 피드를 나란히 배치하고
오버레이 모드에서는 비디오 플레이어 위에 웹캠 피드를 오버레이한다.
슬라이더를 사용하여 비디오 플레이어의 투명도를 조절할 수 있으며,
슬라이더 값에 따라 비디오 플레이어의 opacity 스타일을 동적으로 변경하도록 하였다.
버튼을 클릭하여 웹캠 피드를 좌우 반전(mirror)할 수 있다.
버튼을 클릭하여 전면 카메라와 후면 카메라를 전환할 수 있다.

4.가이드 영상 업로드
- 영상 장르 선택
- 영상 하이라이트 구간 설정
useState를 사용하여 업로드할 비디오, 제목, 가수 이름, 장르 선택 등의 상태를 관리하도록 하였다.
css를 특이한 라디오 버튼을 가져와서 조금 수정해서 구현했는데, 만족스럽다 ㅎㅎ..
사용자가 비디오 파일을 선택하면 changeHandler 함수가 호출되어 비디오 파일을 상태로 저장하고, FileReader를 사용하여 비디오의 URL을 설정한다.
videoRef를 통해 비디오 요소를 참조하여 메타데이터가 로드되면, 비디오의 전체 길이를 videoDuration 상태로 저장한다.
Timeline 컴포넌트를 사용하여 하이라이트 구간을 설정할 수 있도록 하였다. 이때, 사용자가 하이라이트 구간을 설정하면 handleHighlightChange 함수가 호출되어 하이라이트 구간을 상태로 저장한다.
5.마이페이지
- 홈화면
- 피드백 영상 탭
- 숏츠 탭
- 랭킹 및 개인정보 표시

getUserDatas API 호출: 컴포넌트가 마운트될 때 사용자 데이터를 가져온다. 이 데이터에는 사용자 프로필, 피드백 리스트, 쇼츠 리스트가 포함된다.
이때, 최신 5개의 데이터 로드를 통해 최신 5개의 피드백 영상 및 숏츠 데이터를 불러왔고, 이를 통해 초기 로딩 시간을 단축하고, 메모리 사용량을 감소시켰다.
페이징 기법: 더 많은 데이터를 로드하기 위해 페이징 기법을 사용하였다. '더 보기' 버튼을 통해 추가 데이터를 불러올 수 있다.
탭 네비게이션: 홈, 피드백, 쇼츠 탭을 제공하여 사용자가 쉽게 원하는 정보를 찾을 수 있도록 하였다. 그리고, 동적 포인터를 사용해 네비게이션 탭을 클릭할 때 포인터가 이동하여 현재 활성화된 탭을 시각적으로 표시했다.
6. 피드백 영상 확인
- 디테일 피드백 영상 구현
- 틀린 구간, 하이라이트 구간 표시
두 개의 비디오 플레이어(가이드 영상, 업로드된 영상)를 동기화하여 동시에 재생, 일시정지, 다시 재생할 수 있도록 하였다.
handlePlayPause 함수에서 재생 상태에 따라 비디오를 재생하거나 일시정지한다.
비디오의 현재 시간과 진행 상태를 handleProgress 함수에서 업데이트하고, 틀린 구간에 따라 스타일을 동적으로 변경했다.
위 두가지 정도에 염두를 두고 페이지를 구현하였다.

마지막 프로젝트였다보니, 이전 프로젝트에 비해서 질적으로나 양적으로나 뭔가 개선된 프로젝트를 하고 싶었고 초반에 욕심을 갖고 프로젝트를 시작했다.
그러나 프로젝트 초반에 예상치 못한 어려움이 있었다. 백엔드 팀원 두 분이 중도에 싸탈하게 되면서 팀의 사기가 조금 저하되었던것 같고, 프로젝트의 진행에 어려움을 겪게 되었었다. 그럼에도 모두들 프로젝트에 몰두해 서로 격려하며 프로젝트를 지속해 나갈 수 있었다.
그 결과, 여러 가지 기능들을 성공적으로 구현할 수 있었던 것 같다. 비록, 초기 계획했던 RN이나 tensorflow를 사용한 기능은 구현하지 못했지만 가이드 영상 업로드, 피드백 영상 녹화, 마이페이지 관리 등 다양한 기능을 포함한 플랫폼을 완성했다. 이러한 성과는 팀원들의 노력과 협력 덕분에 가능했던 것 같다.
어쨋든, 모두들 노력해서 이런 성과 만들어낼 수 있었어서 좋았고, 싸피 외 앞으로의 프로젝트에서도 앞선 세개의 프로젝트들을 통해 더욱 개선된 프로젝트를 만들 수 있을것 같다.
끝!