[Flutter] 서버 시간 기준으로 앱 구동하기(feat. NTP)

Tykan·2021년 6월 9일
0

Flutter의 DateTime

플러터 앱을 제작하면서 시간을 다룰 때 대부분 DateTime 클래스를 사용한다.
현재 시각이 기준점이 되는 경우가 많은데, 이 때 DateTime.now()로 간단하게 현재 시각을 알 수 있다.

하지만, DateTime.now()를 통해 얻는 시간은 로컬 기기의 시각. 즉, 사용자가 디바이스의 날짜/시간 설정을 변경하면 바뀌게 된다.

상단 사진처럼 수많은 시계들이 각각 자기만의 시간을 가지고 있다.
특정 서비스를 위해서는 이런 수많은 시계들을 동기화시켜 같은 시간을 가지도록 해야할 때가 많다.

클라이언트 앱에서 서버 시간을 기준으로 동작하도록 변경하면서 찾아본 내용들을 정리하고자 글을 쓴다.

NTP(Network Time Protocol)

PC 혹은 서버간의 연결된 사이에 동일한 시간으로 교환을 할수 있는 프로토콜

모든 네트워크 및 장비는 자체적인 시간을 가지고 있다.
이를 동일한 시간을 가지도록 하는 통신 프로토콜이다.

NTP는 stratum 구조(지층 구조)라는 수직적인 형태를 가지고 있는데, 이 구조를 통해 보다 정확한 시간을 트래픽 과부하 문제없이 얻을 수 있다.

Stratum 0은 사실상 NTP에 속하지 않으며 하위 Stratum 1 레벨로 시간을 전송하는 장비로 세슘원자시계, GPS 등이 이에 속한다.

그 아래 차례대로 바로 상위 지층에서 시간을 받아 다시 하위 지층으로 시간을 보내주는 무수히 많은 서버들이 존재한다. 이러한 구조를 통해 상위 레벨의 서버들에 대한 트래픽이 줄어 보다 정확한 표준 시간을 유지할 수 있다.


그럼 Flutter 앱에서는 타임 서버를 통해 어떻게 시간을 받을 수 있을까?

이제 Flutter에서 써보자!

플러터 NTP 패키지

플러터 패키지 라이브러리에 ntp 패키지가 있다.
https://pub.dev/packages/ntp
기본적으로 구글 ntp 서버로부터 시간을 받아온다.

DateTime startDate = await NTP.now();

비동기로 현재 시간을 받아오는데 ntp 통신은 리소스가 매우 적으므로 걱정할 필요는 없다고 한다.

다른 방법은...?

복잡한 기능을 쉽게 구현할 수 있는 패키지는 나도 많이 사용하고 있지만...
개인적으로 의존하는 패키지를 늘리는 것을 선호하지 않는다.
그리고 async를 통한 비동기처리 보다는 동기적으로 처리하고 싶었고, 앱의 API 서버 시간에 동기화시키고 싶었다.

그래서 그냥 앱 내부에 타임 서비스 클래스를 하나 만들었다.

  1. 싱글톤(Singleton)패턴으로 타임 클래스 생성
  2. 인스턴스 생성 시 서버로 부터 시간을 받아 로컬 디바이스 시간과의 오프셋을 계산하여 저장한다.
  3. 디바이스 시간을 오프셋 시켜 현재 서버 시간 호출 가능

단, 동기화 후 유저가 디바이스 시각을 변경하면 다시 동기화를 해줘야하기 때문에 사용자가 앱을 이탈했다가 돌아오면 동기화하도록 했다.

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    // 앱이 다시 재개된 경우 시간 동기화 실시
    if (state == AppLifecycleState.resumed) {
      Time.sync(); //동기화 코드
    }
    super.didChangeAppLifecycleState(state);
  }
profile
개발자 Theo :: 고민은 성장의 힘

3개의 댓글

comment-user-thumbnail
2022년 6월 27일

안녕하세요 좋은글 잘 봤습니다 혹시 시간이 괜찮으시면 제 질문도 한번 확인해주사면 감사하겠습니다.

플러터에서 ElevatedButton을 클릭 시 A앱을 실행 시킴과 동시에 A앱의 서버시간도 가져와서 PIP형태로 띄우고 싶습니다.

이런식으로 특정 웹, 앱의 서버시간을 가져와서 플로팅 시킬 수 있는지 궁금합니다.

가능하다면 연관된 패키지도 알고 싶습니다.

1개의 답글