티스토리 뷰

지금 진행하는 프로젝트에서 아래와 같은 패턴으로 Promise ~ Then 방식이 구현되어있는 코드를 Await / Async로 전환하는 과정에서 매우 까다로와보여서 공유한다.


this.fingerprint.isAvailable().then((value: any) => { // 생체인증 권한 획득
    this.fingerprint.show( options ).then((value: any) => { // 생체인증 다이얼로그 표시
        this.fingerprintSuccessHandler();
    }).catch((error: any) => { // 생체인증 실패
        this.fingerprintErrorHandler();
    });
}).catch((reason: any) => { // 생체인증 권한 획득 실패
    console.warn( reason );
});


위와 같은 코드를 보면 일단 생체인증 다이얼로그를 표시하기 전에 생체인증 권한을 획득해야하는 상황이 발생하는 경우 이를 Async / Await 로 변환하려면 아래와 같이 코드를 작성할 수 있다.

try { // 생체인증 권한 획득
    await this.fingerprint.isAvailable();
    try {
        await this.fingerprint.show( options ); // 생체인증 다이얼로그 표시
        this.fingerprintSuccessHandler();
    } catch( error ) { // 생체인증 실패
        this.fingerprintErrorHandler();
    }
} catch( reason ) {
    console.warn( reason );
}

이렇게 작성된 코드를 보고 알 수 있는 사실은 Async / Await 코드가 코드양에 대하여 무조건 이득을 볼수는 없다는 사실과 try ~ catch 문을 중첩으로 사용해야하는 상황이 발생하는 일이 생기게 된다. 중첩으로 try ~ catch를 사용하는 것이 문제는 아니지만 Promise ~ Then 의 복잡도를 피하기 위해 Async / Await 를 사용한 것인데 이건 살을 취하기 위해 뼈를 내준 것 같은 일이 벌어진거다.


그렇다면 아래의 모양으로 코드를 수정해보자.

try { // 생체인증 권한 획득
    await this.fingerprint.isAvailable();
} catch( reason ) {
    console.warn( reason );
}

try { // 생체인증 다이얼로그 표시
    await this.fingerprint.show( options );
    this.fingerprintSuccessHandler();
} catch( error ) { // 생체인증 실패
    this.fingerprintErrorHandler();
}

이 코드의 문제점은 위 단락에서 권한을 획득하지 못해 에러가 발생하는 경우 권한을 획득하지 못한채로 생체인증 다이얼로그를 요청하는 문제가 발생하게 된다. 그러면 아래처럼 코드를 고쳐볼 수 있다.


let available = false;

try { // 생체인증 권한 획득
    await this.fingerprint.isAvailable();
    available = true;
} catch( reason ) {
    console.warn( reason );
}

if( available ){
    try { // 생체인증 다이얼로그 표시
        await this.fingerprint.show( options );
        this.fingerprintSuccessHandler();
    } catch( error ) { // 생체인증 실패
        this.fingerprintErrorHandler();
    }
}

이런 방식의 코드를 작성하면 정상적으로 동작을 하기는 하지만 뭔가 애매하다. 코드를 단순화하려고 할 때마다 코드가 점점 복잡해지는 아이러니가 발생한다. 어떻게 하면 스마트하게 해결할 수 있을까.

구조적으로 복잡해지긴 하겠지만 생체인증 권한을 획득하는 경우는 계속해서 재활용하면서 사용할 수 있으므로 아래처럼 코드를 정리해서 생체인증 권한을 획득하는 코드를 별도의 블록으로 분리하면 생체인증 다이얼로그를 표시하는 부분이 깔끔해진다.


private async getFingerprintAvailable():Promise<boolean> {
    let available = false;

    try { // 생체인증 권한 획득
        await this.fingerprint.isAvailable();
        available = true;
    } catch( reason ) {
        console.warn( reason );
    }

    return available;
}

private async showFingerprint():Promise<any> {
    if ( await this.getFingerprintAvailable() ) {
        try { // 생체인증 다이얼로그 표시
            await this.fingerprint.show( options );
            this.fingerprintSuccessHandler();
        } catch( error: any ) { // 생체인증 실패
            this.fingerprintErrorHandler();
        }
    }
}

이런식으로 코드를 정리하면 반복적으로 사용하는 생체인증 권한 획득 부분을 별도의 블록으로 관리하여 재사용할 수 있도록 만들어두고 생체인증의 비즈니스 로직을 별도로 처리하도록 만들어두면 되겠다.


처음엔 코드가 증가하는 것 처럼 보일 수 있으나 공통 처리 모듈로 분리 시켰을 때 코드의 재사용으로 얻을 수 있는 잇점은 상당하다.

이러한 패턴은 다양한 부분에서 응용이 가능하니 알아두고 써먹도도록 하자.


아디오스


P.S 물론 Promise - Then으로도 위와같이 블록을 분리해서 코드를 관리할 수 있으나 아무래도 Async / Await 방식이 코드의 가독성을 조금이라도 더 높일 수 있다는 점에서 장점이 있다.

댓글
댓글쓰기 폼