๐Ÿ“ 55. React Native ์‚ฌ์šฉ์ž ์ž…๋ ฅ UX ์ตœ์ ํ™” ์ „๋žต โ€” TextInput, ํ‚ค๋ณด๋“œ ์ฒ˜๋ฆฌ, ํฌ์ปค์Šค ์ด๋™๊นŒ์ง€

JM_Devยท2025๋…„ 6์›” 25์ผ
0
post-thumbnail

์•ฑ์—์„œ ๊ฐ€์žฅ ๋งŽ์ด ์‚ฌ์šฉ๋˜๋Š” ์ปดํฌ๋„ŒํŠธ ์ค‘ ํ•˜๋‚˜๋Š”
๋ฐ”๋กœ TextInput์ด๋‹ค.
ํ•˜์ง€๋งŒ ๊ธฐ๋ณธ ์‚ฌ์šฉ๋งŒ์œผ๋กœ๋Š” ๋ถˆํŽธํ•œ ์ž…๋ ฅ UX,
์˜ˆ๋ฅผ ๋“ค์–ด ํ‚ค๋ณด๋“œ์— ๊ฐ€๋ ค์ง€๋Š” ์ž…๋ ฅ์ฐฝ,
ํฌ์ปค์Šค๊ฐ€ ์•ˆ ๋„˜์–ด๊ฐ€๋Š” ๋ฌธ์ œ ๋“ฑ์ด ์ƒ๊ธด๋‹ค.

์ด๋ฒˆ ๊ธ€์€ React Native์—์„œ ์‚ฌ์šฉ์ž ์ž…๋ ฅ ๊ฒฝํ—˜์„ ์ตœ์ ํ™”ํ•˜๋Š” ์ „๋žต์„ ์ •๋ฆฌํ•œ ๊ธ€์ด๋‹ค.


โœ… TextInput ๊ธฐ๋ณธ ์‚ฌ์šฉ ์˜ˆ์‹œ

<TextInput
  value={email}
  onChangeText={setEmail}
  placeholder="์ด๋ฉ”์ผ์„ ์ž…๋ ฅํ•˜์„ธ์š”"
  keyboardType="email-address"
  autoCapitalize="none"
  returnKeyType="next"
/>

์ฃผ์š” ์†์„ฑ

  • keyboardType: ์ž…๋ ฅ ํ‚ค๋ณด๋“œ ์ข…๋ฅ˜ (default, numeric, email-address, ...)
  • autoCapitalize: ์ž๋™ ๋Œ€๋ฌธ์ž ์„ค์ • (none, sentences, ...)
  • returnKeyType: ๋‹ค์Œ/์™„๋ฃŒ ๋ฒ„ํŠผ UI ๋ณ€๊ฒฝ
  • secureTextEntry: ๋น„๋ฐ€๋ฒˆํ˜ธ ์ž…๋ ฅ ์‹œ ์‚ฌ์šฉ

๐Ÿ”„ ํฌ์ปค์Šค ์ด๋™ ์ฒ˜๋ฆฌ

const emailRef = useRef(null);
const passwordRef = useRef(null);

<TextInput
  ref={emailRef}
  returnKeyType="next"
  onSubmitEditing={() => passwordRef.current?.focus()}
/>

<TextInput
  ref={passwordRef}
  returnKeyType="done"
/>

โœ… ๋กœ๊ทธ์ธ/ํšŒ์›๊ฐ€์ž… ํ™”๋ฉด์—์„œ ์ž์ฃผ ์‚ฌ์šฉ
โœ… ํ‚ค๋ณด๋“œ์—์„œ '๋‹ค์Œ' ๋ˆŒ๋ €์„ ๋•Œ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์ด๋™


๐Ÿงท ํ‚ค๋ณด๋“œ ๊ฐ€๋ฆผ ๋ฐฉ์ง€ ์ฒ˜๋ฆฌ

1. KeyboardAvoidingView

<KeyboardAvoidingView behavior="padding">
  <ScrollView>
    <TextInput />
  </ScrollView>
</KeyboardAvoidingView>
  • iOS์—์„œ๋Š” padding, Android๋Š” height ์ถ”์ฒœ
  • ๋ฐ˜๋“œ์‹œ ScrollView ๋˜๋Š” View๋กœ ๋ž˜ํ•‘ ํ•„์š”
  • ํ™”๋ฉด์ด ๊ธธ์–ด์งˆ์ˆ˜๋ก ํ•„์ˆ˜ ์ ์šฉ

2. KeyboardAwareScrollView (๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ)

npm install react-native-keyboard-aware-scroll-view
  • ๋” ๊ฐ•๋ ฅํ•œ ํ‚ค๋ณด๋“œ ๊ฐ์ง€ + ์Šคํฌ๋กค ๋™์ž‘ ์ œ๊ณต

