[완] 개인서버 개발/EasyCalendar(완)

#2 EasyCalendar Flutter 구현

북극곰은콜라 2023. 6. 20. 18:31
반응형

짤막 흥보: 호구홍시 조대봉 (인스타 툰)


개요

Flutter로 구현한 Client Web 관련 리뷰
개발 중 이슈사항 리뷰

 


Project Structure

main: main class
main_state_page: 시작페이지, 로그인 체크
calendar_page: 일정 확인 / 등록 페이지
main_exception: custom exception
network_client: REST 요청 관련 모듈

리뷰

1. main class를 분리하는 의미가 없는듯하다.
2. main_state_page의 의미가 많이 퇴색되었다. Google 인증도 main_state_page에 넣었어야 했다.
3. 구현해 보니, 각 page에는 widget 생성 관련 로직만 넣고, 비즈니스? 로직은 외부로 빼는 것이 좋을 것 같다.

 


Library

flex_color_scheme: 7.0.4
getwidget: 3.1.1
flutter_secure_storage: ^8.0.0
dio: 5.1.1
flutter_web_auth: 0.5.0

리뷰

flex_color_scheme를 통해 스킨색에 대한 컨트롤은 어느정도 구현되었다.
getwidget으로 UI 컴포넌트를 만들었는데, 딱히 이쁘진 않음...
flutter_secure_storage는 토큰정보를 저장하기 위해 도입했으며, 적절
dio는 REST 요청 등 활용되는 Library인데, 기본 모듈보다 좋은 점은 찾지 못함
flutter_web_auth는 OAuth2.0 Client를 구성하기 위해서 도입했으며, 가장 간단하게 client 연동을 구현했다.

 


이슈

1. OAuth2.0 Client Library 선정

Flutter는 기본적으로 Native App을 위한 크로스 플랫폼 프레임워크이다.
많은 라이브러리가 App을 위해 개발되었으며, Web은 아니다.
OAuth2.0 Library 또한 대부분 Web을 제대로 지원하지 않았다. (WebView가 Web에 없기 때문)
선정된 라이브러리는 Web에서 사용가능한 우회방식을 제시해준다.

사용 예

// API 사용
Future<String> getMainAuthorizationToken() async {
    return await FlutterWebAuth.authenticate(
        url: '$_loginPageUrl?$_loginPageQueryParams',
        callbackUrlScheme: _callbackUrlScheme);
}

// redirect 된 access_token parameter 추출
var accessToken = Uri.parse(result).queryParameters['access_token'];

redirect 경로에 auth.html 추가

<!DOCTYPE html>
<html lang="kr">
<head>
  <meta charset="UTF-8">
    <title>Authentication complete</title>
    <p>Authentication is complete. If this does not happen automatically, please close the window.</p>
</head>
<body>

<script>
    window.opener.postMessage({
        'flutter-web-auth': window.location.href
    }, window.location.origin);
    window.close();
</script>
</body>
</html>
redirect 되면 auth.html로 오게 만들고, 해당 페이지에서 기존 페이지로 돌아오게 하며, 라이브러리 사용법에 따라서 parameter를 받아서 사용한다.

2. Dynamic Widget 생성

Future<List<Widget>> _createCalendarEvent() async {
    _selectedCalendarId = await networkClient.getCalendarId();
    List<dynamic> res = await networkClient.getCalendarEvents(_selectedCalendarId);
    res.sort((a, b) => _compareStartTime(a, b));
    final targetEvents = res.sublist(0, 4);
    for (Map<String, dynamic> event in targetEvents) {
      Map<String, String> start = Map.from(event["start"]);
      _addCalendarEvent(event["id"], start["dateTime"]!, event["summary"]);
    }

    return eventList.values.toList();
}
위와 같이 Future로 Widget이 생성되는 경우, Widget 생성 또한 이에 대응해야 한다.
FutureBuilder(
  future: _createCalendarEvent(),
  initialData: const [Text("data loading 중")],
  builder: (context, snapshot) {
    return Column(
      key: UniqueKey(),
      mainAxisAlignment: MainAxisAlignment.start,
      children: snapshot.requireData,
    );
  },
),
FutureBuilder를 통해 Future를 받을 때 Widget을 구성해주는 Widget이 있다.

3. Web build with prefix

배포되는 환경에서는, url에 prefix가 붙어야 했다.
flutter navigate시 prefix가 붙어서 할 수 있도록 build 시 args를 추가했다.
flutter build web --base-href "/easycal/"

 


총평

첫 Flutter 프로젝트여서, 기능구현에 초점을 맞췄다.
내부 구현 구조가 대규모로 변경되는 사항이 많아서, 프로젝트는 유지보수에 어려움이 있을 것으로 예상된다.
특히 계산로직과 widget 생성 로직 등이 뒤섞여있는 부분이 안타깝다.
front 단 코딩에 쫌 더 생각을 해보고 진행해야겠다.

 

 

 

반응형

'[완] 개인서버 개발 > EasyCalendar(완)' 카테고리의 다른 글

#1 EasyCalendar 기획 및 설계  (0) 2023.05.26