React Native 멘션 스타일링에 성공적으로 실패하기

Oort 오르트
newneek
Published in
9 min readDec 19, 2023

안녕하세요, 뉴닉의 프론트엔드 엔지니어 오르트☀️입니다.

뉴닉에서 새로운 커뮤니티 서비스를 오픈했어요! 아시다시피 기존에도 뉴니커끼리 소통할 수 있는 ‘뉴문뉴답’이라는 공간이 존재했는데요. ‘뉴니커가 묻고, 뉴니커가 답한다’라는 컨셉으로 질문과 답변을 주고받는 곳이었지요. 여기에서 지식의 확장에 초점을 맞추어, 조금 더 자유롭고 풍부한 대화를 나눌 수 있는 장을 만들어보았어요. (뉴닉의 지식 교환 커뮤니티에 놀러 오세요 🙌)

이번 포스팅은 바로 이 커뮤니티 공간을 새로 만들면서 마주했던 기술적인 문제에 관한 이야기예요. 개인적으로는 조금 특별한 이슈여서 여러분께도 공유해보려고 해요.

1. 띵동! 유저 멘션 기능이 도착했습니다 🔔

제가 맡은 파트에는 유저 멘션 기능이 있었어요.
메이트(커뮤니티 안에서 뉴니커를 부르는 이름)가 다른 메이트를 언급할 수 있는 기능으로, 다른 서비스에서도 흔히 쓰이고 있어서 익숙하실 거예요.

이 ‘유저 멘션’ 기능의 요구 사항은 크게 두 가지였는데요.

  1. ‘@’ 를 입력하면 멘션 가능한 메이트들을 노출하여 선택할 수 있게 해주세요.
  2. 답글을 입력하는 창에서 일반 텍스트는 검은색으로, 멘션한 메이트의 닉네임은 오렌지색으로 표시해주세요.

마침 이 요구 사항을 모두 충족하는 라이브러리(react-native-controlled-mentions)를 발견하여 개발하는 데 큰 문제는 없을 것 같았어요.
멘션 상태를 활성화할 수 있는 트리거 문자도 정할 수 있었고, 멘션 텍스트에 대한 스타일 역시 수월하게 적용할 수 있었지요.
요청받은 내용을 구현하기 위해 만들어진 듯 아주 적합한 라이브러리처럼 보였어요. 사실은 그렇지 않았지만요…

2. 한글은 어려우세요 🙏

멘션 후 영문을 입력하면 올바르게 스타일링 되었는데, 문제는 한글을 입력할 때 발생했어요. 요구 사항 2번인 색상 변경이 되지 않고 그대로 출력되는 거예요.
심지어는 영문으로 작성하다가 한글 자음을 연속으로 작성하면 해당 문자에 다시 멘션 스타일이 적용되기까지 했어요.
처음엔 라이브러리에 오류가 있는 걸까 생각했지만 그렇다기에는 영문일 경우 잘 작동되는 점이 이상했어요.

그래서 해당하는 TextInput 컴포넌트를 배열에 담아 로그를 찍어보니, style에 명시된 컬러 코드가 다른데도 하나의 색상으로 표시되고 있다는 걸 알게 되었어요.

컴포넌트에 새로운 컬러 코드가 적용됐음에도 불구하고 그렇게 보이지 않았기 때문에, 렌더링에 문제가 있겠다는 추론을 하게 되었어요.

3. 문제의 축복이 끝이 없네 🤔

출처: 모비딕 Youtube

첫 번째로 시도한 방법은 의도적으로 재렌더링시키기였어요.
TextInput 컴포넌트의 key를 조작해 보기도 하고, 상위 컴포넌트의 state를 변경시켜 보기도 하는 등 여러 가지 방법을 적용해 보았지만 무시할 수 없는 부작용이 있었어요.
재렌더링이 발생하는 순간 유저가 텍스트를 입력하게 되면 자모음이 분리되거나 입력값이 유실될 수 있는 위험이 있었던 거예요.

두 번째는 컴포넌트를 분리하여 입력만 TextInput에서 하고 출력은 일반 View에 하는 방식을 시도해 보았는데요.

<TextInput
{...textInputProps}
style={[styles.input, { color: 'transparent' }]}
/* TextInput에 입력되는 값은 투명하게 */
/>
{
/*
TextInput과 정확히 겹치는 Pressable View를 생성하고,
해당 View를 눌렀을 때 TextInput이 조작되도록 함
*/}
<Pressable
style={[
styles.input,
{ position: 'absolute', left: INPUT_CONTAINER_MARGIN_LEFT },
]}
onPress={() => refInput.current.focus()}
onLongPress={() => refInput.current.focus()}
>
{renderingTextInputValue()} {/* TextInput의 값을 여기에 렌더링 */}
</Pressable>

우선 TextInput에 입력되는 값은 투명하게 표시한 후, 해당 값을 표출하는 Pressable View를 생성하여 TextInput을 덮도록 했어요.
그리고 제대로 스타일링 된 텍스트가 담긴 컴포넌트를 리턴해주는 함수를 정의하여 Pressable View에 표출시켰어요.

과연 이 트릭의 결과는 어땠을까요?

결과는 성공적인 것처럼 보였어요!

