플러터 강좌: 11.4 TextField 위젯

플러터(Flutter)는 구글이 개발한 오픈 소스 UI 소프트웨어 개발 키트(SDK)로, 모바일, 웹, 데스크탑 앱을 만들기 위해 사용됩니다. 이 강좌에서는 플러터의 UI 구성 요소 중 하나인 TextField 위젯에 대해 살펴보겠습니다. TextField는 사용자로부터 텍스트 입력을 받을 수 있는 기본 위젯입니다. 이제 TextField 위젯의 기본적인 사용법 및 다양한 기능, 사용자 정의 방법에 대해 자세히 알아보겠습니다.

1. TextField의 기본 구조

TextField 위젯은 사용자의 입력을 받기 위해 사용되는 기본적인 입력 필드입니다. 이를 사용하기 위해서는 다음과 같은 기본 구조로 위젯을 생성할 수 있습니다:

TextField(
  decoration: InputDecoration(
    border: OutlineInputBorder(), // 입력 필드에 대한 테두리 스타일
    labelText: '입력할 텍스트',   // 레이블 텍스트
    hintText: '여기에 입력하세요',   // 힌트 텍스트
  ),
  onChanged: (text) {
    // 텍스트가 변경될 때 호출되는 콜백
    print('입력한 텍스트: $text');
  },
)

여기서 decoration 속성은 입력 필드의 외관을 정의합니다. labelText는 입력 필드의 레이블을 정의하며, hintText는 입력 필드에 placeholder와 같은 역할을 합니다. onChanged 프로퍼티는 사용자가 텍스트를 입력할 때마다 호출되는 콜백 함수입니다.

2. TextField 위젯의 주요 속성

TextField 위젯에는 몇 가지 중요한 속성이 있으며, 이 속성을 통해 위젯의 행동과 외관을 더욱 세밀하게 조정할 수 있습니다. 다음은 가장 자주 사용하는 속성입니다:

  • controller: TextEditingController의 인스턴스를 사용하여 입력 필드의 현재 상태를 추적합니다.
  • obscureText: 비밀번호와 같은 보안 입력을 제공하기 위해 텍스트를 숨기려면 true로 설정합니다.
  • keyboardType: 입력할 수 있는 키보드의 유형을 설정하여 사용자 경험을 향상시킵니다.
  • maxLines: 입력 가능한 최대 줄 수를 설정합니다.
  • onSubmitted: 사용자가 입력을 완료하고 제출할 때 호출되는 콜백입니다.

이 속성들을 어떻게 사용하는지 보시죠:

TextField(
  controller: myController,
  obscureText: true,
  keyboardType: TextInputType.emailAddress, 
  maxLines: 1, 
  onSubmitted: (value) {
    print('사용자가 입력한 값: $value');
  },
)

3. TextEditingController 사용하기

입력 필드와 관련된 데이터와 상태를 관리하기 위해 TextEditingController를 사용할 수 있습니다. 이를 통해 입력 필드에서 값을 가져오거나 설정할 수 있습니다. 다음은 TextEditingController의 사용 예시입니다:

class MyTextFieldWidget extends StatefulWidget {
  @override
  _MyTextFieldWidgetState createState() => _MyTextFieldWidgetState();
}

class _MyTextFieldWidgetState extends State {
  TextEditingController myController = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        TextField(
          controller: myController,
          decoration: InputDecoration(
            border: OutlineInputBorder(),
            labelText: '이메일을 입력하세요',
          ),
        ),
        ElevatedButton(
          onPressed: () {
            print('입력한 이메일: ${myController.text}');
          },
          child: Text('제출'),
        ),
      ],
    );
  }

  @override
  void dispose() {
    // 위젯을 제거할 때, 컨트롤러를 해제하여 메모리 누수를 방지합니다.
    myController.dispose();
    super.dispose();
  }
}

4. 다양한 TextField 유형

이제 TextField의 다양한 유형에 대해 알아보겠습니다. 기본적인 입력 필드 외에도 여러 가지 유형을 통해 입력 필드를 사용자 맞춤형으로 설정할 수 있습니다.

4.1. 비밀번호 입력 필드

비밀번호 입력 필드를 생성하려면 obscureText 속성을 true로 설정합니다. 아래는 비밀번호 입력 필드의 예입니다:

TextField(
  obscureText: true,
  decoration: InputDecoration(
    border: OutlineInputBorder(),
    labelText: '비밀번호를 입력하세요',
  ),
)

