오늘 배운 것

팀원들이 각자 할 일을 하고 있을 때, 나는 프론트에서 남은 기능상의 자잘한 버그들을 수정하기로 했다. 

 

기존의 팀원들과 나눠서 별도의 기능을 개발할 때, FlatList 기반의 UI Kitten에서 제공하는 List 컴포넌트를 써서 스크롤 기능도 구현했고, 다른 팀원은 DraggableFlatList 컴포넌트를 써서 리스트 컴포넌트를 드래그 앤 드롭하는 기능을 구현했었다. 문제는 이 둘을 합쳐서 스크롤 되면서도 드래그와 드롭이 되는 리스트를 구현하는 것이었다. 

 

기존의 투두를 나타내는 DailyTodo 컴포넌트는 View 컴포넌트로 감싸져 있었는데, 드래그와 드롭을 하려면 이 View를 ScaleDecorator로 감싸야 했다. 그러자 드래그 앤 드롭은 잘 동작하는 대신 잘 되던 스크롤 기능이 되지 않았고, 키보드가 활성화될 때 뷰가 그에 맞춰서 키보드를 피하는, KeyboardAvoidingView의 기능도 동작하지 않았다. 

 

Copilot의 도움으로, DraggableFlatList를 맨 바깥의 GestureHandlerRootView와 KeyboardAvoidingView로 감싸니 스크롤이 되었다! 문제는 키보드가 활성화되면서 텍스트 인풋 컴포넌트를 가린다는 점이었다... 이렇게 말이다. 저게 스크롤을 최대로 내린 것인데도 인풋 컴포넌트가 가려져서 나타나지 않는 상황이다. 

 

이전에 프론트 멘토님께 멘토링 받은 직후에는 Input 컴포넌트가 마치 카톡의 대화창 인풋 컴포넌트처럼 키보드 바로 위에 떴었다. 그때는 드래그 앤 드롭 구현 전이라 그 외의 별다른 문제는 없었었다. 코파일럿에게 물어보니, KeyboardAccessoryView를 사용해서 키보드가 활성화되면 항상 그 위에 나타나게 하고 싶은 컴포넌트를 감싸주었다. 

 

얼핏 보기에는 잘 된 것처럼 보였다. 그러나 키보드가 활성화되면 인풋 창이 저 맨 위로 가버리는 문제(...)가 있어서, 이 부분만 해결된다면 하위 이슈 하나는 완료될 것 같다. 


해결되었다!!

왜인지는 모르겠다.... 코파일럿과 GPT와 몇 번의 대화를 거친 후에 반신반의한 마음으로 적용해 보았다. 

 

일단 해결된 코드는 다음과 같다. 

return (
    <GestureHandlerRootView style={{ flex: 1 }}>
      <Fragment>
        <KeyboardAvoidingView behavior="padding" style={{ flex: 1 }}>
          <DraggableFlatList
            data={currentTodos}
            renderItem={renderTodo}
            onDragEnd={handleDragEnd}
            keyExtractor={item => item.id.toString()}
          />
        </KeyboardAvoidingView>
        <KeyboardAccessoryView alwaysVisible androidAdjustResize>
          <View style={styles.inputContainer}>
            <Input
              style={styles.input}
              placeholder="Add a new task"
              value={input}
              onChangeText={setInput}
              onSubmitEditing={handleSubmit}
            />
          </View>
        </KeyboardAccessoryView>
      </Fragment>
    </GestureHandlerRootView>
  );

 

문제를 해결한 과정(GPT 및 코파일럿과의 대화)은 다음과 같다. 

위의 문제 상황에서 이렇게 질문하니, 코파일럿은 KeyboardAccessoryView라는 서드파티 라이브러리를 추천해주었다. 말 그대로 키보드가 활성화될 때 보였으면 하는 컴포넌트를 KeyboardAccessoryView로 감싸면 키보드가 활성화될 때 그 안에 감싸진 컴포넌트를 보이게 해 주는 컴포넌트였다. 그리고 alwaysVisible 속성을 추가하면 키보드가 활성화되지 않아도 해당 컴포넌트가 보이게끔 해 주었다. 

알고보니 공식문서에 잘 나와있었다 머쓱

 

이제 이를 추가해서 Input 컴포넌트가 리스트에 가려지지 않고, 키보드가 활성화될 때도 보이게끔 하는 과정은 성공했다. 그 상황이 바로 위와 같은 상황(Input 컴포넌트가 보이긴 하는데 저 화면 위에 보이는 상황)이다. 이를 해결하기 위해서는 여러 번의 질문 끝에 다음과 같이 물어보았더니 잘 답해주었다. 

 

코드가 크게 변한 부분은 없었고, 해답은 KeyboardAccessoryView 컴포넌트에 androidAdjustResize 옵션을 추가하는 것이었다. 찾아보니 현재 사용하는 기기는 안드로이드 에뮬레이터이고 'android'가 앞에 붙은 걸로 봐서는 안드로이드 기기 한정으로 작동하는 기능일 것이라고 생각했다. 

 

ejected apps은 무엇일까?

공식문서를 잘 참고하자!

찾아보니 안드로이드 기기의 경우 아이폰과 다르게 작동하나보다. 저번에 프론트 멘토님과 멘토링 할 때도 이와 비슷한 문제로 android/app/src/main/AndroidMainfest.xml 파일의 androidAdjustResize 옵션을 변경해 본 적이 있었다. 뭔가 중요한 파일인 것 같아서 공식문서를 대강 봤는데 내용이 방대했다. 나는 그 중에서도 androidAdjustResize 옵션을 설정하는 부분이 아주 조금 궁금했으므로, 관련 문서만 아주 대강 훑어보았다. 

<activity android:windowSoftInputMode="adjustResize">
// 많은 설정들을 생략했다.

 

해당 코드는 <activity> 태그에 있었으므로, <activity> 부분의 문서만 보았다. 

 

해당 속성의 설명에 적힌 내용은 딱 내가 원하는 대로 작동하는 키보드의 모습이었다. 이렇게 2가지의 이슈(드래그 앤 드롭 적용했을 때 화면 스크롤도 되게 하기, Input 컴포넌트가 항상 키보드 바로 위에서 활성화되게 하기)를 해결하였다. 

 

궁금한 점들

1. "VirtualizedLists should never be nested inside plain ScrollViews with the same orientation because it can break windowing and other functionality - use another VirtualizedList-backed container instead." 이 오류는 왜 나는 걸까? ScrollView와 FlatList 모두 스크롤 가능한 리스트 뷰를 제공하는 게 아닌가? 둘의 차이점이 뭐길래 FlatList로 컴포넌트를 감싸면 이런 오류가 없는데 ScrollView로 감싸면 이런 오류가 뜨는 것인지 궁금하다. 

2. (이 포스트와 관련은 없지만) 왜 react hook 함수는 컴포넌트 내부와 다른 react hook 함수 내부에서만 사용할 수 있게 제한을 걸어 놓았을지도 궁금하다. 

 

+ Recent posts