모바일 앱 개발자라면 레이아웃과 로직을 즉시 변경할 수 있는 온라인 개발의 유연성과 몇 초 만에 가설 테스트를 실행하고 결과를 훨씬 더 빠르게 처리할 수 있는 능력을 꿈꿔왔을 것입니다.

모바일 개발자는 애플리케이션이 출시되고 업데이트되는 속도가 애플리케이션이 사용자에게 도달하는 속도와 직접적인 관련이 있다고 믿도록 배웁니다. App Store 검토 시간은 답답할 정도로 길 수 있습니다. 소프트웨어 개발 키트(SDK)를 구축하는 것은 다른 사람의 제품 개발 및 릴리스 주기에 자신의 요구 사항을 맞춰야 하기 때문에 훨씬 더 느릴 것입니다. 가설을 전혀 테스트하지 않는 것은 좋은 핑계가 될 수 있습니다.

이 블로그 게시물에서 우리는 주제를 살펴보고 백엔드 중심 개발 단계를 안내하여 특정 문제를 해결하는 데 사용되는 방법과 우리에게 가져온 이점을 설명합니다. 이 포스트의 자료는 MovilePay의 예제 소스 에서 가져왔습니다. 원본 텍스트의 저자는 Rodrigo Maximo입니다.

백엔드 주도 개발이란 무엇입니까?

백엔드 기반 개발(또는 백엔드 기반 개발, 백엔드 기반 UI 또는 서버 기반 UI)은 서버 응답을 기반으로 하는 프론트엔드 애플리케이션을 개발하는 개념입니다. 서버의 응답에 따라 화면과 흐름이 바뀝니다.

모바일 애플리케이션을 만드는 작업의 대부분은 일반적으로 사용자 인터페이스 구축과 관련이 있습니다. 사용자가 하나 또는 다른 작업을 빠르게 수행할 수 있도록 사용자가 상호 작용하는 요소를 화면에 배치합니다. 이러한 구성 요소 중 일부는 API 페이로드로 채워집니다. 일반적으로 기본 유형(정수, 부울, 문자열) 또는 애플리케이션 비즈니스 프로세스가 있는 JSON입니다.

화면을 구현하는 전통적인 접근 방식에는 애플리케이션 측에 많은 비즈니스 로직이 있을 수 있고 코드를 유지 관리하기가 더 어려워지기 때문에 특정 단점이 있습니다.

  • 많은 플랫폼(Android, iOS, 웹 등)에 대해 동일한 코드가 필요합니다. 이 접근 방식은 플랫폼 간 호환성을 유지하기 어렵게 하여 버그 및 비호환성 가능성을 높입니다.
  • 모바일 애플리케이션의 각 업데이트 또는 수정은 코드를 변경할 필요가 있음을 의미하며, 이는 App Store에서 애플리케이션의 확장 릴리스로 이어집니다.
  • 디지털에서는 A/B 테스트가 더 어렵습니다. 중요한 제품 정보를 이해하기 위해 개념을 테스트하고 사용자로부터 데이터를 수집하는 것이 더 어렵습니다.
  • 대부분의 비즈니스 로직이 애플리케이션 측에 있기 때문에 코드를 유지 관리하기가 더 어렵습니다.

이러한 문제를 해결하기 위해 백엔드 지향 개발이 등장했습니다.

다음 시나리오를 고려하십시오(샘플 iOS 앱을 기반으로 하지만 다른 프런트 엔드 프로젝트로 쉽게 변환할 수 있음).

Scenario for backend driven development

 {
    "pageTitle" : "시연 제목" ,
    "상자" : [
        {
            "유형 ": "bigBlue" ,
            "제목" : "좋은 상자" ,
            "subtitle" : "상자  자막"
        } ,
        {
            "유형 ": "작은빨간색" ,
            "제목" : "큰 상자"
        } ,
        {
            "유형 ": "rectangleGreen" ,
            "제목" : "인크레더블 박스" ,
            "subtitle" : "상자  자막" ,
            "숫자" : 10
        }
    ]
}

