[FIX] 입력 모달 키보드 대응 개선 및 완료 키 저장 동작 제거#63
Conversation
sunm2n
left a comment
There was a problem hiding this comment.
iOS에서 키보드 애니메이션과 모달 위치 미싱크
파일: components/ui/title-edit-modal.tsx, app/(tabs)/(folder)/index.tsx
문제:
두 파일 모두 keyboardDidShow 이벤트를 사용해 모달 위치를 조정합니다. iOS에서
keyboardDidShow는 키보드 애니메이션이 완전히 끝난 뒤 (~300ms 후) 에야
발생합니다. 기존 KeyboardAvoidingView는 내부적으로 keyboardWillChangeFrame을
사용해 애니메이션 시작 시점에 동기화됩니다.
증상:
- iOS에서 TextInput 포커스 시 키보드가 올라오는 300ms 동안 모달은 제자리에
있다가, 애니메이션이 끝난 순간 위치가 순간이동 함 - 기존의 자연스러운 키보드 연동 UX가 깨짐
제안:
// keyboardDidShow 대신 keyboardWillShow 사용
Keyboard.addListener('keyboardWillShow', (event) => { // iOS 전용
setKeyboardInset(event.endCoordinates.height);
});
// Android는 keyboardWillShow가 없으므로 Platform 분기 필요
Keyboard.addListener(
Platform.OS === 'ios' ? 'keyboardWillShow' : 'keyboardDidShow',
(event) => setKeyboardInset(event.endCoordinates.height)
);
| returnKeyType="done" | ||
| onSubmitEditing={Keyboard.dismiss} | ||
| maxLength={50} | ||
| autoFocus |
There was a problem hiding this comment.
TextInput에 autoFocus가 새로 추가됐는데
handleEditName(line 111)에 이미 setTimeout(() => renameInputRef.current?.focus(), 100)
이 있습니다.
실제로는 중복 포커스 시도가 발생합니다.
대부분의 경우 무해하지만 autoFocus 하나만 두거나 setTimeout 하나만 두는 게 더 명확하지 않을까 합니다.
There was a problem hiding this comment.
피드백 감사합니다!
확인해보니 TextInput의 autoFocus와 handleEditName 내부의 setTimeout(() => renameInputRef.current?.focus(), 100)가 함께 존재해서, 모달이 열릴 때 포커스 시도가 중복으로 발생하고 있었습니다.
대부분의 경우 동작상 문제는 없겠지만, 이번 수정 범위가 키보드 표시 시점과 모달 위치 동기화에 관련되어 있기 때문에 포커스 트리거가 두 군데에 나뉘어 있으면 키보드 이벤트 발생 흐름을 추적하기 어려워질 수 있다고 판단했습니다.
그래서 선언적으로 의도가 드러나는 autoFocus만 남기고, 100ms 지연 후 수동으로 focus를 호출하던 로직은 제거했습니다. 이렇게 하면 모달이 렌더링된 뒤 TextInput이 스스로 포커스를 요청하는 구조가 되어 더 명확하고, 불필요한 타이머 의존도도 없앨 수 있습니다.
There was a problem hiding this comment.
테스트하며 추가 확인 결과, autoFocus만 남기는 방향은 일부 모달 전환 케이스에서 안정적이지 않았습니다.
특히 폴더명 수정 모달은 컨텍스트 메뉴 Modal에서 수정 Modal을 다시 여는 구조라, visible 상태 변경 시점과 네이티브 모달이 실제로 표시되는 시점이 어긋날 수 있었습니다. 이 경우 autoFocus가 기대대로 동작하지 않아 키보드가 올라오지 않는 현상이 확인되었습니다.
그래서 최종적으로는 포커스 트리거를 하나만 유지하되, autoFocus가 아니라 Modal의 onShow 시점에 수동 focus를 실행하는 방식으로 수정했습니다. onShow 이후 100ms 뒤 TextInput에 focus를 요청하도록 하여, 모달이 실제로 표시된 뒤 키보드가 올라오도록 했습니다.
같은 문제가 제목 수정 모달에서도 간헐적으로 발생할 수 있어, 제목 수정 모달과 폴더명 수정 모달 모두 동일한 방식으로 맞췄습니다. 또한 저장/취소/언마운트 시 예약된 focus timer가 뒤늦게 실행되지 않도록 cleanup도 함께 추가했습니다.
피드백 감사합니다! 제안해주신 특히 iOS는 Android에 비해 키보드 전환 애니메이션이 더 길고 부드럽게 표현되는 편이라, 모달 위치 변경이 키보드 애니메이션과 어긋날 경우 사용자가 더 부자연스럽게 느낄 수 있다고 판단했습니다. 그래서 단순히 이벤트 시점만 앞당기는 것보다, 모달의 bottom inset 변경도 키보드 애니메이션 타이밍에 맞추는 방향을 선택했습니다. 그래서 iOS에서는 Android는 수정 내용은 다음과 같습니다.
|
|
변경 확인했습니다! 수고하셨습니다! |
|
66f3026 |
Closes #54
개요
입력 모달에서 키보드 노출 시 입력창과 저장/취소 버튼이 가려지는 문제를 개선하고, 키보드의 완료/done 키로 저장이 실행되는 동작을 제거했습니다.
기존 제목 수정 모달과 폴더명 수정 모달은 화면 하단에 붙어 표시되는 구조라 Android 키보드가 올라왔을 때 모달 영역이 가려질 수 있었습니다. 이번 작업에서는 키보드 show/hide 이벤트를 기준으로 모달 하단 여백을 직접 조정해, 키보드가 올라온 상태에서도 입력창과 버튼을 확인할 수 있도록 보완했습니다.
또한 URL 제목 저장 모달, 링크 제목 수정 모달, 폴더명 수정 모달에서
TextInput의 완료/done 키가 저장 핸들러를 실행하지 않도록 변경했습니다. 이제 실제 저장은 모달 내부의저장버튼을 눌렀을 때만 실행됩니다.Android 환경에서는 하단 시스템 내비게이션 바가 표시되는 경우 모달의 버튼 영역이 일부 가려질 수 있어, 모달의 기본 하단 위치에 안전 여백을 적용했습니다. 키보드가 닫힌 뒤에도 이 보정된 위치로 복귀하도록 처리해 하단 메뉴바와 겹치지 않도록 개선했습니다.
주요 구현 내용
ScrollView로 감싸 작은 화면 대응 보완Keyboard.dismiss만 실행하도록 변경파일별 역할
components/ui/link-save-modal.tsx: URL 제목 저장 모달에서 완료/done 키 입력 시 저장 대신 키보드만 닫히도록 수정components/ui/title-edit-modal.tsx: 링크 제목 수정 모달의 키보드 대응, 하단 위치 보정, 완료 키 저장 동작 제거app/(tabs)/(folder)/index.tsx: 폴더명 수정 모달의 키보드 대응, 하단 위치 보정, 완료 키 저장 동작 제거해결한 이슈 목록
TextInput완료 키 동작 확인TextInput완료 키 동작 확인TextInput완료 키 동작 확인onSubmitEditing에 저장 핸들러가 연결된 지점 확인저장버튼을 눌렀을 때만 실행되도록 유지체크 사항
Screenshots or Video