개발을 하다 보니 의외로 이쪽은 정보가 많은듯 보이지만, 시작 자료만 넘쳐날뿐 깊게 다루는 정보는 많이 없다는 것을 깨달았다...
나는 ReactNative(이하 RN)를 개발하면서 많이 느끼게 되었다. 삽질 정말 많이했다. 적어도 내가 고생했으면 다른사람은 쉽게 얻어야 할 수 있는것 아닌가 그런 생각이 문득 들었고, 그래서 지금 이 블로그를 팠다. 물론 블로그를 파게 된것은 여러가지 사연이 복합적으로 들어있다.
첫번째로 블로그를 파게된 이유는 다음과 같다.
난 여느때나 다름없이 RN을 이용하여 개발을 하고 있었다. 나는 RN을 보조하는 디펜던시는 대부분 react native community 계열이거나, software mansion, airbnb사의 라이브러리만 거의 사용중이다. 다른 라이브러리를 쓰지않은 이유는 너무 불안정해서이다. 에초에 위에서 내가 사용한다고 언급한 라이브러리들도 어느정도 검증을 받았음에도 불구하고 문제가 많은데, 검증되지 않은 라이브러리를 사용했다간 프로덕션에서 어떤이슈가 생길지 모르고, 디버깅이 너무 힘들어질것 같다.
어느정도 엄선된 라이브러리들을 설명을 좀해보자면, react native community는 facebook에서 제대로된 react native library 생태계를 형성하기 위해 만들어진 organization이여서 react native community산 라이브러리는 믿을만 하다. 그리고 이전엔 RN자체 기능이였던 feature들을 점점 react native community로 분리를 하는것 같다... software mansion의 라이브러리는 RN을 사용하면 사실상 표준인것 같다. 그냥 안쓰면 구현을 못한다... 어려워서 못한다 수준이 아니라 진짜 못한다. 물론 gesture handler는 직접 구현을, reanimated는 그냥 animated를 쓰면 되지만... ㅎㅎ.. 한번 써보길 바란다. 마지막으로 airbnb는 RN에 올인을 했고, 그로인해 여러가지 좋은 라이브러리를 생성했으며
빤스런쳤다...
ㅠㅠ
그래서 어느정도 괜찮은 라이브러리들도 어딘가 하나씩 나사빠져있는 경우가 많다. 특히 react native pager view. 이놈은 원래 RN 이였다가 react native community 였다가 따로 빠져나온걸로 알고있다. 얘 버그 겁나많다. 물론 다 커버 가능하다.
근데 이런걸 도대체 누가 알려주는가. 알려줄 사람이 없지않은가. 나도 RN 처음 시작할때 옆에서 미리 개발해보신 분이 도움을 주셔서 그나마 빠르게 정착할 수 있었다. 그런데 아무도 없이 개발하는사람이면... 그래서 나라도 글을 좀 써야겠다고 생각했다.
두번째, Superset TS의 만행때문이다.
TS? JS와 달리 타입을 명시할수 있다니 너무 좋은거 아니야?
그래.... 타입 명시하는건 좋다 이거야... 근데 도대체 왜 왜 왜 타입 매칭을 지원하지 않는거야????
type A = {
a: string;
}
type B = {
b: string;
}
type C = {
c: string;
}
type TestType = A | B | C;
function test(value: TestType) {
if (value instanceof A) {
console.log(value.a);
} else if (value instanceof B) {
console.log(value.b);
} else if (value instanceof C) {
console.log(value.c);
} else {
throw Error('what?');
}
}
놀랍게도 해당코드는 동작하지 않는다. 사실 놀라운건 아니다. TS의 동작 원리를 생각해보면 당연한거긴 하다. 동작이 되면 그게 더 이상한거긴 하다. TS는 Type을 컴파일타임에만 유지하고 런타임에는 전부 날려버리고 js로 코드를 컴파일한다. 그말은 컴파일타임에서 타입을 판정하는 instanceof나, typeof는 전혀 사용할 수 없다는 것이다.
????????
진짜 처음에 보고 이게 뭔소린가 했다. 아니 이해야 하지... 근데 그럼 다른 솔루션은??
function test(value: TestType) {
if (value.a) {
console.log(value.a);
} else if (value.b) {
console.log(value.b);
} else if (value.c) {
console.log(value.c);
} else {
throw Error('what?');
}
}
실화다 진짜 이렇게 해야한다
근데 더 반전은 저것도 동작안된다. 왜냐? TestType은 union타입이라서 TestType에 a라는 필드가 있는지 없는지 모른다. 따라서 a라는 필드를 바로 접근하려고하면 오류가 난다.
좋다... 그럼 다음과 같이 바꾸면 되겠지
function test(value: TestType) {
if ('a' in value && value.hasOwnProperty('a')) {
console.log(value.a);
} else if ('b' in value && value.hasOwnProperty('b')) {
console.log(value.b);
} else if ('c' in value && value.hasOwnProperty('c')) {
console.log(value.c);
} else {
throw Error('what?');
}
}
드디어 정답이다. 참고로 in과 hasOwnProperty를 동시에 쓰는이유는 js 자체 문제때문에 항상 in으로 검사하고 추가로 hasOwnProperty를 해야한다고 기억하고있다.
미안하다. 왜인지 이유는 잘 기억이 나질 않는다...
아무튼 이제는 커스텀 타입을 런타임에서도 typesafe하게 사용가능하다!
...
여기에 TestType이란걸 Generic하게 받아버리면 더 골치 아프다. GenericType이 Object인지 아닌지 확인해야한다. 그러다 보면 타입이 런타임에 safe함을 증명하기 위해 작성된 코드가 원래 코드보다 훨씬 길어지는 사태가 많이 일어난다. 그래서 이땐 as 캐스팅하거나 적절히 is 타입가드로 대충 때우긴 한다
이러한 문제가 정말 많이 겪었고, 정말 다양한 블로그를 찾아보았다. 그러나 이 문제가 어떠한 문제이고, 생기는 원인은 무엇이며, 이 문제가 어떤 영향을 주고, 그래서 해결법은 무엇이고, 한계는 무엇인지. 아무곳도 적혀있지 않다. 그래서 직접 나라도 삽질을 하면서 고민한 흔적을 누군가와 공유를 하는게 좀더 좋지 않을까? 라는 생각이 들어서 개설하게 되었다
아직 더 남았다... 박찬호 아니다
RN으로 앱개발 하기 전에 백엔드 개발을 했던적이 있다. 백엔드를 처음 개발하는거였고, DB를 처음만지는거라 정말힘들었다. 그런데 제일 힘들었던건 설계다.
설계, 흐름, 동작 메커니즘, 알고리즘, 뭐 이런건 난 정말 별로 중요하게 생각 안했다. 알고리즘 같은건 PS만큼 복잡한 경우는 본적없어서 그렇게 생각했다 그런데 백엔드 DB설계를 하고, 프로덕션 개발을 하다보니까 설계가 얼마나 중요하게 작용하는지 알게되었다.
그래서 어느정도 개발한 이후부터 무언가 복잡한 상황을 심플하게 개선한 설계, 흐름등을 공유하고 싶어졌다. 솔직히 다들 코드 이쁘고 구조 이쁘거 보면 눈돌아가지 않나...
나만그런가...
뭐 그래서 종합하면 이 블로그를 만들게 된 원인을 정리하면 다음과 같다
개발할때 필연적으로 생기는 고민에 대해서 기록을 해보고 해결법을 작성하는 곳이 필요하게 되었다
뭐... 그렇다고...
말주변이 좀 없어서 말의 아귀가 잘 안맞을 수 있다. 더군다나 새벽 5시에 썼다 그래서 좀 글이 안읽힌다해도 괜찮다. 수능 국어 비문학 지문보다는 쉽게 쓰려고 노력 했으니 언젠가는 나아질것이다. 사실 보는사람도 없을 것 같지만...
정말 마지막으로 딱 한가지 이유가 더있었다.
원래... 개인 서버를 얻고 도메인도 얻은 이후에 프론트를 만들어서 호스팅하려고 했다. 그래도 나름 프론트엔드 개발자인데 토이 플젝은 힙하게 가야지!
그렇게 svelte + snowpack + ts + scss라는 힙함의 끝을 달리게 되었고... 도저히 끝날 기미가 보이지 않자 그냥... 일단 기록이라도 해두자라고 생각이 들었다.
욕심은 금물