4.2. 이메일 주소 입력 필드

이메일을 입력 받을 때는 keyboardTypeTextInputType.emailAddress로 설정하여 이메일 전용 키보드를 표시합니다:

TextField(
  keyboardType: TextInputType.emailAddress,
  decoration: InputDecoration(
    border: OutlineInputBorder(),
    labelText: '이메일을 입력하세요',
  ),
)

4.3. 멀티라인 입력 필드

여러 줄의 텍스트 입력을 지원하려면 maxLines 속성을 설정합니다:

TextField(
  maxLines: 5,
  decoration: InputDecoration(
    border: OutlineInputBorder(),
    labelText: '여기에 내용을 입력하세요',
  ),
)

5. TextField 스타일링

입력 필드를 더 아름답고 직관적으로 만들기 위해 다양한 속성을 통해 스타일링 할 수 있습니다. InputDecoration의 속성을 사용해볼까요?

  • fillColor: 입력 필드의 배경색을 설정합니다.
  • focusedBorder: 입력 필드가 포커스를 받을 때의 테두리 스타일을 설정합니다.
  • enabledBorder: 입력 필드가 활성 상태일 때의 테두리 스타일을 설정합니다.
  • errorText: 입력 에러 발생 시 보여줄 텍스트를 설정합니다.

예시는 다음과 같습니다:

TextField(
  decoration: InputDecoration(
    fillColor: Colors.lightBlueAccent,
    filled: true,
    focusedBorder: OutlineInputBorder(
      borderSide: BorderSide(color: Colors.green, width: 2.0),
    ),
    enabledBorder: OutlineInputBorder(
      borderSide: BorderSide(color: Colors.blue, width: 2.0),
    ),
    errorText: '잘못된 입력입니다',
  ),
)

6. TextField의 검증 및 유효성 검사

사용자가 입력한 텍스트의 유효성을 검사하기 위해 간단한 검증 로직을 추가할 수 있습니다. 예를 들어, 이메일 형식에 대한 기본 검증을 수행할 수 있습니다:

String? validateEmail(String? value) {
  if (value == null || value.isEmpty) {
    return '이메일을 입력하세요';
  }
  String pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$';
  RegExp regex = RegExp(pattern);
  if (!regex.hasMatch(value)) {
    return '유효한 이메일 형식이 아닙니다';
  }
  return null;
}

TextField(
  decoration: InputDecoration(
    errorText: validateEmail(myController.text),
  ),
)

7. TextField와 TextFormField

입력 필드의 유효성 검사와 상태 관리를 보다 효율적으로 처리하기 위해 TextFormField 위젯을 사용할 수 있습니다. TextFormFieldForm 위젯과 함께 사용되며, 더 나은 유효성 검사와 상태 관리를 제공합니다:

Form(
  child: Column(
    children: [
      TextFormField(
        decoration: InputDecoration(labelText: '이메일을 입력하세요'),
        validator: validateEmail,
      ),
      ElevatedButton(
        onPressed: () {
          // submit 로직
        },
        child: Text('제출'),
      ),
    ],
  ),
)

8. TextField와 FocusNode

입력 필드에 포커스를 제어하기 위해 FocusNode를 사용할 수 있습니다. 포커스를 제어하여 특정 액션을 수행하거나 입력을 관리할 수 있습니다:

FocusNode myFocusNode = FocusNode();

@override
void initState() {
  super.initState();
  myFocusNode.addListener(() {
    print('포커스 상태 변경: ${myFocusNode.hasFocus}');
  });
}

@override
Widget build(BuildContext context) {
  return TextField(
    focusNode: myFocusNode,
    decoration: InputDecoration(labelText: '포커스를 테스트하세요'),
  );
}

9. 결론

이번 강좌에서는 플러터의 TextField 위젯에 대해 깊이 있게 살펴보았습니다. TextField는 매우 기본적인 UI 구성 요소로, 사용자로부터 입력을 받아야 하는 모든 앱에서 필수적으로 사용됩니다. 다양한 속성과 기능들을 통해 더욱 직관적이고 유용한 사용자 경험을 제공할 수 있습니다.

플러터를 활용하여 모바일 및 웹 애플리케이션을 개발하면서 TextField의 다양한 활용을 통해 사용자 인터페이스를 보다 매력적으로 만들 수 있습니다. 이 강좌가 여러분의 플러터 개발에 도움이 되었기를 바랍니다!