멘션 텍스트도 잘 인식하고, 무엇보다 한글을 입력하더라도 의도한 스타일링이 유지되었어요.
재렌더링보다 안정적인 흐름에 마음을 놓고 드디어 QA에 들어갈 수 있었어요.

그러나 이 문제와의 인연은 아직 끝나지 않았고…

아무래도 컴포넌트 고유 속성을 그대로 재현해 낼 수는 없었어요.

TextInput은 정의된 높이를 넘어가게 되면 스크롤이 생기는 반면, View는 그렇지 않아서 긴 글을 커버하기에는 어려움이 있었지요.
또한 수정할 때 커서를 옮기는 과정, 단어 선택을 위한 더블탭 등의 케이스에서 TextInput과 동일한 경험을 주지는 못했어요.

ScrollView를 사용해 보기도 하고 TextInput 두 개를 겹쳐 포커스 아웃을 유도해 보았지만, 개행이 발생하는 순간 스크롤의 싱크를 정확하게 맞춰주는 부분이 매끄럽지 않았어요.

이외에도 여러 솔루션을 시도해 보았지만 결국 위의 요구 사항을 충족하는 동시에 부드러운 사용감을 제공하는 것에는 실패했어요.

4. 이제는 더 이상 물러날 곳이 없다 ❌

출처: MBC 무한도전

돌고 돌아 다시 원점부터 출발해 보기로 했어요.

“왜 영어는 잘 작동하는데 한글에서만 이런 문제가 발생하는 걸까?”

“왜 컴포넌트에 스타일은 적용되었는데 화면에서는 그렇게 보이지 않을까?”

의문을 품고 이리저리 검색해 보았더니 비슷한 이슈를 겪고 있는 분들이 계시더라고요.

[IOS] text color is changed

TextInput is unstable for Korean. (iOS only)

Styling TextInput toggles between default and applied font styling for CJK characters on iOS in RN 0.63

React Native에는 CJK(Chinese, Japanese, Korean) 언어에 대한 이슈가 지속적으로 존재하고 있었어요.

지금 겪고 있는 문제 역시 관련이 있다는 사실도 알 수 있었지요.

한글의 자모음 분리, 입력 시 들썩임 등 이미 해결된 이슈도 있었지만, 그동안의 히스토리를 봤을 때 해당 이슈가 빠르게 처리되지 않을 것 같다는 판단이 되었어요.

커뮤니티 개발 건에 할당된 일정이 얼마 남지 않았던 터라 제품셀 PM인 뉴에게 이 상황을 공유했고, 결론적으로 이 문제는 백로그로 남아 일단락되었어요.

글을 작성하는 시점에서는 사용자가 의도를 갖고 행동(멘션)하기 때문에, 별도의 스타일링이 들어가지 않더라도 큰 문제는 없을 거라는 이유였어요.

5. 중요한 건 꺾였는데도 그냥 하는 마음 💪

출처: 할명수 Youtube

우여곡절의 결과 끝에 지금의 멘션 기능이 릴리즈되었어요!

멘션 기능이 릴리즈된 후, 조금의 여유를 갖고 원인 파악에 나설 수 있었는데요.
그때 이 문제에 대해 가장 큰 도움을 준 글을 발견하게 되었어요. (드디어!)
해당 이슈를 올려주신 버나드 님은 이전에도 React Native TextInput 한국어 입력 관련한 기여를 하셨기에, ‘혹시 이분이라면?’하는 마음으로 메일을 한 통 드렸어요.

감사하게도 자세한 답변을 받아볼 수 있었어요.

버나드 님의 말씀처럼 iOS에서 받아쓰기(Speech-to-text) 기능을 이용해 보니 영문에서도 스타일링이 적용되지 않고 있더라고요.

덕분에 React Native 프레임워크의 문제라는 것을 더 확신할 수 있게 되었어요.

이제 이 문제를 위해 제가 할 수 있는 일은 하나였어요. 바로 깃허브 이슈 등록!

나중에라도 메이트들이 답글을 작성할 때 스타일링이 적용된 멘션을 볼 수 있었으면 하는 마음으로 등록해 보았어요.
아무래도 처음 기획대로 구현되지 않았다 보니 개인적으로 아쉬움이 남기도 했고요.
만약 이슈가 해결되어 추후에 업데이트가 가능해진다면 꼭 다시 알려드릴게요.

이번 작업을 회고해보면 개발자로서 참 좋은 경험이었다는 생각이 들어요.

원인 파악을 위해 깊게 파고들어 보고, 외부 개발자분께 조언을 구하고, 깃허브 이슈 등록까지 해보았으니까요.
최선을 다했음에도 문제가 해결되지 않았을 때는 어떤 행동을 취할 수 있는지 배울 수 있었어요.

멘션 기능 하나에도 이야기가 꽤 길어졌는데, 여러분은 읽으면서 어떠셨나요?
혹시 궁금한 점이 생기셨다면 뉴닉의 커뮤니티에 오셔서 마음껏 남겨주세요.

뉴닉이 야심차게 준비한 커뮤니티, 바로 이 곳에서 기다리고 있을게요!

--

--

Oort 오르트
newneek
Editor for

안녕하세요. 뉴닉의 프론트엔드 엔지니어 오르트라고 합니다!