react-native-biometics
라이브러리의 네이티브 코드를 수정하고자 파일을 열었다. 안드로이드는 자바로, iOS는 Objective C
로 개발되어있었다.
응답형태를 키-값으로 통일하고 싶었으나 iOS 코드를 도대체 어떻게 수정해야하는지 감이 오지 않았다. 다른 코드를 읽어보며 그럴듯하게 작업은 마무리가 되었지만,
다음에 있을 기회에는 좀 더 발전됨을 준비하고자 프로그래밍 오브젝트 C
책과 react-native-biometrics
코드를 읽어보며 Objective C
를 알아두고자 한다.
자바랑 비슷한데 너무 C다
객체지향인 것은 자바랑 같다. 그러나 스타일은 C이다. C를 하나도 모르는데 이해할 수 있을까 걱정했지만, 오브젝티브 씨를 공부하면서 얻고자 하는 방향성에 대해 생각해보면서 부담없이 알아보도록 하였다.
interface + implementation
interface
에서 클래스의 데이터, 메소드를 선언하고 implementation
에서 이를 오버라이딩하는 개념으로 구현해낸다.
객체 선언
my = [myClass alloc]
으로 객체를 할당하였고 [my init]
으로 초기화를 진행한다.
이를 한번에 나타내면 [[myClass alloc] init]
으로 표현할 수 있으며 [myClass new]
와 같다.
가비지 콜렉션
자바에서는 사용하고 있지 않은 메모리에 대해 정리해주는 가비지 콜렉션
이 존재한다. 그러나 iOS에서는 이걸 지원하지 않고 있다. (왜 인지 모르겠지만...)
그래서 사용한 메모리에 대해 사용하지 않는 경우 항상 정리를 직접 해줘야한다. 이때, 어디선가 사용하고 있는 경우 retain
으로 레퍼런스 카운트
가 증가하고 사용하지 않는 경우 release
로 감소시킨다. 그리고 레퍼런스 카운트
가 0이 되면 해당 메모리가 완전하게 정리된다.
포인터
그냥 값을 가져오면 되는거 아닐까 생각했는데, 만약 엄청 큰 데이터가 있고 이를 들고서 왔다갔다 해야한다면 그때마다 메모리가 소비된다. 이때 이 데이터가 들어있는 주소만 알아내서 들고다닌다면 훨씬 효율적으로 움직일 수 있다.
카테고리, 프로토콜
카테코리: 라이브러리, 모듈화
프로토콜: 구현되어야 하는 메서드 모음
react-native-biometrics
직접 커스텀했던 라이브러리 코드를 다시 열어보았다.
#import <React/RCTBridgeModule.h>
@interface ReactNativeBiometrics : NSObject <RCTBridgeModule>
@end
ReactNativceBiometrics.h
파일로 interface
선언 부분이다. 안타깝게도 여기에 선언된 변수와 메소드가 없다... 아마 React Native
특성상 브릿지로 호출하게 되어서 그런건 아닐까 생각해본다.
NSObject
를 상속받고 있으며 프로토콜로 RCTBridgeModule
이 눈에 보인다.
#import "ReactNativeBiometrics.h"
#import <LocalAuthentication/LocalAuthentication.h>
#import <Security/Security.h>
#import <React/RCTConvert.h>
@implementation ReactNativeBiometrics
RCT_EXPORT_MODULE(ReactNativeBiometrics);
RCT_EXPORT_METHOD(isSensorAvailable:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
{
LAContext *context = [[LAContext alloc] init];
NSError *la_error = nil;
BOOL canEvaluatePolicy = [context canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&la_error];
if (canEvaluatePolicy) {
NSString *biometryType = [self getBiometryType:context];
NSDictionary *result = @{
@"available": @(YES),
@"biometryType": biometryType
};
resolve(result);
} else {
NSString *errorMessage = [NSString stringWithFormat:@"%@", la_error];
NSDictionary *result = @{
@"available": @(NO),
@"error": errorMessage
};
resolve(result);
}
}
그리고 이 코드는 ReactNativeBiometrics.m
으로 implementation
구현 내용이다.
RCT_EXPORT_MODULE
으로 명시된 이름올 네이티브 모듈을 사용할 수 있는데 여기에는 isSensorAvailable
이 있고 인자로 resolve
와 reject
를 받는다.
첫번째 코드로 LAContext *context = [[LAContext alloc] init];
이 있는데 이는 LAContext
를 할당 alloc
하고 init
으로 초기화된 포인터가 context
이다.
그다음에 NSError *la_error = nil;
로 에러 변수를 초기화하였다.
위에서 초기화한 context
의 메소드 canEvaluatePolicy
을 바로 아래에서 사용하고 있다.
리턴된 값에 따라 아래 조건이 분기되며 [self getBiometryType:context]
에서 ReactNativeBiometrics.m
파일에 같이 구현되어있는 getBiometryType
메서드를 호출한다.
그리고 NSDictionary
에 키-값 형태로 만들어서 응답값을 돌려주면 해당 네이티브 모듈이 완성된다.
결론
황금 연휴에 쓱 읽어내려간 책 한권으로 이해하기에는 너무나 방대했고, C를 너무 몰랐다. 지금도 헷갈리는 부분은 많지만 읽기 전과 후가 다르게 라이브러리를 읽는데 눈에 더 보이는 것들이 있으니 앞으로 도움이 될거라 생각한다.