필드를 표시하고 텍스트 및 시각적 정보를 표시하기 위한 모든 비즈니스 로직은 서버 측에서 통합 및 추상화되어 이 API를 처리하기 위해 여러 인터페이스가 필요하지 않습니다. 그런 다음 서버는 비즈니스 로직을 적용하고 그 결과를 사용하여 JSON 형식의 API 응답을 생성합니다.

예에서 화면에 블록("bigBlue", "smallRed" 및 "rectangleGreen")을 표시하기 위해 각 필드의 추가 정보가 사용됩니다. 흥미롭게도 "boxes" 변수를 사용하면 백엔드에서 서버가 제공하는 만큼의 블록을 처리할 수 있습니다.

이런 상황에서 A/B 테스팅을 어떻게 수행할 수 있는지 이미 짐작하셨나요? 서버는 특정 사용자를 선택하여 "bigBlue" 블록만 볼 수 있고 다른 사용자는 세 가지 유형의 블록을 모두 볼 수 있습니다. 또한 화면에 표시되는 블록의 순서를 변경하는 A/B 테스트를 수행할 수 있습니다.

서버 주도 개발의 또 다른 사용 사례는 애플리케이션의 인터페이스를 변경하는 것입니다. 예를 들어 애플리케이션의 헤더를 변경해야 하는 경우 서버의 응답을 간단히 변경하면 됩니다. 자막과 블록의 표시 순서도 쉽게 변경할 수 있습니다. 이 경우 AppStore에 새 애플리케이션 릴리스를 게시할 필요가 없습니다.

Making changes to the interface in backend driven development

 {
    "pageTitle" : "시연 제목" ,
    "상자" : [
        {
            "유형 ": "rectangleGreen" ,
            "제목" : "또 다른 제목" ,
            "자막" : "다른 자막" ,
            "숫자" : 100
        } ,
        {
            "유형 ": "작은빨간색" ,
            "제목" : "다른 제목"
        }
        {
            "유형 ": "bigBlue" ,
            "제목" : "백엔드 기반" ,
            "자막" : "개발"
        }
    ]
}

두 번 생각

백엔드 기반 개발 접근 방식을 사용할 때 염두에 두어야 할 몇 가지 사항이 있습니다. 첫째, 어느 정도의 유연성이 필요합니까?

경험과 연구를 바탕으로 중간 정도의 유연성이 최적이라고 생각합니다.

한 극단에서 다른 극단으로 서두르면 안 됩니다. 많은 양의 자유는 개발 투자 회수에 부정적인 영향을 미칠 수 있습니다. 특히 기기 사양이나 화면 크기가 제어할 수 없기 때문에 모든 것을 예측할 수는 없습니다. 마지막으로, 매우 혼란스럽고 과부하된 애플리케이션 측 프리젠테이션 로직으로 끝납니다. 또한 디자인 팀이 미래에 하고자 하는 모든 것을 예상할 수는 없습니다. 따라서 여전히 애플리케이션 코드를 변경해야 하며 테스트 중에 목표를 달성하기 위한 수많은 복잡한 경로가 발견됩니다.

따라서 결론적으로 대부분의 경우 HTML이 가지고 있는 유연성이 필요하지 않습니다. 따라서 Backend-Driven Development의 아이디어를 사용하는 화면과 서버 솔루션을 개발하기 전에 가능한 모든 옵션을 고려하는 것이 좋습니다.

슈퍼 앱 제작, 모바일 테크 사례

슈퍼 앱 개념에 익숙하고 WeChat과 같은 앱에 대해 들어본 적이 있을 것입니다. WeChat은 중국에서 개발된 모바일 메시징 플랫폼이자 소셜 네트워크로 전 세계적으로 매우 인기가 있습니다.

이러한 애플리케이션은 여러 반복 서비스를 한 곳에서 수집하고 사용자에게 일상 생활에서 대부분의 온라인 쿼리에 대한 단일 액세스 지점을 제공하는 것을 목표로 합니다. 그것은 소프트웨어 개발의 성배입니다.e, 사용자에게 복잡한 질문에 대한 간단한 답변과 큰 문제에 대한 솔루션을 제공합니다.

