[SSAFY] 자율프로젝트 별이삼샵 회고록

·2024년 12월 6일
0

Projects

목록 보기
4/4

쪽지를 장소에 숨기고 직접 찾아서 읽는 Mobile App 메신저 서버스

들어가기 전에,,

9-6를 제일 잘 지킨 프로젝트이면서도 초반 팀장의 싸탈로 인해 팀장직을 넘겨받으면서 제일 신경을 많이 쓴 프로젝트기도 하다.
성격 상 의견을 잘 내고 주도하는 스타일이어서 팀장이던 아니던 구성원으로서 비슷한 일을 할 것이라고 생각했는데 아니었다..!🙃
팀원들의 진행 사항 체크부터 산출물 제출 등 신경써야할 부분이 많았지만, 계속 회피했던 발표도 해보고 정말 의미있는 경험이었다.
프로젝트가 끝난 시점에서 팀원들에게 좋은 팀장이었는지 궁금하다!

프로젝트 소개

앱 프로젝트 / 6인 프로젝트 / 024.10.14 ~ 2024.11.19

위치 기반 쪽지로 사용자들이 자신이 선택한 장소에 직접 가서 사진을 찍고, 사진의 픽셀화된 이미지를 힌트로 삼아 쪽지를 숨깁니다.

쪽지를 받은 사용자는 힌트를 단서 삼아 장소를 찾아가 쪽지를 열람할 수 있습니다.

1대1 소통뿐만 아니라 단체 쪽지, 불특정 다수 등 다양한 소통 방식을 제공합니다.

기획 과정

기업 연계 프로젝트가 하고 싶어서 공통 때 같이 한 팀원 몇명과 팀을 꾸려서 지원했지만 떨어져서 어쩔 수 없이 기획을 다시 해야했다.
앞선 두번의 프로젝트(공통, 특화)에서 경험한 바로 기획이 제일 힘들었기에 이번 프로젝트는 주제를 빨리 정하고 싶었다(실제로 기간도 짧았기도 하고)

일반 메세지 기능은 기존의 메시징 서비스에 비해 경쟁력이 없다고 판단하여 조금 더 직접적으로, 물리적인 방식으로 아날로그 감성을 더할 수 있는 ✨위치 기반 쪽지 서비스를 기획했다.

전반적으로 싸피를 통해 새로운 기술을 배우고 사용해보고 싶었다.
이번에는 익스텐션이나 vanilla javascript만으로 프로젝트를 만들어보고 싶기도 했지만 백엔드 볼륨이 작아 아쉽게도 다음을 기약했다.

메신저 서비스가 전체적인 볼륨이 작은 대신 1차 배포를 빨리해서 사용자 피드백을 받고 사용자 분석을 해보기로 정하고 계속 해보고 싶었던 네이티브 앱 개발을 Flutter로 해보기로 했다!! 예~~~😁

도전 과제 및 해결책

Positioned.fill의 위치

다트와 플러터를 이틀만에 공부한 바람에 위젯의 올바른 사용에 대해 완벽하게 알지 못했다.

디버깅 모드로 개발을 했을 때는 화면상에 문제가 없어, 배포하려고 빌드하고 apk를 실행해본 순간...!!
하얀색 오버레이가 위에 씌어진 듯한 화면에 터치도 먹지 않았다ㅜㅜㅜ

내가 만든 layout.dart가 문제라고 생각했고 잘못된 부분은 아래와 같다.

