2023년 4월 16일
카테고리 : 회고록회고
조회 : 1060|6분 읽기
OA 회고 - 개발
기술 소개
기술들을 소개하면서 왜, 어디서 사용했는지 자세하게 작성
Next.js
이제 일반 react에서 route 설정하는 것 부터 api를 작성하는 것까지 너무 익숙해서 프로젝트를 시작한다면 무조건 Next!라는 생각에 Next를 베이스로 시작하게 되었다.
이번 프로젝트에서 장점
- config를 이용해서 key를 숨김
- route가 간단히 설정 가능함
- api를 작성해서 뒤에서 open ai api를 다시 설정하고 보내는 것이 가능했음
이번 프로젝트에서 단점
- 모바일과 같이 보이기 위해 페이지만 바뀌길 원했는데 route가 바뀌어 이상해짐 -> react-route-dom의 outlet을 사용하고 싶었지만 사용하지 못하게 됨
- local image가 next에서 제공하는 Image 태그를 사용하면 production에서 나오지 않았음 -> 결국 일반 image 태그를 사용함
Redux-Tool-Kit
Redux는 모르겠지만 RTK가 이제 상태관리 라이브러리 중에서 제일 사용하기 간단한 것 같았다.
간단한 프로젝트인데 상태관리까지 써야하나에 대한 생각이 지배되어 무거워질까봐 여러 군데에 localStorage를 사용했던 점이 조금 아쉬운 것 같다.
이번 프로젝트에서 장점
- 다양한 컴포넌트에서 dialog가 나오는 기능들이 많았는데 이름과 fn을 줘서 간단하게 처리할 수 있었다.
TailwindCSS
Next와 같이 최애 프레임워크 빠르고 간단하게 사용이 가능하고 css 파일을 따로 관리해주지 않아도 되는 점이 좋았다.
이번 프로젝트에서 장점
- 모바일 반응형에 대응이 쉬움
- 적은 코드로 CSS 작성 가능
이번 프로젝트에서 단점
- 애니메이션 적용이 어려웠음
Firebase
앱은 Firebase라고 생각해서 처음 이것을 사용하자 했었지만 생각보다 편리한 기능들이 많았다.
특히 auth에 대한 어드민 페이지가 있는 것이 내가 유저를 관리하는데 편리할 것 같다는 생각이 들었고 현재 유저에 대한 정보를 알려주고 익명을 제공하는 등 다양한 기능들이 있었다.
store는 미들웨어 구성할 필요 없이 제한을 거는 것이 가능했다.
이번 프로젝트에서 장점
- 현재 유저에 대한 정보가 바로 클라이언트에서 사용 가능
- 익명 로그인 기능
- 유저들의 정보 확인 가능
- transaction 등 db에 대한 기능들도 빵빵
- analistic으로 유저가 얼마나 사용하는지 확인 가능
이번 프로젝트에서 단점
- api 키를 env로 숨기고 또 nextconfig로 숨기다 보니 next api에서 기능을 사용할 수 없었다.
- 회원가입 후 이메일을 인증하는 기능이 있어서 추가하고 싶었지만 하루 2번을 넘어가면 과금이 필요했었다..
- 벡엔드를 따로 구성하지 않으니까 기능들을 생각하는데에 있어 조금 불편한 감이 있었다.
Flutter
처음 사용해보는 기술이었지만 초보자들도 빠르게 앱을 빌드할 수 있기도 하고 하이브리드이기 때문에 채용하게 되었다.
맨 처음에는 code push 기술이 있는 RN을 사용해보려고 했지만 다른 설정을 하면서 결국 막혔고 코드 푸시는 만능이 아니라는 것을 알게 된 후 flutter를 이용해 보기로 했다.
이번 프로젝트에서 장점
- 빠르게 WebView를 띄울 수 있었음
- 플러그인들이 다양해 스플러시 등 빠르게 구현 가능했음
- 진짜 쉽게 코드를 이해하고 빠르게 내게 필요한 것들을 구현할 수 있었음
- 코드 JIT 제공
이번 프로젝트에서 단점
- dart 문법이 생각보다 어려움
- WebView에 대한 플러그인이 너무 다양해서 고르기 어려웠음
- 결국 ios는 처음 선택한 WebView 플러그인 때문에 오류를 계속 내고 있음
- 무슨일인지는 모르겠는데 flutter run을 하면 애뮬레이터에 계속 apk에 대한 데이터가 쌓여서 애뮬레이터에서 저장공간이 다 찼다고 뭐라함
- WebView uri를 바꾸면 JIT가 먹히지 않아서 계속 앱을 껏다켜야했음
어려웠던 점과 해결
open ai api
제일 처음 난관에 만난 open ai
패널티에 대한 설정은 post를 보낼 때 property를 같이 설정해서 보낼 수 있지만 내 이름, ai 이름, 역할과 같은 것들은 ai에게 이야기를 하고 그것들을 계속 기억하고 있어야 했다.
open ai는 직전의 대화만 기억하고 나와 대화하는 전체적인 내용을 기억하며 대화를 이어나가는 것이 아니다.
따라서 이전의 대화를 계속 기억하기 위해서는 전의 대화를 계속 저장해놨다 post를 같이 보내는 것인데 이렇게 되면 token을 엄청나게 사용하게 되고 결국 한계치가 있어 어쨋든 대화가 끊기게 된다.
어떻게 하면 설정을 유지할 수 있는지 고민하다가 post를 보내는 body에 messages라는 속성이 있다는 것을 알게되고 거기에 적절한 role과 content를 사용해서 같이 보내는 방법을 생각하게 되었다.
하지만 role은 어떤식으로 설정하면 되는지 알게되었지만 content는 어떻게 작성해도 계속 이상하게 출력이 되었다.
나는 분명 "내 이름은 req.userName이고 너의 이름은 req.aiName이야"라고 보내도 자꾸 유저 이름을 ai이름으로 부르고 이상한 답변만 내놓았다.
이름은 별로 중요한 것도 아니지만 이런식이면 역할을 주는 것도 제대로 못하겠다고 생각했었고 여러 가지 문장을 집어 넣어보면서 실험을 계속했다.
유저 이름과 ai이름을 제대로 내놓게 하는데 하루가 걸렸다. 후에 역할을 이해시키는 것도 어려운 일이었다.
이름과 역할을 주고 이전 대화까지 같이 보내는 것으로 최대한 대화가 이어지고 적절한 대답을 내놓게 하는 prompt가 완성되었다.
WebView
안드로이드 개발자 인턴을 하면서 웹뷰에 대해서 듣기만 했지 실제로 사용은 못해보고 나오게 되었지만 어떤 것인지 대충 개념은 잡혀서 이것을 사용해 앱을 구성하기 했다.
처음에는 flutter를 이용해 webview를 구성하는 아주 간단한 앱이 될거라 생각했지만 처음 접하는 것을 바로 사용하려고 하니 생각보다 엄청 어려운 작업이었다.
WebView에 대한 플러그인을 찾고 적용하려고 보니 플러그인은 이미 대격번일 정도로 엄청 바뀐 업데이트가 되었는데 구글 공식에서 조차 업데이트 전으로 설명을 하고 있었기 때문에 많이 헤멨었지만 공식문서를 뜯어보고 깃헙 이슈등 돌아다니면서 하나하나 정보를 얻어 해결할 수 있었다.
웹->앱으로 보내는 것을 엄청 고생하며 찾다가 결국 어차피 앱->웹으로 보내는게 우선적으로 일어나는 일인데 왜 이걸 찾고 있지? 하면서 깨닫기 까지는 보낸 시간이 많았다.
WebView Bridge는 웹에서 작동하는 함수를 미리 작성해두고 앱에서 그 함수를 호출하면 웹에서 함수가 작동하는 방식인데 이것을 사용해서 Drawer를 터치하면 해당하는 url로 이동하는 함수를 웹에 작성해 두고 사용했다.
javascript1useEffect(()=>{ 2 isMobile ? (window as any).webviewNav = function(data:webViewRouteType) { 3 switch (data){ 4 case '': { 5 return router.push(`/${data}`); 6 } 7 case 'profile':{ 8 return router.push(`/user/${data}`); 9 } 10 case 'information-info' :{ 11 return router.push(`/information/${data}`) 12 } 13 case 'chat' : { 14 if(auth.currentUser !== null) { 15 return router.push(`/${data}`); 16 }else{ 17 return false; 18 } 19 } 20 case 'delete' :{ 21 localStorage.removeItem('previousChats'); 22 return dispatch(setClearChatToggle()) 23 } 24 } 25 26 27 } : null 28 29 },[]) 30
함수를 작성해두고 이론은 이해했어도 막상 앱에서 터치하면 웹에 이런 함수가 없다면서 오류를 엄청 냈었다.
처음에는 리액트가 마운트 되기 전이라 함수가 없다고 오류를 냈었고 이 부분은 useEffect를 사용하면서 처리할 수 있었다.
후에는 ts 에러 때문에 웹이 문제를 냈다.
웹뷰 함수를 실행시키기 위해서는 window에 함수를 붙여야하는데 이것에 내가 정의한 메소드는 없기때문에 에러를 냈었는데 window를 any로 type assertion을 해줘야했다.
isMobile은 웹뷰를 통해 접속하면 flutter 플러그인이 제공해주는 webview에서 userAgent를 설정할 수 있는데 그것을 설정해 웹뷰로 접속했는지 아닌지 확인 가능한 함수다.
bridge에 대한 개념은 아직도 받아드리기 어렵다.
CloudFlare Pages
웹의 배포를 위해서 cloudflare의 pages를 사용했다.
next의 api 기능을 할 수 있도록 해줬지만 새로운 방식으로 코드를 작성해야 했고 일간 api 사용량이 정해져있다.
제일 먼저 세팅을 runtime: 'edge'라는 설정을 해줘야하고 reponse를 new Response(JSON.stringify({ result: data }))으로 해줘야했다.
이것때문에 최대한 api를 사용하지 않는 방법을 생각해 결국엔 open ai api에 대한 응답을 내려주는 api만 작성하게 되었다.
Google Play Store
처음으로 앱을 배포하기 위해서 개발자 계정을 신청했다.
배포하기 위해서는 그냥 abb 하나만 올리고 설명만 대충 작성하면 끝일 줄 알았지만 많은 일들이 남아있었다.
앱에 대한 정보를 입력하는데 개인정보 관리법, 광고는 들어있는가, 어떤 앱인가 설문도 많았고 필요한 것들도 많았다.
특히 앱이 어떤 앱인지 알려주는 스토어에 대표적으로 나오는 이미지를 편집할때 시간이 오래걸린것 같았다.
설명을 잘한것인지 앱에 기능이 별로 없어서 인지 심사 후 거절을 당할 것을 예상하고 있었는데 심사 신청 5일 후 바로 승인되어 앱스토어에 올라가게 되었다.
느낀점
결과를 놓고 보면 간단하게 api request, response하고 Auth를 구현한 앱이지만 생각보다 생각할 것들이 많았다.
덕분에 flutter를 잠깐 사용해봤지만 어떤식으로 구성하는지 알게 되었고 WebView도 어떻게 동작하는지 알게 되었다.
chat gpt의 역할을 주는 것이 생각보다 중요한 역할을 하는 것을 체감하게 되었고 많은 사람들이 알면 좋겠다고 생각한다.