๐Ÿ“ 37. React Native ํผ ์ฒ˜๋ฆฌ ์™„์ „ ์ •๋ฆฌ โ€” TextInput, ํ‚ค๋ณด๋“œ ์ฒ˜๋ฆฌ, Formik๊นŒ์ง€

JM_Devยท2025๋…„ 5์›” 15์ผ
post-thumbnail

React Native์—์„œ ํผ์„ ๋‹ค๋ฃฐ ๋•Œ
๋‹จ์ˆœํžˆ <TextInput />๋งŒ ์“ฐ๋ฉด ๋  ๊ฒƒ ๊ฐ™์ง€๋งŒ,
์‹ค์ œ๋กœ๋Š” ์ƒ๊ฐ๋ณด๋‹ค ์‹ ๊ฒฝ ์จ์•ผ ํ•  ํฌ์ธํŠธ๊ฐ€ ๋งŽ๋‹ค.

  • ํ‚ค๋ณด๋“œ๊ฐ€ ์˜ฌ๋ผ์™€์„œ ์ž…๋ ฅ์ฐฝ์„ ๊ฐ€๋ฆฐ๋‹ค
  • iOS/Android ํ‚ค๋ณด๋“œ ์ฒ˜๋ฆฌ ๋ฐฉ์‹์ด ๋‹ค๋ฅด๋‹ค
  • ์ž…๋ ฅ๊ฐ’์„ ๊ฒ€์ฆํ•ด์•ผ ํ•œ๋‹ค
  • ์—ฌ๋Ÿฌ ์ž…๋ ฅ์ฐฝ ๊ฐ„ ํฌ์ปค์Šค ์ด๋™์ด ํ•„์š”ํ•˜๋‹ค

์ด๋ฒˆ ๊ธ€์€ ๊ธฐ๋ณธ์ ์ธ TextInput ์‚ฌ์šฉ๋ฒ•๋ถ€ํ„ฐ
ํ‚ค๋ณด๋“œ ๋Œ€์‘, ์ƒํƒœ ๊ด€๋ฆฌ, ์œ ํšจ์„ฑ ๊ฒ€์ฆ๊นŒ์ง€ ํ•œ ๋ฒˆ์— ์ •๋ฆฌํ•œ ๊ธ€์ด๋‹ค.


โœ… ๊ธฐ๋ณธ: TextInput ์‚ฌ์šฉ๋ฒ•

import { TextInput, View } from 'react-native';
import { useState } from 'react';

export default function Login() {
  const [email, setEmail] = useState('');

  return (
    <View>
      <TextInput
        value={email}
        onChangeText={setEmail}
        placeholder="์ด๋ฉ”์ผ์„ ์ž…๋ ฅํ•˜์„ธ์š”"
        keyboardType="email-address"
        autoCapitalize="none"
        style={{
          borderWidth: 1,
          padding: 12,
          borderRadius: 8,
        }}
      />
    </View>
  );
}

๐Ÿง  ์œ ์šฉํ•œ TextInput ์†์„ฑ ์ •๋ฆฌ

์†์„ฑ์„ค๋ช…
placeholder์ž…๋ ฅ ์ „ ์•ˆ๋‚ด ๋ฌธ๊ตฌ
keyboardTypeํ‚ค๋ณด๋“œ ํƒ€์ž… (default, email-address, numeric)
secureTextEntry๋น„๋ฐ€๋ฒˆํ˜ธ ์ž…๋ ฅ ์ฒ˜๋ฆฌ
autoCapitalize์ž๋™ ๋Œ€๋ฌธ์ž ์„ค์ • (none, sentences)
returnKeyTypeํ‚ค๋ณด๋“œ์˜ Enter ํ‚ค ์Šคํƒ€์ผ
onSubmitEditingEnter ๋ˆŒ๋ €์„ ๋•Œ ์‹คํ–‰๋˜๋Š” ํ•จ์ˆ˜

๐Ÿ“ฑ ํ‚ค๋ณด๋“œ๊ฐ€ ์ž…๋ ฅ์ฐฝ์„ ๊ฐ€๋ฆด ๋•Œ ํ•ด๊ฒฐ๋ฒ•

import { KeyboardAvoidingView, Platform } from 'react-native';

<KeyboardAvoidingView
  behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
  style={{ flex: 1 }}