โœ… ์ž…๋ ฅ ์ƒํƒœ ๋ฐ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ

const [email, setEmail] = useState('');
const [error, setError] = useState('');

useEffect(() => {
  const emailRegex = /\S+@\S+\.\S+/;
  setError(emailRegex.test(email) ? '' : '์˜ฌ๋ฐ”๋ฅธ ์ด๋ฉ”์ผ ํ˜•์‹์ด ์•„๋‹™๋‹ˆ๋‹ค.');
}, [email]);

โœ… ์‹ค์‹œ๊ฐ„ ํ”ผ๋“œ๋ฐฑ
โœ… ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€ ์ถœ๋ ฅ โ†’ UX ์นœ์ ˆ๋„ ์ƒ์Šน


๐ŸŽจ UX ํ–ฅ์ƒ์„ ์œ„ํ•œ ํŒ

ํ•ญ๋ชฉ์ „๋žต
placeholder ์ปฌ๋ŸฌplaceholderTextColor="#999" ๋“ฑ ๋ช…ํ™•ํžˆ ์ง€์ •
ํ„ฐ์น˜ ์‹œ ํ‚ค๋ณด๋“œ ๋‹ซ๊ธฐTouchableWithoutFeedback + Keyboard.dismiss() ์กฐํ•ฉ
์—๋Ÿฌ ๋ฉ”์‹œ์ง€ UI์ž…๋ ฅ์ฐฝ ์•„๋ž˜์— ์ž‘๊ฒŒ ํ‘œ์‹œ, ์ƒ‰์ƒ์€ ๋ถ‰์€ ๊ณ„์—ด
์ž…๋ ฅ ์™„๋ฃŒ ์‹œ ์ฒ˜๋ฆฌonSubmitEditing์œผ๋กœ ๋ฒ„ํŠผ ํด๋ฆญ ์—†์ด๋„ ์ „์†ก ๊ฐ€๋Šฅ

๐Ÿง  ๋‚ด๊ฐ€ ๋А๋‚€ ์ 

์ฒ˜์Œ์—๋Š” TextInput๋งŒ ๋„ฃ์–ด๋„ ๋˜๋Š” ์ค„ ์•Œ์•˜๋Š”๋ฐ
๋ง‰์ƒ ์œ ์ € ์ž…์žฅ์—์„œ ์จ๋ณด๋‹ˆ
ํฌ์ปค์Šค๊ฐ€ ์•ˆ ๋„˜์–ด๊ฐ€๊ณ , ํ‚ค๋ณด๋“œ๊ฐ€ ๋ฒ„ํŠผ์„ ๊ฐ€๋ฆฌ๊ณ ,
์ž…๋ ฅ ์—๋Ÿฌ๊ฐ€ ๋ญ”์ง€๋„ ์•ˆ ์•Œ๋ ค์ฃผ๋Š” ์•ฑ์€ ๋‹ต๋‹ตํ•œ UX ๊ทธ ์ž์ฒด์˜€๋‹ค.

์ง€๊ธˆ์€ ๊ธฐ๋ณธ์ ์œผ๋กœ

  • ์ž…๋ ฅ ํฌ์ปค์Šค ๊ด€๋ฆฌ
  • ํ‚ค๋ณด๋“œ ํšŒํ”ผ ์ฒ˜๋ฆฌ
  • ์ƒํƒœ ๊ธฐ๋ฐ˜ ์œ ํšจ์„ฑ ์ฒดํฌ
    ๋ฅผ ๋ชจ๋‘ ํฌํ•จํ•ด์„œ ์ž…๋ ฅ ํ๋ฆ„ ์ž์ฒด๋ฅผ ํ•˜๋‚˜์˜ UX ๋‹จ์œ„๋กœ ์„ค๊ณ„ํ•˜๊ณ  ์žˆ๋‹ค.

โœ๏ธ โ€œ์ž…๋ ฅ์€ ๊ธฐ๋Šฅ์ด ์•„๋‹ˆ๋ผ ํ๋ฆ„์ด๋‹ค. ๊ทธ ํ๋ฆ„์ด ๋ถ€๋“œ๋Ÿฌ์šธ์ˆ˜๋ก ์•ฑ์€ ์ข‹์•„์ง„๋‹ค.โ€


profile
๊ฐœ๋ฐœ์ž๋กœ ์ทจ์—…์„ ์ค€๋น„ ์ค‘ ์ด๋ฉฐ, ์—ด์‹ฌํžˆ ๊ณต๋ถ€ ์ค‘ ์ž…๋‹ˆ๋‹ค!

0๊ฐœ์˜ ๋Œ“๊ธ€