return Scaffold(
      backgroundColor: themeProvider.backgroundColor,
      body: Stack(
        children: [
          Positioned.fill(
            child: child,
          ),
          IgnorePointer(
            ignoring: true,
            child: Positioned.fill( // 여기가 잘못됨!
            ),
          ),

positioned.fill는 Stack 바로 밑에 있어야하는데 그렇지 않을 경우 디버깅 모드에선 괜찮은데 릴리즈모드에선 화면이 깨질 수 있다!

관련 이슈

Positioned.fill과 비슷하게 Expanded 위젯도 위치를 잘못 배치하면 디버그 모드에서는 오류 메시지가 나타나지만, 릴리스 모드에서는 UI가 응답하지 않거나 깨지는 현상이 발생할 수 있다.

FormData null

메세지 전송 api를 테스트하는데 계속 10초 타임아웃 에러가 났다.
처음에는 이미지가 커서 전송하는데 시간이 걸리나 싶어 압축을 하고 보내봐도 nginx는 여전히 499 에러,,

이미지가 문제가 아니라고 생각하여, 잠시 nginx가 아니라 백서버로 요청을 보내 정확한 에러 로그를 확인해보니...422에러!!!
계속 Int가 String으로 넘어간다는 거시었다

이미지가 있어 'multipart/form-data'로 넘겨주기로 했는데 아무리 출력을 해봐도 정확히 출력이 되는데 뭐가 문젠가 울고 싶었다 /(ㄒoㄒ)/~~

문제는 바로..바로.. null 값이 ""로 넘어가기 때문이다!!
그래서 출력을 해도 알 바가 없었고, 백엔드 팀원이 더 정확한 에러 메세지를 알려줘서 해결할 수 있었다. (하얗게 불태웠다..)

피티햄 왈:

Dio는 내부적으로 null 값을 처리할 때, 필드를 무조건적으로 빈 문자열로 변환하지는 않습니다.
하지만 FormData의 일부 필드가 null로 설정된 경우, 이를 직렬화(serialization)하는 과정에서 빈 문자열로 변환될 수 있습니다.
이는 HTML 폼 제출의 기본 동작을 모방한 것으로, null 값을 빈 문자열로 처리하는 것을 기본값으로 삼기 때문입니다.

그래서 값이 비어있는 경우 formData에서 빼는 식으로 코드를 바꿔주었다.

//이전 코드
final rawData = data.toJson();
final processedData = rawData.map((key, value) {
  if (value is String && value.isEmpty) {
    return MapEntry(key, null); 
  }
  return MapEntry(key, value);
});
final formData = FormData.fromMap(processedData);


//수정된 코드
 final Map<String, dynamic> rawData = data.toJson();
      final Map<String, dynamic> processedData = {};
      rawData.forEach((key, value) {
        if (value != null &&
            !((value is String && value.isEmpty) ||
                (value is List && value.isEmpty) ||
                (value is File))) {
          processedData[key] = value;
        }
      });

6시에 시작한 작업이

11시 반이 되어야 끝나는 매직 🤮🤩

착한 우리 팀원들 😭

사이사이 백엔드에서 respnse type이 잘못 주기도 했고, fastApi에 보내야하는 request body 형식과 ec2서버에 보내야하는 body 형식이 다른 문제도 있어서 에러를 하나 해결하면 새로운 에러가 나오고 마치 에러 순회 공연을 하는 것 같았다ㅋㅋㅋ

DateTime

여러 서버를 쓰면서 서버의 timeZone이 다른 문제가 있었다.
알 길이 없는 프론트는 똑같이 보냈는데, 알림함에서는 시간이 맞고 메세지함에서는 9시간이 더해진 두개의 시간대를 살게되는 신기한 모험을 하게됐다.

백엔드에게 물어보니, createdTime을 각각 처리하는데 서버 간의 timeZone이 달라서 같은 Date객체를 파싱하는데 문제가 있었다.

덕분에 TimeZone에 대해 깊게 알아볼 수 있었다.

아래는 우리 팀원의 한마디이다.

요즘IT Timezone 설명 글
이 글만 읽어도 Timezone에 대한 개념은 잘 잡힐거 같다.

다양한 Exception 처리

앱이다 보니 웹프로젝트보다 더 꼼꼼하게 에러핸들링을 해줬다.

🚨엄청난 에러코드..

서버에서 주는 에러 뿐만 아니라 사용자 네트워크 연결 여부에 따른 화면, 타임 아웃 에러 등 다양한 예외를 처리해주었다.

ResponseCode 클래스를 만들어서 api response를 포괄적으로 처리하고, ErrorHandler 클래스를 만들어 에러를 캡슐화하고 사용자에게 에러에 따른 일관된 메세지를 제공하도록 설계했다.

향후 계획

다른 팀원이 구현한 Map을 대거 리팩토링하고 싶다..
중간에 한번 시도했는데 마감이 얼마남지 않아 포기했었기 때문에 더 미련이 남는다.

마무리 및 후기

배운 점

  • FCM
  • Google Analytics
    처음으로 GA4를 사용해보면서 사용자 분석을 할 수 있었다.
    분석이랄 것도 없지만, 확실히 로그인 이전에 메인화면에서 이탈이 많은 것을 확인할 수 있었다.

다음에 또 싸피를 한다면(?) 로그인이 필요없는 서비스, 앱이 아니라 웹 서비스(+ pwa)로 만들어서 접근성을 높여 더 많은 사용자 데이터를 받아보고 싶다.

아쉬운 점

실제 스토어에 올려보지 못한건 아쉽다!
올려도 프로젝트가 끝나면 서버가 내려가기 때문에 안되겠지만,,

또한 프론트엔드와 백엔드에서의 데이터 가공에 대해 팀원들과 좀더 대화를 나눠보고 싶었다. 이번에 백에서 과도하게 데이터를 가공해서 주지 않았나 싶기 때문에, 어떤 데이터는 포맷해주고 어떤 데이터는 프론트가 하는게 좋을지 얘기해보고 싶다.

profile
중요한 건 꺾여도 다시 일어서는 마음

0개의 댓글