>
  {/* ์ž…๋ ฅ์ฐฝ๋“ค */}
</KeyboardAvoidingView>
  • KeyboardAvoidingView๋Š” ํ‚ค๋ณด๋“œ๊ฐ€ ์˜ฌ๋ผ์˜ฌ ๋•Œ ๋ทฐ์˜ ์œ„์น˜๋ฅผ ์กฐ์ ˆ
  • iOS์™€ Android์˜ ํ‚ค๋ณด๋“œ ๋™์ž‘์ด ๋‹ฌ๋ผ์„œ Platform.OS ๋ถ„๊ธฐ ์ฒ˜๋ฆฌ ํ•„์š”

๐Ÿ”„ ์—ฌ๋Ÿฌ ์ž…๋ ฅ์ฐฝ ๊ฐ„ ํฌ์ปค์Šค ์ด๋™

const secondInputRef = useRef(null);

<TextInput
  onSubmitEditing={() => secondInputRef.current?.focus()}
/>

<TextInput
  ref={secondInputRef}
/>
  • ์—”ํ„ฐ(๋‹ค์Œ) ์ž…๋ ฅ ์‹œ ๋‹ค์Œ ์ž…๋ ฅ์ฐฝ์œผ๋กœ ํฌ์ปค์Šค๋ฅผ ์ด๋™
  • ref๋ฅผ ์‚ฌ์šฉํ•ด ์ œ์–ด

โœ… Formik + Yup์œผ๋กœ ํผ ์ฒ˜๋ฆฌ ๋ฐ ๊ฒ€์ฆ ์ž๋™ํ™”

npm install formik yup
import { Formik } from 'formik';
import * as Yup from 'yup';

const schema = Yup.object().shape({
  email: Yup.string().email().required('์ด๋ฉ”์ผ์€ ํ•„์ˆ˜์ž…๋‹ˆ๋‹ค'),
});

<Formik
  initialValues={{ email: '' }}
  validationSchema={schema}
  onSubmit={(values) => console.log(values)}
>
  {({ handleChange, handleSubmit, values, errors }) => (
    <>
      <TextInput
        value={values.email}
        onChangeText={handleChange('email')}
        placeholder="์ด๋ฉ”์ผ"
      />
      <Text>{errors.email}</Text>

      <Button title="์ œ์ถœ" onPress={handleSubmit} />
    </>
  )}
</Formik>

โœ… ์ž๋™ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ
โœ… ๊ฐ„๋‹จํ•œ ์—๋Ÿฌ ์ฒ˜๋ฆฌ
โœ… handleChange, handleSubmit ๋“ฑ ์œ ํ‹ธ ์ œ๊ณต


๐Ÿ“ ๋‚ด๊ฐ€ ๋А๋‚€ ์ 

์ฒ˜์Œ์—” TextInput๋งŒ ๋„ฃ์œผ๋ฉด ๋‹ค ๋  ์ค„ ์•Œ์•˜๋Š”๋ฐ,
์‹ค์ œ ์•ฑ์—์„  ํ‚ค๋ณด๋“œ ๊ฐ€๋ฆผ ๋ฌธ์ œ, ์—”ํ„ฐ ์ด๋™, ์ž…๋ ฅ ๊ฐ’ ์œ ํšจ์„ฑ ๋“ฑ
์ž‘๊ณ  ๊ท€์ฐฎ์€ ๋ฌธ์ œ๋“ค์ด UX ์ „์ฒด๋ฅผ ๊ฒฐ์ •ํ•œ๋‹ค๋Š” ๊ฑธ ๋А๊ผˆ๋‹ค.

์ง€๊ธˆ์€ KeyboardAvoidingView + Formik + Yup ์กฐํ•ฉ์œผ๋กœ
ํผ ์ž…๋ ฅ์„ ํ‘œ์ค€ํ™”ํ•ด์„œ ๋งŒ๋“ค๊ณ  ์žˆ๋‹ค.


๐Ÿงพ "๋ชจ๋ฐ”์ผ UX๋Š” ํผ ์ž…๋ ฅ์—์„œ ๊ฐˆ๋ฆฐ๋‹ค. ์ž‘์ง€๋งŒ ์ค‘์š”ํ•˜๋‹ค."


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

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