상세 컨텐츠

본문 제목

[Flutter] Row 내부 TextField 렌더링 이슈

플러터/오류, 삽질 및 해결방법

by 감자 바보 2025. 5. 26. 12:28

본문

반응형

[Flutter] Row 내부 TextField 렌더링 이슈

 

플러터 화면 구성 중, Row 위젯 내부에 Textfeild를 사용할 시, 화면이 정상적으로 구현되지 않는 문제가 발생하였습니다. Column 내부에서 사용할 때는 이러한 증상이 없었기에 Row와 Column간 차이를 파악하고 정리해보도록 하겠습니다.

 

 

발생 오류

 

Row(
    children: [
      TextField(),
      // ... 다른 위젯들
    ],
  ),

 

위 코드와 같이 Row단 안에 TextField의 크기를 제한하지 않는 경우, 화면 전체의 구성요소가 정상적으로 렌더링되지 않고 깨지는 현상을 확인하였습니다.

 

문제 원인

 

Row의 경우  가로방향에 대해 자식에게 무제한의 자유를 제공합니다. 즉 스스로 너비를 계산하여 사용하도록 합니다. 

Column의 경우 이와 반대로, 세로방향에 대해 자식에게 무제한의 자유를 제공합니다.

 

따라서 Row 하위에 크기제한 없는 TextField를 둘 시, 크기를 확정짓지 못해 렌더링이 이상해지는 문제가 발생한 것입니다.

하지만 Column에 경우, 가로 크기에는 기본으로 제한을 주기 때문에, 이 문제가 발생하지 않습니다.

 

그렇다면 왜 TextField는 특별히 민감할까요?

 

TextField는 내부적으로 RenderBox 기반이고, 텍스트 편집 기능을 위해 정확한 위치 계산과 너비 제약이 필요합니다. 그래서 상위 위젯이 너비를 주지 않으면 레이아웃을 계산하지 못해 오류 또는 레이아웃 망가짐이 발생합니다.

 

해결 방법

 

Row 하위 TextField의 크기를 제한하는 것으로 이를 해결할 수 있습니다. 크게 아래 2가지 방법이 있습니다.

 

1. Expanded로 감싸기

Row(
  children: [
    Expanded(
      child: TextField(),
    ),
  ],
)

 

이렇게 하면, TextField가 Row 내의 전체 가용 너비를 사용하게 됩니다.

일반적으론 이 방법을 많이 사용합니다.

 

2. TextField 사이즈 직접 제한

Row(
  children: [
    SizedBox(
      width: 200,
      child: TextField(),
    ),
  ],
)

 

SizedBox나 다른 방법으로 TextField의 너비를 직접 제한하면 Row 내에서도 정상적으로 동작합니다.

 

테스트 데모

 

이 문제를 테스트할 수 있는 데모 코드입니다. 코드는 GPT가 작성해주었습니다.

 

이를 테스트할 때, 가로 제약이 없는 경우를 주석하지 않고 실행한다면, 화면이 정상적으로 렌더링 되지 않는 것을 확인할 수 있습니다.

 

더보기
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'TextField 제약 데모',
      home: Scaffold(
        appBar: AppBar(title: Text('TextField Constraints')),
        body: Padding(
          padding: const EdgeInsets.all(16.0),
          child: DemoWidget(),
        ),
      ),
    );
  }
}

class DemoWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [

        /// ✅ 정상 동작: Column 안의 TextField (가로 제약 있음)
        Text('Column 안의 TextField (정상 동작):'),
        Container(
          color: Colors.yellow[100],
          child: TextField(
            decoration: InputDecoration(border: OutlineInputBorder()),
          ),
        ),
        SizedBox(height: 24),

        /// ❌ 문제 발생: Row 안의 TextField (가로 제약 없음)
        Text('Row 안의 TextField (에러 or 깨짐):'),
        Container(
          color: Colors.red[100],
          child: Row(
            children: [
              TextField(
                decoration: InputDecoration(border: OutlineInputBorder()),
              ),
            ],
          ),
        ),
        SizedBox(height: 24),

        /// ✅ 해결: Row + Expanded
        Text('Row + Expanded 안의 TextField (정상 동작):'),
        Container(
          color: Colors.green[100],
          child: Row(
            children: [
              Expanded(
                child: TextField(
                  decoration: InputDecoration(border: OutlineInputBorder()),
                ),
              ),
            ],
          ),
        ),
      ],
    );
  }
}

 

 

마무리

 

해당 문제는 가로 제한이 무제한인 Row에 상위 위젯에게서 너비를 받아오는 TextField를 크기제한 없이 사용하였기 때문에 발생한 문제였습니다. 해당 문제에 대해서는 아래 표와 같이 해결할 수 있습니다.

 

Row에 TextField 1개만 있음 Expanded 또는 SizedBox로 너비 제한하기
Row에 여러 위젯이 있음 TextField는 Expanded로, 나머지는 기본 배치
Column 안의 Row에서 사용 전체 레이아웃이 오버플로우 날 수 있으니 조심

 

다만 이 문제는 Row, Column을 사용할 때, 다른 위젯에서도 나타날 수 있으므로 항상 주의해서 사용해야 할 것 같습니다.

728x90
반응형

관련글 더보기