팀 프로젝트의 입력 검증 로직을 중심으로, Flutter Form에서 사용하는 validator의 동작 구조, 실행 순서, 활용 패턴을 자세히 학습했다. 단순히 문법을 아는 것을 넘어, 실제 폼 흐름 속에서 언제 실행되고 어떤 역할을 하는지 체계적으로 정리했다.
1. validator의 역할
- 입력값 검증 로직을 정의하는 함수.
- 반환값이 null이면 “유효”, 문자열이면 “에러 메시지”.
- FormState.validate()가 호출될 때 모든 필드의 validator가 실행된다.
- autovalidateMode를 통해 입력 중 자동 검증(onUserInteraction 등)도 가능하다.
validator: (v) {
if (v == null || v.trim().isEmpty) return '값을 입력해 주세요.';
return null;
}
2. 실제 프로젝트(ProductFormPage)에서의 사용 예시
이미지 선택 필드
- FormField<String?>로 감싸 비텍스트 입력에도 검증을 적용.
- _imageFieldKey.currentState?.didChange()를 이용해 상태 변경을 폼에 반영.
- validator는 _imageSelection == null일 때 경고 문구를 띄움.
상품명 필드
validator: (v) {
if (v == null || v.trim().isEmpty) return '상품 이름을 입력해 주세요.';
return null;
}
가격 필드
validator: (v) {
if (v == null || v.trim().isEmpty) return '상품 가격을 입력해 주세요.';
final clean = v.replaceAll(RegExp(r'[^0-9]'), '');
final n = int.tryParse(clean);
if (n == null || n < 0) return '유효한 가격을 입력해 주세요.';
if (n < 100 || n > 10000000) return '100원 이상 10,000,000원 이하로 입력해 주세요.';
return null;
}
상품 설명 필드
validator: (v) {
if (v == null || v.trim().isEmpty) return '상품 설명을 입력해 주세요.';
return null;
}
3. 실행 흐름과 동작 순서
- 사용자가 “등록하기” 클릭
- _formKey.currentState?.validate() 호출
- 모든 필드의 validator 순회 실행
- 하나라도 에러 메시지를 반환하면 false
- 모든 필드가 null(=유효)일 때 다음 단계 진행 → 상품 등록 완료 다이얼로그 표시
4. 폼 검증의 제어 방식
- 기본적으로 FormState.validate()를 통해 명시적으로 실행.
- 자동 검증 모드는 아래처럼 지정 가능:
Form(
autovalidateMode: AutovalidateMode.onUserInteraction,
child: ...
);
→ 사용자가 입력하거나 포커스를 이동할 때마다 validator가 자동 실행.
5. 재사용 가능한 검증 함수 패턴
공통 로직은 별도 유틸 파일로 분리하면 유지보수가 쉬움.
class Validators {
static String? required(String? v, {String label = '값'}) {
if (v == null || v.trim().isEmpty) return '$label을 입력해 주세요.';
return null;
}
static String? intRange(String? v, int min, int max, {String label = '값'}) {
final n = int.tryParse(v!.replaceAll(RegExp(r'[^0-9]'), ''));
if (n == null) return '유효한 $label을 입력해 주세요.';
if (n < min || n > max) return '$min 이상 $max 이하로 입력해 주세요.';
return null;
}
}
6. 추가적으로 배운 포인트
- FormField와 didChange(): 이미지처럼 텍스트가 아닌 입력도 검증하려면 FormField로 래핑하고 didChange로 상태를 업데이트해야 함.
- 동기 검증만 가능: validator는 Future를 반환할 수 없기 때문에 비동기 검증(서버 중복 체크 등)은 별도 로직으로 구현.
- UX 일관성: 에러 메시지 문체를 통일하고, 필드 라벨과 매칭된 메시지를 보여주는 게 중요.
- 입력 포맷과 검증 분리: TextInputFormatter로 시각적 포맷을, validator로 논리 검증을 담당해야 함.
7. 개선 포인트 요약
- autovalidateMode를 제출 이후 자동으로 활성화하도록 제어
- 가격 포맷터와 validator의 정규식 로직을 별도 함수로 분리
- FormField로 래핑한 이미지 검증 로직을 재사용 가능하게 정리
이번 학습을 통해 Form 구조에서 validator의 진짜 역할을 명확히 이해했다.
validator는 단순한 입력 검사 도구가 아니라, 폼 상태 전체의 일관성과 사용자 경험을 지키는 핵심 장치라는 점이 인상 깊었다.
앞으로는 단일 필드 검증뿐 아니라, 재사용성·일관성·UX까지 고려한 검증 설계를 목표로 해야겠다.