Skip to content

9oHigh/usket.Discussion-App

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

header

📃 목차


💁 프로젝트 소개

"주제별로 특정 시간만 활성화되는 채팅방 기능을 가진 SNS 앱"

  • 원하는 채팅방을 예약하고, 예약한 방이 오픈되기 1분 전에 알림 전송
  • 정해진 시간이 지나면 채팅방은 종료

📱 스크린샷

Image 1     Image 2     Image 3
Image 1     Image 2     Image 3

⚙️ 사용한 기술 스택

  • Front

    flutter     dart
    Package Purpose
    http REST API 통신을 위해 사용
    socket_io_client 채팅 구현을 위해 사용 - SocketManager
    go_router Screen navigation을 위해 사용
    permission_handler 알림 권한 요청을 위해 사용
  • Back

    nodejs     typeScript     postgres    
  • 협업도구

    gitlab     notion     discord     figma     postman

🏗️ 디렉토리 구조

├── lib
│   ├── core
│   │   ├── app_color.dart
│   │   ├── app_constant.dart
│   │   └── app_font_size.dart
│   ├── main.dart
│   ├── manager
│   │   ├── notification_manager.dart
│   │   ├── socket_manager.dart
│   │   ├── toast_manager.dart
│   │   └── topic_manager.dart
│   ├── model
│   │   ├── player.dart
│   │   ├── room.dart
│   │   └── topic
│   │     ├── topic_count.dart
│   │     ├── topic_item.dart
│   │     └── topic.dart
│   ├── router.dart
│   ├── screens
│   │   ├── chat_screen.dart
│   │   ├── create_room_screen.dart
│   │   ├── favorite_screen.dart
│   │   ├── filter_screen.dart
│   │   ├── home_page.dart
│   │   ├── home_screen.dart
│   │   ├── styles
│   │   └── widgets
│   ├── services
│   │   ├── api_service.dart
│   │   └── end_point.dart
│   └── utils
│       ├── mixin
│       └── topic_mapped.dart

🚩 성과

  1. 리팩토링을 통해 코드 가독성의 중요성을 알게되었습니다.
  • 방 목록을 가지고오는 코드에서 조건문이 많이 코드가 중복되고, 가독성이 떨어졌습니다.
    • 문제의 코드
      Future<void> _fetchRoomList({bool? isReload}) async {
        final DateTime now = DateTime.now();
        if (isReload != null && isReload) {
          _roomList = await _apiService.getRoomList(null, 10);
          _roomList = _roomList
              .where((room) => !room.isReserved && now.isBefore(room.startTime))
              .toList();
          if (_roomList.isNotEmpty) {
            cursorId = _roomList.last.roomId.toString();
          }
          if (mounted) setState(() {});
        } else {
          final toBeAddedRooms = await _apiService.getRoomList(cursorId, 10);
          if (toBeAddedRooms.isEmpty) {
            return;
          } else {
            _roomList += toBeAddedRooms;
            _roomList = _roomList
                .where((room) => !room.isReserved && now.isBefore(room.startTime))
                .toList();
            if (_roomList.isNotEmpty) {
              cursorId = _roomList.last.roomId.toString();
            }
          }
        }
      }
    • 개선
      Future<void> _fetchRoomList({bool isReload = false}) async {
        final DateTime now = DateTime.now();
        List<Room> fetchedRooms =
            await _apiService.getRoomList(isReload ? null : cursorId, 10);
      
        if (fetchedRooms.isEmpty) return;
      
        final List<Room> filteredRoom = fetchedRooms
            .where((room) => !room.isReserved && now.isBefore(room.startTime))
            .toList();
      
        _roomList = isReload ? filteredRoom : _roomList += filteredRoom;
        cursorId = _roomList.isNotEmpty ? _roomList.last.roomId.toString() : null;
        if (mounted && isReload) setState(() {});
      }
      • isReload의 경우, 입력 받지 않을 경우에 초기값을 false로 구현해 옵셔널 확인 및 값을 확인하는 작업을 제거했습니다.
      • 필터 처리된 리스트를 추가하거나 대체하는 작업을 제외하면 나머지 코드는 동일하기에 데이터를 가져와 필터 처리를 먼저 진행하도록 수정했습니다. 즉, 두 번의 필터처리가 아닌 한 번만 수행하게 됩니다.
      • 이후, reload인지 more인지 확인 및 분기 처리하여 리스트를 업데이트했습니다.
  1. http를 활용해 REST API를 구축하는 방법을 알 수 있었습니다.
  • EndPoint Enum
    enum EndPoint {
      topicList,
      topicRoomCount,
      player,
      roomList,
      roomCreate,
      roomIdList,
      deleteRoom,
    }
    
    extension EndPointExtension on EndPoint {
      String get url {
        switch (this) {
          case EndPoint.topicList:
            return '/topic/list';
          case EndPoint.topicRoomCount:
            return '/topic/room-count';
          case EndPoint.player:
            return '/player';
          case EndPoint.roomList:
            return '/room/list';
          case EndPoint.roomCreate:
            return '/room/create';
          case EndPoint.roomIdList:
            return '/room/ids';
          case EndPoint.deleteRoom:
            return '/room/delete';
          default:
            return '/';
        }
      }
    }
    • enum과 extension을 활용해 endpoint를 정의해 사용했습니다.
  • Get, Post, Delete Http Method를 사용해 필요한 데이터를 요청하거나, 보내는 방법을 알 수 있었습니다.
    • apiService.dart
    • 예시 코드
      Future<List<TopicCount>> getTopicRoomCounts() async {
        // EndPoint extension을 활용해 url을 가져와 get method를 통해 요청
        final response =
            await http.get(Uri.parse("$_baseUrl${EndPoint.topicRoomCount.url}"));
        // 결과 값을 확인하고 매핑해 반환
        if (200 <= response.statusCode && response.statusCode <= 299) {
          final List<dynamic> data = json.decode(response.body);
          final List<TopicCount> topicCounts =
              data.map((json) => TopicCount.fromJson(json)).toList();
          return topicCounts;
        } else {
          throw Exception('Failed to load topic room counts');
        }
      }

😎 팀원

프로필 이미지 신가연
- 채팅방 생성 화면과 기능
- 필터 화면 및 기능
- 채팅방 알림 예약, 취소
- UI 디자인 및 구현
프로필 이미지 이경후
- 홈 화면과 기능
- 채팅 화면과 기능
- 라우터 적용
- 리팩토링(비지니스 로직과 예외처리)

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages