Docs Menu
Docs Home
/ /
Atlas App Services

튜토리얼: FTXUI를 사용한 C++용 Atlas Device Sync

이 페이지의 내용

  • 학습 목표
  • 전제 조건
  • 템플릿으로 시작하기
  • 템플릿 앱 살펴보기
  • 앱 열기
  • 앱 빌드
  • 앱 구조 살펴보기
  • 앱 실행하기
  • 백엔드 확인하기
  • 애플리케이션 수정하기
  • 새 속성 추가
  • 모델에 속성 추가
  • UI에 요소를 추가하여 우선 순위 설정
  • 데이터베이스에 새 속성 저장
  • 실행 및 테스트
  • 구독 변경
  • 구독 업데이트
  • 실행 및 테스트
  • 결론
  • 다음 단계

예상 완료 시간: 30분, C++ 사용 경험에 따라 다름

C++ 용 Atlas Device SDK 를 사용하면 휴대폰, 태블릿,웨어러블 또는 IoT 기기 전반에 걸쳐 데이터를 저장 하고 동기화 할 수 있습니다. 이 튜토리얼은 이름이 인 C++ 템플릿 cpp.todo.flex 앱을 기반으로 하며,FTXUI 로 빌드된 할 일 목록 터미널 GUI 애플리케이션 을 만드는 방법을 보여줍니다. . 이 애플리케이션 을 통해 사용자는 다음을 수행할 수 있습니다.

  • 이메일을 새 사용자 계정으로 등록합니다.

  • 이메일과 비밀번호를 사용하여 계정에 로그인하고 나중에 로그아웃합니다.

  • 자신의 작업을 보고, 만들고, 수정하고, 삭제할 수 있습니다.

  • 사용자가 소유자가 아닌 경우에도 모든 작업을 볼 수 있습니다.

템플릿 앱은 장치가 '오프라인 모드'에 있는 것을 시뮬레이션하는 토글도 제공합니다. 이 토글을 사용하면 인터넷에 연결되지 않은 사용자를 에뮬레이션하여 시뮬레이터에서 Device Sync 기능을 빠르게 테스트할 수 있습니다. 그러나 프로덕션 애플리케이션에서는 이 토글을 제거할 가능성이 높습니다.

이 튜토리얼은 템플릿 앱을 기반으로 합니다. 기존 Item 모델에 새 priority 필드를 추가하고 Flexible Sync 구독을 업데이트하여 우선 순위 범위 내의 항목만 표시합니다.

이 튜토리얼에서는 필요에 맞게 템플릿 앱을 조정하는 방법을 보여줍니다. 템플릿 앱의 현재 구조를 고려할 때 반드시 이렇게 변경할 필요는 없습니다.

이 튜토리얼에서는 다음을 알아봅니다.

  • 호환성이 손상되지 않는 변경을 적용해 C++ 객체 모델을 업데이트합니다.

  • Device Sync 구독 업데이트.

  • 동기화되는 데이터를 변경하려면 서버의 Device Sync 구성에 쿼리 가능한 필드를 추가하십시오.

안내된 튜토리얼을 따르는 대신 직접 애플리케이션을 시작하고 싶다면 C++ 빠른 시작을 확인해 보세요. 여기에는 복사 가능한 코드 예시와 Atlas App Services 백엔드를 설정하는 데 필요한 필수 정보가 포함되어 있습니다.

  • 필요한 소프트웨어가 설치되어 있는지 확인합니다. C++ 템플릿 앱에서는 다음이 있다고 가정합니다.

    • CMake 버전 3.25 이상입니다.

    • C++ 17 이상.

  • 이 튜토리얼은 템플릿 앱으로 시작합니다. 템플릿 앱을 만들려면 Atlas 계정, API 키, Atlas App Services CLI가 필요합니다.

    • Atlas 계정 만들기에 관한 자세한 사항은 Atlas 시작하기 문서에서 확인할 수 있습니다. 이 튜토리얼을 사용하려면 프리 티어 클러스터가 있는 Atlas 계정이 필요합니다.

    • 로그인하려는 MongoDB Cloud 계정에 대한 Atlas API 키도 필요합니다. App Services CLI를 사용해 템플릿 앱을 만들려면 프로젝트 소유자여야 합니다.

    • App Services CLI 설치에 대해 자세히 알아보려면 App Services CLI 설치를 참조하세요. 설치 후 Atlas 프로젝트의 API 키를 사용하여 login 명령을 실행합니다.

이 튜토리얼은 cpp.todo.flex라는 이름의 C++ 동기화 템플릿 앱을 기반으로 합니다. 기본 앱으로 시작하여 여기에 새로운 기능을 구축합니다.

템플릿 앱에 관한 자세한 사항은 템플릿 앱을 참조하십시오.

아직 Atlas 계정이 없는 경우 등록하여 템플릿 앱을 배포합니다.

App Services App 만들기 가이드 에 설명된 절차에 따라 Create App from Template 을 선택합니다. Real-time Sync 템플릿을 선택합니다. 이렇게 하면 Device Sync 템플릿 앱 클라이언트 중 하나와 함께 사용하도록 사전 구성된 App Services App 이 생성됩니다.

템플릿 앱을 만들면 UI에 Get the Front-end Code for your Template이라는 레이블이 붙은 모달이 표시됩니다. 이 모달은 템플릿 앱 클라이언트 코드를 .zip 파일로 다운로드하거나 App Services CLI를 사용하여 클라이언트를 가져오는 방법에 대한 지침을 제공합니다.

C++ 템플릿 앱은 아직 App Services UI 에서 다운로드 수 없습니다. CLI 를 사용하거나 Github 에서 리포지토리 를 복제하여 클라이언트 코드를 가져옵니다.

appservices apps create 명령은 백엔드 를 설정하고 이 튜토리얼의 기반으로 사용할 C++ 템플릿 앱 을 만듭니다.

터미널 창에서 다음 명령을 실행하여 US-VA 리전에 배포되고 환경이 'development(production 또는 QA가 아닌)'로 설정된 'MyTutorialApp'이라는 앱을 만듭니다.

appservices app create \
--name MyTutorialApp \
--template cpp.todo.flex \
--deployment-model global \
--environment development

이 명령은 --name 플래그의 값과 동일한 이름으로 현재 경로에 새 디렉토리를 작성합니다.

클라이언트 코드가 포함된 리포지토리 를 Github 포크하고 복제할 수 있습니다.Device Sync C++ 클라이언트 코드는 https://github.com/mongodb/ Template-app-cpp-todo에서 확인할 수 있습니다.

이 프로세스를 사용하여 클라이언트 코드를 가져오는 경우 클라이언트와 함께 사용할 템플릿 앱을 만들어야 합니다. 템플릿 앱 만들기의 지침에 따라 Atlas App Services UI, App Services CLI, 또는 Admin API를 사용하여 Device Sync 템플릿 앱을 만듭니다.

1

원하는 IDE에서 프론트엔드 클라이언트 코드를 엽니다.

Github 리포지토리 에서 클라이언트 를 복제한 경우 클라이언트 의 적절한 위치에 App Services App ID 를 수동으로 삽입해야 합니다. 앱 ID 삽입 위치를 학습 보려면 클라이언트 README.mdConfiguration 지침을 따르세요.

2
  1. 앱을 빌드할 디렉토리를 만듭니다. 편의를 위해 템플릿 앱과 함께 패키징된 .gitignore는 클라이언트 디렉토리 내의 build 디렉토리를 무시합니다. 빌드 디렉토리로 이동합니다.

    mkdir build && cd build
  2. CMake를 사용하여 Makefile을 만듭니다. 클라이언트 디렉토리 내의 build 디렉토리에서 구축한다고 가정합니다.

    cmake ../
  3. CMake를 사용하여 앱 실행 파일을 빌드합니다. 종속성을 설치하고 실행 파일을 컴파일하는 데 잠시 시간이 걸립니다.

    cmake --build .
3

잠시 시간을 내어 CMake가 실행 파일을 빌드하는 동안 프로젝트가 어떻게 구성되는지 살펴보세요.

이 튜토리얼에서는 다음과 같은 파일로 직접 작업하지는 않지만 C++ SDK를 사용하는 데모 코드가 포함되어 있습니다.

file
목적
controllers/app_controller.cpp

nlohmann::json 라이브러리를 사용하여 atlasConfig.json에서 값을 읽습니다. 그런 다음 이 값을 사용하여 realm::App을 초기화하고 앱의 상태에 저장합니다. App은 애플리케이션이 App Services 백엔드와 통신하는 방법입니다. 이를 통해 인증에 액세스하고 로그인한 사용자의 realm::user 객체에 액세스할 수 있습니다.

앱 구성을 사용자 지정하는 방법에 대해 자세히 알아보려면 Atlas App Services 백엔드에 연결하기를 참조하세요.

이 코드는 AuthManagerErrorManager도 설정합니다. 여기에는 로그인한 사용자가 있는지 여부에 따라 사용자를 LoginController 또는 HomeController로 보내는 탐색 흐름이 포함되어 있습니다.

managers/auth_manager.cpp
이메일/비밀번호 사용자를 등록하고, 해당 사용자를 로그인 또는 로그아웃시키고, 인증 오류가 발생하면 오류 메시지를 표시하는 로직입니다.

이 튜토리얼에서는 다음 파일에서 작업하게 됩니다.

file
목적
state/item.hpp
당사가 데이터베이스에 저장하는 Item 객체를 정의합니다.
state/home_controller_state.hpp
홈 뷰의 앱 상태를 관리합니다.
controllers/home_controller.hpp
Home(홈) 보기 컨트롤러에 대한 중요한 정의를 포함합니다.
controllers/home_controller.cpp
홈 뷰 구현 로그인한 사용자가 앱으로 작업할 수 있는 뷰입니다.
managers/database_manager.hpp
Device Sync 및 데이터베이스 작업에 대한 중요한 정의를 포함합니다.
managers/database_manager.cpp
몇 가지 Device Sync 및 데이터베이스 작업(항목 만들기, Device Sync 쿼리 구독 변경, 동기화 오류 처리 등)을 구현합니다.
4

코드를 변경하지 않고도 터미널에서 앱을 실행할 수 있어야 합니다. 애플리케이션을 실행할 때 atlasConfig.json 의 경로를 인수로 전달하세요.

./sync_todo /path-to-file/atlasConfig.json

앱을 실행하고 새 사용자 계정을 등록한 다음 할 일 목록에 새 항목을 추가합니다.

필요한 경우 터미널 창을 확장합니다.

홈 화면 상단에는 완료된 작업을 숨길 수 있는 버튼과 토글이 있습니다. 터미널 창이 너무 작으면 버튼 텍스트 레이블이 표시되지 않습니다. 레이블을 보려면 터미널 창을 크게 만드세요. 그러면 FTXUI가 더 큰 창에 맞게 콘텐츠를 다시 렌더링합니다.

5

Atlas App Services에 로그인합니다. Data Services 탭에서 Browse Collections를 클릭합니다. 데이터베이스 목록에서 todo 데이터베이스를 찾아 펼친 다음 Item 컬렉션을 찾아 펼칩니다. 해당 컬렉션에 만든 문서가 표시되어야 합니다.

1

이제 모든 것이 예상대로 작동하는지 확인했으므로 변경 사항을 추가할 수 있습니다. 이 튜토리얼에서는 우선 순위에 따라 항목을 필터링할 수 있도록 각 Itempriority 속성을 추가합니다.

프로덕션 앱에서는 PriorityLevel 열거형을 추가하여 사용 가능한 값을 제한할 수 있습니다. 이 튜토리얼에서는 숫자 속성을 사용하여 UI 프레임워크 작업을 간소화하겠습니다.

이렇게 하려면 다음 단계를 따라 진행합니다.

  1. 원하는 IDE에서 클라이언트 코드를 엽니다.

  2. state/ 디렉터리에서 item.hpp 파일을 엽니다.

  3. Item 구조체에 다음 속성을 추가합니다.

    int64_t priority;
  4. priority 속성을 REALM_SCHEMA()에 추가합니다.

    REALM_SCHEMA(Item, _id, isComplete, summary, owner_id, priority)

    이제 Item 모델이 다음과 유사하게 표시되어야 합니다.

    namespace realm {
    struct Item {
    realm::primary_key<realm::object_id> _id{realm::object_id::generate()};
    bool isComplete;
    std::string summary;
    std::string owner_id;
    int64_t priority;
    };
    REALM_SCHEMA(Item, _id, isComplete, summary, owner_id, priority)
    } // namespace realm
2
  1. state 디렉토리에서 home_controller_state.hpp(으)로 이동합니다. 기존 newTaskIsComplete 속성 아래에 새 int 속성을 추가합니다. 그런 다음 static const int(을)를 추가하여 이 속성의 int 기본값을 저장합니다.

    이제 HomeControllerState 구조체는 다음과 비슷할 수 있습니다.

    struct HomeControllerState {
    static const int DEFAULT_TASK_PRIORITY = 3;
    // Used for creating a new task.
    std::string newTaskSummary;
    bool newTaskIsComplete{false};
    int newTaskPriority{DEFAULT_TASK_PRIORITY};
    ...more code here...
    };
  2. controllers 디렉토리에서 home_controller.hpp로 이동합니다. 이 컨트롤러는 앱의 기본 보기를 렌더링합니다.

    문자열 및 벡터 라이브러리를 가져옵니다.

    #include <string>
    #include <vector>

    새 우선 순위 UI 요소에 대한 문자열 레이블의 배열을 만듭니다.

    std::vector<std::string> priorityLevelLabels = {
    "Severe", "High", "Medium", "Low"
    };
  3. 여전히 controllers 디렉토리에서 home_controller.cpp (으)로 이동합니다. 여기에 사용자가 항목의 우선순위를 설정할 수 있는 UI 요소를 추가합니다. FTXUI는 이 기능에 사용할 수 있는 Radiobox 또는 Dropdown 의 두 가지 UI 요소를 제공합니다. 이 튜토리얼에서는 Dropdown (을)를 사용하지만, UI가 드롭다운을 렌더링하기 위해 리플로우되는 방식이 마음에 들지 않는다면 Radiobox(을)를 선호할 수 있습니다.

    이 새 UI 요소 입력을 auto newTaskCompletionStatus 줄 뒤에 추가합니다.

    auto newTaskPriorityDropdown = ftxui::Dropdown(
    &priorityLevelLabels,
    &_homeControllerState.newTaskPriority
    );

    auto saveButton 함수 클로저에서 작업 우선 순위 선택을 _dbManager.addNew() 함수 호출에 전달합니다.

    _dbManager.addNew(
    _homeControllerState.newTaskIsComplete,
    _homeControllerState.newTaskSummary,
    _homeControllerState.newTaskPriority);

    그다음, 우선 순위 선택 항목을 기본값으로 재설정하는 줄을 추가합니다.

    _homeControllerState.newTaskPriority = HomeControllerState::DEFAULT_TASK_PRIORITY;

    항목 행 컨테이너의 대화형 요소 레이아웃을 설정하는 auto newTaskLayout 항목에 드롭다운 선택기를 추가합니다.

    auto newTaskLayout = ftxui::Container::Horizontal(
    {inputNewTaskSummary, newTaskCompletionStatus, newTaskPriorityDropdown, saveButton});

    이제 코드의 이 섹션이 다음과 유사하게 표시되어야 합니다.

    auto newTaskCompletionStatus = ftxui::Checkbox("Complete", &_homeControllerState.newTaskIsComplete);
    auto newTaskPriorityDropdown = ftxui::Dropdown(
    &priorityLevelLabels,
    &_homeControllerState.newTaskPriority);
    auto saveButton = ftxui::Button("Save", [this] {
    _dbManager.addNew(
    _homeControllerState.newTaskIsComplete,
    _homeControllerState.newTaskSummary,
    _homeControllerState.newTaskPriority);
    _homeControllerState.newTaskSummary = "";
    _homeControllerState.newTaskIsComplete = false;
    _homeControllerState.newTaskPriority = HomeControllerState::DEFAULT_TASK_PRIORITY;
    });
    auto newTaskLayout = ftxui::Container::Horizontal(
    {inputNewTaskSummary, newTaskCompletionStatus, newTaskPriorityDropdown, saveButton});
  4. 마지막으로 home_controller.cpp 파일의 아래쪽에 있는 auto itemListRenderer에 새 UI 요소를 추가합니다.

    inputNewTaskSummary->Render() | ftxui::flex,
    newTaskCompletionStatus->Render() | ftxui::center,
    newTaskPriorityDropdown->Render(),
    saveButton->Render(),

    그러면 UI의 저장 버튼 바로 앞에 새 요소가 렌더링됩니다.

3
  1. managers 디렉토리에서 database_manager.hpp로 이동합니다. addNew() 함수 시그니처를 업데이트하여 home_controller.cpp에서 전달한 int newItemPriority를 포함하도록 합니다.

    void addNew(
    bool newItemIsComplete,
    std::string newItemSummary,
    int newItemPriority);
  2. 이제 database_manager.cpp로 이동하여 addNew() 구현을 업데이트합니다. 함수 인수에 int newItemProperty 추가:

    void DatabaseManager::addNew(
    bool newItemIsComplete,
    std::string newItemSummary,
    int newItemPriority) {
    ...implementation...
    }

    Item을 데이터베이스에 저장할 때 priority 속성 값을 설정하기 위해 함수에 새 줄을 추가합니다.

    .priority = newItemPriority

    addNew() 구현은 이제 다음과 같아야 합니다.

    void DatabaseManager::addNew(bool newItemIsComplete, std::string newItemSummary, int newItemPriority) {
    auto item = realm::Item {
    .isComplete = newItemIsComplete,
    .summary = std::move(newItemSummary),
    .owner_id = _userId,
    .priority = newItemPriority
    };
    _database->write([&]{
    _database->add(std::move(item));
    });
    }
4

이 시점에서 애플리케이션을 다시 빌드하고 실행합니다. 빌드 디렉토리에서 변경한 내용을 적용하여 실행 파일을 다시 빌드합니다:

cmake --build .

그리고 다음과 같이 앱을 실행하세요.

./sync_todo /path-to-file/atlasConfig.json

이 튜토리얼의 앞부분에서 생성한 계정을 사용하여 로그인합니다. 이전에 생성한 하나의 항목이 표시됩니다. 새 항목을 추가하면 이제 우선 순위를 설정할 수 있는 것을 볼 수 있습니다. 우선 순위로 High를 선택하고 항목을 저장합니다.

이제 브라우저에서 Atlas 데이터 페이지로 다시 전환하고 Item 컬렉션을 새로 고침 하십시오. 그러면 priority 필드가 추가되고 1로 설정된 새 항목이 표시됩니다. 기존 항목에는 priority 필드가 없습니다.

컬렉션에 있는 두 가지 항목
클릭하여 확대

참고

동기화가 해제되지 않은 이유는 무엇인가요?

SDK 클라이언트 객체에 속성을 추가하는 것은 호환성이 손상되는 변경이 아니므로 클라이언트를 재설정할 필요가 없습니다. 템플릿 앱에는 개발 모드가 활성화되어 있으므로 클라이언트 객체에 대한 변경 사항이 서버 사이드 스키마에 자동으로 반영됩니다. 자세한 내용은 개발 모드데이터 모델 업데이트를 참조하세요.

managers 디렉토리의 database_manager.cpp 파일에서 당사는 사용자의 장치 및 계정과 동기화할 문서를 정의하는 Flexible Sync 구독을 생성합니다. 기본적으로 당사는 모든 항목을 구독합니다. 사용자는 다른 사람들이 만든 항목을 볼 수는 있지만 서버 측 규칙에 따라 해당 항목에 쓰기를 수행할 수는 없습니다. 이 로직은 당사가 초기 구독을 생성하는 블록에서 확인할 수 있습니다. 앱이 열릴 때 구독이 없으면 당사는 다음과 같이 모든 Item 객체에 대한 구독을 추가합니다.

_database->subscriptions().update([this](realm::mutable_sync_subscription_set& subs) {
// By default, we show all items.
if (!subs.find(_allItemSubscriptionName)) {
subs.add<realm::Item>(_allItemSubscriptionName);
}
}).get();

toggleSubscriptions() 함수에서는 현재 구독 상태 에 따라 구독 을 전환합니다. UI 에서 사용자는 모든 항목을 표시하거나 자신의 항목만 표시하도록 토글할 수 있습니다. 이 함수 내에서 _myItemSubscriptionName 로직을 찾습니다. 이 구독 이름에 대한 구독 이 아직 없는 경우 앱 은 owner_id 속성 이 인증된 사용자의 ID와 일치하는 모든 문서에 구독 을 추가합니다.