과거 MovilePay는 슈퍼 앱 개발에 참여했으며 개선된 버전을 개발하는 과정이 이 기사에 설명되어 있습니다. 팀이 새로운 서비스를 테스트하고 사용에서 공통점을 찾을 수 있는 테스트 및 검증 센터가 되어야 했습니다.

MovilePay는 코드를 빠르게 변경할 수 있는 애플리케이션을 만드는 데 문제가 있었습니다. 많은 서비스와 서비스를 테스트하고 표시된 정보를 기반으로 사용자 행동에 대한 연구를 수행하고 가설을 테스트해야 했습니다. MovilePay는 기능을 빠르게 켜고 끌 수 있기를 원했습니다. 이러한 조건에서 모든 변경 사항에 대해 릴리스와 함께 전통적인 접근 방식을 사용하는 것은 불가능했습니다. 이러한 모든 점과 복잡한 시나리오를 고려하여 Backend-Driven Development를 적용하기로 결정했습니다.

MovilePay는 이 문제를 해결하기 위해 카테고리 기반 홈 화면을 만들었습니다. 각 섹션에는 위젯이라는 고유한 항목 세트가 있습니다. 섹션에는 이미 구현된 서비스에 대한 진입점이 임의의 순서로 표시되고 개별 위젯이 강조 표시되었습니다.

때때로 하나의 서비스만 표시되었습니다. 다른 경우에는 현재 테스트 중인 항목에 따라 세 가지가 있었습니다. MovilePay는 규칙을 애플리케이션에 하드코딩하지 않고 서버에 선택권을 남겼습니다. 결과적으로 애플리케이션은 서비스 진입점의 정의와 각각의 특정 스타일을 렌더링하는 방법만 알고 있습니다. 그들의 서버는 어떤 서비스가 어떤 순서로 생성되어야 하는지 알려줍니다. 다음은 MovilePay 애플리케이션이 표시할 수 있는 몇 가지 위젯입니다.

Widgets that the MovilePay application

Widgets in MovilePay application

Widgets in MovilePay application

Widgets in MovilePay application

따라서 적응력이 뛰어난 홈 화면을 만들기 위해 백엔드로부터 위젯 목록이 포함된 섹션 목록으로 응답을 받아야 했습니다. 다음은 MovilePay 애플리케이션이 아래 예시와 같이 홈 화면을 파싱하여 생성해야 하는 JSON 응답의 예시입니다.