이 튜토리얼에서는 이를 유지하되 '높음' 또는 '심각' 우선 순위로 표시된 항목만 동기화하려고 합니다.

이러한 이유로 priority 속성에 int64_t를 사용하고 UI의 우선 순위 수준을 중요도 순서로 표시합니다. 가장 높은 우선 순위(심각)의 값은 0이고 가장 낮은 우선 순위(낮음)의 값은 3입니다. 숫자와 우선 순위 속성을 직접 비교할 수 있습니다.

1

구독을 변경하려면 managers 디렉토리로 이동하여 database_manager.cpp 파일을 엽니다. 우선 순위가 1과 같거나 작은 같은 문서를 포함하도록 쿼리 문을 업데이트합니다. 여기에는 '심각'(0) 또는 '높음'(1) 우선 순위의 항목만 포함되어야 합니다.

if (!subs.find(_myItemSubscriptionName)) {
subs.add<realm::Item>(
_myItemSubscriptionName,
[&](auto &item){
return item.owner_id == _userId && item.priority <= 1;
}
);
}
2

애플리케이션을 다시 실행합니다. 이 튜토리얼의 앞부분에서 생성한 계정을 사용하여 로그인합니다. Subscription 상자에서 Switch to Mine 버튼을 누릅니다. SDK에서 문서 컬렉션을 다시 동기화하는 초기 시점 이후에는 사용자가 만든 새로운 높음 우선 순위 항목만 볼 수 있습니다. 마우스를 움직이거나 화살표 키를 사용하여 UI가 백그라운드에서 동기화된 새 항목으로 다시 렌더링되도록 해야 할 수도 있습니다.

처음에 생성한 항목 문서에는 priority 필드가 없기 때문에 장치에 표시되지 않습니다. 이 항목을 장치와 동기화하려면 Atlas UI에서 문서를 편집하고 priority 필드에 값을 추가할 수 있습니다.

개발자 모드가 활성화된 상태에서 구독 변경하기

이 튜토리얼에서는 구독을 변경하고 처음으로 우선 순위 필드에 대한 쿼리를 하면 해당 필드가 Device Sync Collection Queryable Fields에 자동으로 추가됩니다. 이는 템플릿 앱에 개발 모드가 기본적으로 활성화되어 있기 때문입니다. 개발 모드가 활성화되지 않은 경우 클라이언트 사이드 동기화 쿼리에서 필드를 사용하려면 쿼리 가능 필드로 수동으로 추가해야 합니다.

자세한 내용은 쿼리 가능 필드를 참조하세요.

기능을 추가로 테스트하려면 다양한 우선 순위의 항목을 생성할 수 있습니다. 우선 순위가 낮은 새 항목이 항목 목록에 잠시 나타났다가 사라지는 것을 볼 수 있습니다. 동기화 오류 처리기는 이 동작을 설명하는 메시지를 유용하게 제공합니다.

A sync error occurred. Message:
"Client attempted a write that is not allowed; it has been reverted"

이 시나리오에서 SDK는 항목을 로컬에서 생성하고 백엔드와 동기화한 후 쓰기를 되돌립니다(구독 규칙을 충족하지 않기 때문).

참고

알려진 UI 문제

오류 모달이 표시된 상태에서 오류 모달을 해제하기 전에 터미널의 항목 목록 위로 마우스를 이동하면 UI 렌더링이 중단됩니다. 이는 FTXUI 라이브러리의 제한 사항과 관련이 있습니다. 이 문제가 발생하면 ctrl + c를 사용하여 앱을 종료했다가 다시 실행하세요. 마우스를 움직이기 전에 Enter 키를 사용하여 오류 모달의 Dismiss 버튼을 누르면 이 문제를 방지할 수 있습니다.

기존 SDK 객체에 속성을 추가하는 것은 호환성이 손상되지 않는 변경이며, 개발 모드는 스키마 변경이 서버 사이드에 반영되도록 합니다.

참고

피드백 공유

어떻게 되었나요? 페이지 오른쪽 하단의 Rate this page 위젯을 사용하여 효과를 평가하세요. 문제가 있었다면 GitHub 리포지토리에 이슈를 제출하세요.

다음

Atlas Application Services란 무엇인가요?