Parsing and creating a home screen

 [
    {
        "제목" : "섹션 1" ,
        "위젯" : [
            {
                "식별자" : "COLLECTION_WIDGET" ,
                "내용" : [
                    {
                        "제목" : "제목 A" ,
                        "이미지" : "아" ,
                        "색상" : "노란색"
                    } ,
                    {
                        "제목" : "제목 B" ,
                        "이미지" : "B" ,
                        "색상" : "파란색"
                    } ,
                    {
                        "제목" : "제목 C" ,
                        "이미지" : "C" ,
                        "색상" : "빨간색"
                    } ,
                    {
                        "제목" : "제목 D" ,
                        "이미지" : "D" ,
                        "색상" : "보라색"
                    } ,
                    {
                        "제목" : "제목 E" ,
                        "이미지" : "E" ,
                        "색상" : "녹색"
                    }
                ]
            } ,
            {
                "식별자" : "IMAGES_WIDGET" ,
                "내용" : [
                    {
                        "이미지" : "이미지" ,
                        "색상" : "녹색"
                    } ,
                    {
                        "이미지" : "이미지" ,
                        "색상" : "파란색"
                    } ,
                    {
                        "이미지" : "이미지" ,
                        "색상" : "오렌지"
                    }
                ]
            } ,
            {
                "식별자" : "COLLECTION_WIDGET" ,
                "내용" : [
                    {"제목" : "제목 E" , "이미지" : "E" , "색상" : "녹색" } , { "제목" : "제목 F" , "이미지" : "F" , "색상" : "보라색" " } , { "제목" : "제목 G" , "이미지" : "G" , "색상" : "빨간색" } , { "제목" : "제목 H" , "이미지" : "H" , "색상 " : "파란색" } , { "제목" : "제목 H" , "이미지" : "H" , "색상" : "노란색" } ] } ] } , { "제목" : "섹션 2" , "위젯 " : [ { "식별자" : "CELLS_WIDGET" , "내용" : [ { "제목" : "셀 1" , "색상" : "빨간색" } , { "제목" : "셀 2" , "색상" : "보라색" } , { "제목" : "셀 3" , "색상" : "노란색" } , { "제목" : "셀 4" , "색상" : "파란색" } , { "제목" : "셀 5" , "색상" : "진한 녹색" } ] } ] } ]

또한 백엔드 기반 개발을 사용하여 구축할 수 있는 몇 가지 화면을 살펴보겠습니다.

Home screens in backend-driven development

유연한 탐색

MovilePay에서 개발한 Super App은 혁신이라는 의도한 목표를 달성했습니다. MovilePay는 가설 테스트를 통해 많은 것을 배웠지만 특히 잘하는 것 중 하나는 결제 처리 또는 다양한 서비스 및 제품에 대한 결제 프로세스입니다. 그들은 그들이 제공한 모든 서비스에 대한 지불을 처리할 수 있는 지불 앱을 가지고 있었습니다. MovilePay는 여러 거래를 처리하고 소비자 행동에 대한 귀중한 통찰력을 얻어 가격을 낮출 수 있기 때문에 지불 거래를 관리하는 기능은 상당한 이점이었습니다.

MovilePay는 다른 애플리케이션과 통합할 수 있는 Google Pay, Apple Pay 또는 VisaCheckout 모델을 기반으로 하는 결제 SDK를 개발하기로 결정했습니다.

그러나 SDK 작업은 일반적인 개발 패턴을 사용하여 테스트할 수 있는 능력이 거의 없음을 의미하므로 자동화가 필요합니다.

MovilePay는 결제를 처리했기 때문에 흐름의 변환이 중요했습니다. MovilePay는 전환 유입경로 단계에서 사용자를 잃을 여유가 없었습니다. 따라서 사용자 등록에서 카드 추가 및 결제에 이르기까지 전체 비즈니스 프로세스를 최적화해야 했습니다. 서버를 애플리케이션의 "내비게이터"로 바꾸면서 백엔드 기반 개발이 다시 유용해졌습니다.

Optimizing the business process with BDD

어떤 MovilePay 애플리케이션 화면도 다음 화면이 무엇인지 알지 못했습니다. 이전 화면이 작업을 완료한 후 서버는 다음에 표시해야 할 화면을 반환하는 역할을 했습니다.

경로는 응용 프로그램이 라우터로 알려진 구조를 통해 인식하고 응답할 수 있는 작업이었습니다. 로그인 메커니즘에는 두 개의 개별 작업 분기가 포함되어 있습니다. 하나는 페이지 제목에 대한 것이고 다른 하나는 작업 트리에서 발생한 다른 요소(예: 사용자 이름 변경 또는 새 암호)에 대한 것입니다. 라우터는 이를 서버로 전송하여 처리한 다음 서버에서 해당 작업을 해석하고 다음 화면에 어떤 해석이 표시되어야 하는지 결정했습니다.

이러한 약간의 전략 변화는 합리화를 가능하게 했습니다. MovilePay는 가입 양식을 표시하기 위해 다양한 방법을 시도했습니다. 카드를 추가하기 전이나 추가한 후에 결제 화면을 표시하는 것이 바람직한지 테스트할 수 있었습니다. 예를 들어, 이것이 MovilePay가 다른 지불 옵션에 비해 전환율을 30% 높일 수 있었던 이유 중 하나입니다.

또 다른 예는 MovilePay가 백엔드 주도 개발을 사용하여 문제를 해결한 방법입니다. 우리는 당신이 이상하다고 생각합니다이 접근 방식을 실제로 적용하는 방법에 대해 설명합니다. 얼마나 쉬운지 보여드리겠습니다.

동일한 목표를 달성하기 위한 많은 대안적 방법이 있습니다. iOS에서 MovilePay가 어떻게 작동했는지 보여드리겠습니다. 원하는 경우 이 개념을 다른 모든 프론트 엔드 플랫폼에 적용할 수 있습니다.

MovilePay는 이를 구현할 때 위젯 추가의 용이성, 코드 가독성, 단일 책임과 같은 요구 사항을 고려했습니다. 일을 더 간단하고 기본적으로 만들기 위해 MovilePay는 직렬화에 Codable API를 사용하기로 결정했습니다.

위젯(iOS)

유연성 측면에서 MovilePay는 프로토콜로 구문 분석해야 하는 위젯을 일반화하는 것이 최상의 솔루션이라고 생각했습니다. MovilePay는 또한 데이터를 구문 분석할 위젯 구조를 결정하기 위해 열거형을 설정합니다.

 프로토콜 위젯 : 디코딩 가능 { }

열거형 WidgetIdentifier : 문자열 , 디코딩 가능 {
    케이스 배너 = "배너"
    케이스 컬렉션 = "COLLECTION"
    케이스 목록 = "LIST"

    var 메타 유형 : 위젯 . 유형 {
        스스로 전환 {
        케이스 . 배너 :
            배너 위젯을 반환 합니다 . 본인
        케이스 . 컬렉션 :
            CollectionWidget을 반환 합니다. 본인
        케이스 . 목록 :
            ListWidget 을 반환 합니다 . 본인
        }
    }
}

그들은 Widget 프로토콜에 의해 구현된 Decodeable 프로토콜을 통해 Codable API를 활용하고 있습니다. 다음은 위젯 구조를 정의한 예이다.

 배너 위젯 구조 : 위젯 {
    private let imageURLString : 문자열
}

구조체 CollectionWidget : 위젯 {

    구조체 항목 : 디코딩 가능 {
        let imageURLString : 문자열
        제목 : 문자열
        let subtitle : 문자열
    }

    let sectionTitle : 문자열
    let list : [ 항목 ]
}

구조체 ListWidget : 위젯 {

    구조체 항목 : 디코딩 가능 {
        let imageURLString : 문자열
        let text : 문자열
    }

    let sectionTitle : 문자열
    let list : [ 항목 ]
}

마지막으로 Decodeable에서 제공한 사용자 정의 초기화를 변경해야 할 때 필요한 초기화 방법으로 모든 위젯을 해석하는 유형 삭제로 정의되었습니다.

 최종 클래스 AnyWidget : 디코딩 가능 {

    개인 enum CodingKeys : CodingKey {
        케이스 식별자
    }

    let 위젯 : 위젯 ?

    필요한 초기화 ( 디코더에서 : Decoder ) 에서 {
         {
            let container = 디코더를 시도 합니다. 컨테이너 ( keyedBy : CodingKeys . self )
            let type = 시도 컨테이너 . 디코딩 ( WidgetIdentifier . self , forKey : . identifier )
            자기 . 위젯 = 시도 유형 . 메타타입 . 초기화 ( from : 디코더 )
        } 잡기 {
            자기 . 위젯 = 없음
        }
    }
}

이 삭제 유형은 위젯의 식별자와 "메타 유형" 속성을 해독하여 구문 분석된 위젯 데이터의 나머지 부분을 구문 분석하는 데 사용해야 하는 위젯 구조를 결정하는 데 사용됩니다.

이 모든 결과 위젯에 대한 모든 정보가 포함된 응답을 구문 분석할 수 있는 아래 구조가 생성됩니다. 고유한 기능이 있습니다. 위젯 프로토콜 유형의 배열이며 위에서 정의한 유형 삭제를 사용하여 각 위젯을 해독할 수 있습니다.

 struct HomeResponse : 디코딩 가능 {

    개인 enum CodingKeys : CodingKey {
        케이스 위젯
    }

    let 위젯 : [ 위젯 ]

    init ( 디코더에서 : Decoder ) 던짐 {
        let container = 디코더를 시도 합니다. 컨테이너 ( keyedBy : CodingKeys . self )
        자기 . 위젯 = 시도 컨테이너 . 디코딩 ( [ AnyWidget ] . self , forKey : . widgetsss="토큰 구두점">) . CompactMap {$ 0. 위젯 } } init ( 위젯 : [ 위젯 ] ) { 자기 . 위젯 = 위젯 } }

MovilePay는 프로토콜을 사용하지 않고 백엔드에 의존하여 구문 분석을 위해 지원되는 각 위젯의 배열을 반환하는 것과 같은 다른 옵션을 선택할 수 있습니다. 그러나 우리는 프로토콜 선택이 유지 관리 및 가독성을 위한 최선의 선택이라는 것을 발견했습니다. 이 접근 방식은 새 위젯을 만들어야 할 때마다 새 구조를 만들고 열거형에 사례를 추가하기에 충분했습니다. 비슷한 상황에서 다른 시스템을 사용하면 HomeResponse의 디자인이 변경되어야 합니다.

다음은 이 모델이 구문 분석할 가능한 JSON API 응답입니다.

 {
    "위젯" : [
        {
            "식별자" : "배너" ,
            "imageURLString" : "url_image_to_be_downloaded"
        } ,
        {
            "식별자" : "컬렉션" ,
            "sectionTitle" : "섹션 제목" ,
            "목록" : [
                {
                    "imageURLString" : "url_image_to_be_downloaded" ,
                    "title" : "제목 항목 1" ,
                    "subtitle" : "자막 항목 1"
                } ,
                {
                    "imageURLString" : "url_image_to_be_downloaded" ,
                    "제목" : "제목 항목 2" ,
                    "subtitle" : "자막 항목 2"
                } ,
                {
                    "imageURLString" : "url_image_to_be_downloaded" ,
                    "title" : "제목 항목 3" ,
                    "subtitle" : "자막 항목 3"
                }
            ]
        } ,
        {
            "식별자" : "목록" ,
            "sectionTitle" : "섹션 제목" ,
            "목록" : [
                {
                    "imageURLString" : "url_image_to_be_downloaded" ,
                    "text" : "텍스트 항목 1"
                } ,
                {
                    "imageURLString" : "url_image_to_be_downloaded" ,
                    "text" : "텍스트 항목 2"
                } ,
                {
                    "imageURLString" : "url_image_to_be_downloaded" ,
                    "text" : "텍스트 항목 3"
                }
            ]
        } ,
        {
            "식별자" : "배너" ,
            "imageURLString" : "url_image_to_be_downloaded"
        }
    ]
}

이 접근 방식은 MovilePay가 다양한 사용자에게 다양한 서비스를 제공하고, 많은 표시 옵션을 테스트하고, 가설을 세우고, 어떤 위젯을 어떤 서비스에 사용할지 결정할 수 있도록 하는 Super App의 개발에 매우 가깝습니다. 화면 정렬 및 서비스 그룹화의 변화는 이전에 MovilePay가 했던 것과 비슷했습니다.

탐색(iOS)

위젯 문제를 수정한 후 MovilePay도 마찬가지로 탐색 개선을 시도했습니다. 그들은 위젯 프로토콜과 동일한 액션 프로토콜을 만들었습니다.

Action은 일부 MovilePay API의 JSON 응답에서 반환되는 구조화된 객체로, 해당 객체가 나타내는 장면에 표시되어야 하는 ID 및 매개변수를 포함합니다. 결과적으로 Action 프로토콜은 구조화된 객체를 해체하는 데 도움을 줄 책임이 있습니다.

 프로토콜 작업 : 디코딩 가능 {
    func 장면 ( ) - > UIViewController
}

열거형 ActionIdentifier : 문자열 , 디코딩 가능 {
    케이스= "홈"
    case screenOne = "SCREEN_ONE"
    case screenTwo = "SCREEN_TWO"

    var 메타 유형 : 작업 . 유형 {
        스스로 전환 {
        케이스 .:
            반환 HomeAction . 본인
        케이스 . 스크린원oken operator">: ScreenOneAction 반환 . self case . screenTwo : ScreenTwoAction 반환 . self } } } 원시 보기

Action 프로토콜과 Widget 프로토콜의 유일한 차이점은 Action 정의에서 각 Action에 대해 적절한 장면을 반환하는 메서드를 제공한다는 것입니다. 예를 들어 이러한 작업이 구현되는 방식을 살펴보십시오.

 struct HomeAction : 액션 {
    func 장면 ( ) - > UIViewController {
        HomeCoordinator를 반환 합니다 . 장면 ( )
    }
}

구조체 ScreenOneAction : 액션 {
    제목 : 문자열

    func 장면 ( ) - > UIViewController {
        ScreenOneCoordinator를 반환 합니다 . 장면 ( 제목 : self .title )
    }
}

구조체 ScreenTwoAction : 액션 {
    제목 : 문자열
    let subtitle : 문자열

    func 장면 ( ) - > UIViewController {
        ScreenTwoCoordinator를 반환 합니다 . 장면 ( 제목 : 자기 . 제목 , 자막 : 자기 . 자막 )
    }
}

위의 예는 Actions가 생성될 때 장면을 초기화하고 UIViewController를 인스턴스화하기 위해 Coordinators 메서드를 호출하는 데 필요한 모든 속성을 포함해야 함을 보여줍니다. 코디네이터는 UIViewController를 제공하는 구조입니다. 여기에 언급할 사항이 있습니다. MovilePay는 각 단계에 대한 UIViewController 인스턴스를 생성하는 작업을 수행하는 정적 scene() 메서드로 표시되는 코디네이터 구조체의 디자인 패턴을 사용합니다.

 최종 클래스 HomeCoordinator : 코디네이터 {
    정적 함수 장면 ( ) - > UIViewController {
        // ViewController와 이 장면의 모든 아키텍처 구성 요소를 만듭니다...
        CreatedViewController 반환
    }
}

최종 클래스 ScreenOneCoordinator : 코디네이터 {
    정적 함수 장면 ( ) - > UIViewController {
        // ViewController와 이 장면의 모든 아키텍처 구성 요소를 만듭니다...
        CreatedViewController 반환
    }
}

최종 클래스 ScreenTwoCoordinator : 코디네이터 {
    정적 함수 장면 ( ) - > UIViewController {
        // ViewController와 이 장면의 모든 아키텍처 구성 요소를 만듭니다...
        CreatedViewController 반환
    }
}

선택한 아키텍처 디자인 패턴(MVC, MVP, MVVM-C, VIPER-C, VIP 또는 조정자를 사용하여 장면을 만들고 한 장면에서 다른 장면으로 이동하는 기타 아키텍처)에도 불구하고 다음을 사용하여 구현합니다. Action 및 Backend-Driven Development는 매우 적절합니다.

Actions MovilePay 컨텍스트의 경우 위젯과 동일한 유형의 지우기를 사용했지만 약간 수정했습니다.

 최종 클래스 AnyAction : 디코딩 가능 {

    개인 enum CodingKeys : CodingKey {
        케이스 식별자
    }

    행동 하자 : 행동 ?

    필수 초기화 ( 디코더에서 : Decoder ) 에서 {
         {
            let container = 디코더를 시도 합니다. 컨테이너 ( keyedBy : CodingKeys . self )
            let type = 시도 컨테이너 . 디코딩 ( ActionIdentifier . self , forKey : . identifier )
            자기 . 액션 = 시도 유형 . 메타타입 . 초기화 ( from : 디코더 )
        } 잡기 {
            자기 . 액션 = 없음
        }
    }
}

여기서 적절한 참고 사항은 MovilePay가 복제 유형 삭제 코드를 피하기 위해 Generics 디자인 패턴을 사용할 수 있다는 것입니다. 그러나 그들은하지 않기로 결정했습니다. 다음은 Action을 포함하는 구조체의 예입니다.

 구조체 ResponseModelForActions : 디코딩 가능 {
    개인 enum CodingKeys"token operator">: CodingKey { case action , text } let action : Action ? let text : String init ( from 디코더 : Decoder ) throws { let container = try 디코더 . 컨테이너 ( keyedBy : CodingKeys.self) self . 텍스트 = 시도 컨테이너 . 디코드 ( String .self , forKey :.text ) let anyAction = try ? 컨테이너 . 디코딩 ( AnyAction.self , forKey :.action ) self . 액션 = anyAction ?. 액션 } }

예를 들어 화면에 UIButton을 생성하기 위해 API에서 JSON을 제공할 수 있습니다. 사용자가 이 버튼을 탭한 후 처리되는 작업 개체는 제공된 작업을 수행하여 애플리케이션이 홈 화면을 표시하도록 할 수 있습니다.

 {
    "text" : "설명 텍스트" ,
    "액션" : {
        "식별자" : "HOME_SCREEN"
    }
}

모든 코디네이터가 Actions 개체를 통해 새 장면을 얻을 수 있도록 Coordinator 프로토콜을 확장하여 쉽게 달성했습니다.

코디네이터가 작동하도록 허용합니다. 즉, 해당 작업에 대한 다음 UIViewController 인스턴스를 생성한 다음 표시할 수 있습니다.

 확장 코디네이터 {
    func 장면 ( action : Action 사용 ) - > UIViewController {
        반환 조치 . 장면 ( )
    }
}

서버 구현에 대한 힌트

이 모든 것이 서버 측에서 어떻게 보이는지 궁금할 것입니다. 서비스 및 핵심 기능을 외부 정보와 혼동하지 않는 방법은 무엇입니까? 소프트웨어 개발의 성공 비결은 레이어 작업에 있습니다.

따라서 모든 복잡한 핵심 서비스 외에도 MovilePay는 다른 모든 서비스를 추상화하고 모든 애플리케이션 논리를 적용하여 데이터를 프런트엔드에서 예상하는 응답으로 변환하는 또 다른 계층을 서버에 추가했습니다. 이 계층을 BFF라고 하며 Frontend용 Backend는 시스템의 관련 없는 두 끝 사이의 통신을 제공하는 계층입니다. 문자열, 이미지, 스트림 및 스타일 변형이 응용 프로그램으로 보내기 전에 기본 데이터에 구성되고 적용되는 곳입니다.

결론

백엔드 기반 접근 방식을 사용하면 몇 가지 이점이 있으며 이 기사 전체에서 이를 명확히 하려고 했습니다. 그러나 이것은 또 다른 솔루션 템플릿일 뿐입니다. 앱 개발을 위한 마법의 약이 아닙니다. 또한 응용 프로그램이 사용되는 컨텍스트를 고려해야 합니다. 여러 플랫폼을 위한 애플리케이션을 만들어야 합니까? 어떤 유형의 테스트를 하시겠습니까? 모든 화면을 완벽하게 제어해야 합니까? 페이로드는 얼마나 클까요? 이러한 작업을 처리할 수 있는 개발 팀을 포함하여 이 프로젝트를 수행하기에 충분한 리소스가 있습니까?

무엇보다도 어느 정도의 유연성이 필요한지 항상 주의해야 합니다. 매우 다양한 UI 구성 요소를 만들거나 비표준 글꼴과 여백을 사용하면 코드베이스가 엄청나게 복잡해져 사용자 경험이 나빠질 수 있습니다.

대부분의 프로젝트에는 이러한 유연성이 필요하지 않습니다. 백엔드 기반 접근 방식을 선택할 때 재무 및 개발 팀의 형태로 이러한 프로젝트를 개발 및 유지 관리할 리소스가 있는지 여부와 애플리케이션의 페이로드를 올바르게 계산할 수 있는지 여부를 고려하는 것이 필수적입니다.