컴포넌트/필드 컴포넌트

Textarea (텍스트영역)

VanillaFront 2026. 9. 13. 23:54

Va.Textarea — 여러 줄 텍스트 입력

HTML <textarea> 표준을 감싸되, 글자 수 표시·내용에 따른 높이 자동 조절·리사이즈 방향 제어 같은 실무에 자주 필요한 기능이 추가된 컴포넌트. 게시글·메모·리뷰 본문 같은 긴 텍스트 입력에 씁니다.

  • 클래스: Va.Textarea  va_component.js:4722
  • short name: textarea
  • 상속: Va.PureField (Input과 형제)
  • DOM 태그: <textarea>
  • isContainer: true
  • 베이스 CSS: va-textarea


1. 기본 사용

{
    tagName: 'textarea',
    value: '초기 내용',
    placeholder: '내용을 입력하세요',
    onChange: 'onContentChange'
}
  • 여러 줄 텍스트 입력창
  • Enter로 줄바꿈 (Input과 다름)
  • 기본은 사용자가 우하단 코너로 리사이즈 가능 (<textarea> 표준)

2. Va.Input과의 차이

항목Va.InputVa.Textarea

DOM 태그 <input> <textarea>
입력 형태 한 줄 여러 줄
Enter 키 change 확정 줄바꿈
numberComma
masking 실효 제한
글자 수 표시 ✓ (visibleTextLength)
높이 자동 조절 ✓ (autoHeight)
리사이즈 방향 해당 없음 ✓ (resizeField)

한 줄 요약: "여러 줄 텍스트 입력 + 글자 수 카운터 + 자동 높이 조절."


3. 주요 속성

Textarea 전용

속성기본값설명

maxLength 최대 글자 수
byteMaxLength true면 maxLength를 바이트 단위로 (한글 3바이트 등)
visibleTextLength true면 우하단에 글자 수 카운터 표시 (123 / 500 형태)
autoHeight true면 내용에 따라 자동 높이 조절 (스크롤 없이)
resizeField 리사이즈 방향. 'none' / 'horizontal' / 'vertical' / 'both'

PureField 상속

속성설명

value 텍스트 값
placeholder 플레이스홀더
name 폼 name
readonly / disabled 상태
required 필수 표시
size / appearance 시각 스타일
textAlign 정렬
stopPropagation 이벤트 버블링

4. 이벤트 (PureField 상속)

Input과 동일:

이벤트시그니처

change (component, element, evt) — blur 후 값 확정
focus / blur 표준 (200ms debounce)
keydown / keyup 키 이벤트
click 필드 클릭

⚠️ Textarea 특유의 keydown 처리 — Backspace/Delete를 제외한 모든 키에서 stopPropagation 호출 (va_component.js:4763-4768). 상위 컴포넌트로 키 이벤트가 안 올라가 편함 (모달·팝업 안에서도 자연스러운 편집 가능).


5. 메서드

값 관리 (PureField 상속 + 오버라이드)

메서드설명

getValue() 텍스트 값 반환
setValue(value) 값 세팅 + autoHeight면 높이 재계산 자동

상태

메서드설명

setDisabled(bool) / setReadOnly(bool) 상태
focus() / blur() 포커스

유틸

메서드설명

calcHeight() 현재 내용에 맞게 높이 재계산 (자동 호출되지만 강제 필요 시 사용)

6. 세 가지 기능 상세

1) visibleTextLength — 글자 수 카운터

{
    tagName: 'textarea',
    maxLength: 500,
    visibleTextLength: true
}

우하단에 0 / 500 형태로 표시. 사용자 타이핑에 따라 실시간 갱신.

  • byteMaxLength: false (기본) — 글자 수 카운트
  • byteMaxLength: true — 바이트 수 카운트 (한글 3바이트 등)

리뷰·게시글 폼에서 "500자 이내로 작성해주세요" UX에 유용.

2) autoHeight — 자동 높이 조절

{
    tagName: 'textarea',
    autoHeight: true
}

내용이 길어지면 textarea 높이가 자동으로 늘어남 → 내부 스크롤이 안 생김.

동작:

  • keyup  calcHeight() 자동 호출
  • scrollHeight를 읽어 height에 대입
  • mounted() 시 300ms 후 초기 계산

⚠️ 초기 렌더링 후 300ms 지연이 있음 — 처음 표시될 때 살짝 튈 수 있음.

3) resizeField — 리사이즈 방향

{
    tagName: 'textarea',
    resizeField: 'vertical'   // 세로만 리사이즈 가능
}

값동작

'none' 리사이즈 불가
'vertical' 세로만
'horizontal' 가로만
'both' 가로 세로 모두 (기본)

'horizontal' / 'both' 지정 시 fieldWrapper 폭이 auto가 되어 부모 flex 컨테이너 정렬이 흐트러질 수 있음.

주의: autoHeight: true와 resizeField는 서로 상충. 자동 조절 상황에선 리사이즈 비활성화('none') 권장.


7. 내부 구조

<div elname="element" class="va-textarea [size]..." tag-name="textarea" field="true">
  <div elname="fieldWrapper" class="field-wrapper">
    <textarea elname="field" style="border:0px"></textarea>
    <div elname="focusLine" class="focus-line"></div>
  </div>
  <div elname="textLengthInner" class="text-length-inner"
       style="display:none">                              ← visibleTextLength일 때 표시
    <span elname="textLength" class="text-length">123</span>
    <span elname="textLengthDivider">/</span>
    <span elname="textMaxLength" class="text-max-length">500</span>
  </div>
</div>

8. 언제 쓰나

Textarea가 맞을 때

  • 게시글·리뷰·메모 본문
  • 긴 설명·비고 필드
  • 주소 상세 (여러 줄)
  • 문의·불만사항 입력
  • JSON·YAML 편집 (resizeField로 크게)

다른 걸 쓸 때

  • 한 줄 입력 → Va.Input
  • 코드 편집 (문법 강조) → Va.Monaco / CodeMirror
  • 리치 텍스트 편집 → 별도 에디터
  • 라벨 붙은 폼 필드 → Va.TextareaField

9. 흔한 조합 예시

// 표준
{
    tagName: 'textarea',
    placeholder: '내용을 입력하세요',
    style: { width: '100%', height: '200px' }
}

// 글자 수 카운터
{
    tagName: 'textarea',
    maxLength: 500,
    visibleTextLength: true,
    placeholder: '500자 이내로 작성',
    style: { width: '100%', height: '150px' }
}

// 자동 높이 (스크롤 없이)
{
    tagName: 'textarea',
    autoHeight: true,
    resizeField: 'none',
    placeholder: '내용에 맞춰 높이 자동 조절'
}

// 바이트 제한 (한글 게시글)
{
    tagName: 'textarea',
    maxLength: 900,
    byteMaxLength: true,
    visibleTextLength: true,
    placeholder: '한글 300자, 영문 900자'
}

// 리사이즈 방향 제어
{
    tagName: 'textarea',
    resizeField: 'vertical',
    style: { width: '100%', height: '100px' }
}

// 읽기 전용 (긴 텍스트 표시)
{
    tagName: 'textarea',
    value: '이용약관 전문...',
    readonly: true,
    style: { width: '100%', height: '300px' }
}

10. 실전 예 — 리뷰 작성 (글자 수 제한)

class ReviewForm extends Va.View {
    onSubmit(btn, el, evt) {
        const content = this.getRef('review').getValue();

        if (!content || content.length < 10) {
            new Va.Alert({ title: '알림', message: '10자 이상 작성해주세요' }).show(this);
            return;
        }

        ReviewService.save(this, { content }, (view, ok) => {
            if (ok) new Va.Alert({ title: '완료', message: '리뷰 등록 완료' }).show(view);
        });
    }

    config() {
        return {
            tagName: 'page',
            tags: [{
                tagName: 'panel',
                tags: [
                    { tagName: 'h2', innerHTML: '리뷰 작성' },
                    {
                        tagName: 'textarea',
                        ref: 'review',
                        placeholder: '솔직한 리뷰를 남겨주세요 (최대 500자)',
                        maxLength: 500,
                        byteMaxLength: false,
                        visibleTextLength: true,
                        style: { width: '100%', height: '200px' }
                    },
                    {
                        tagName: 'button',
                        text: '등록',
                        appearance: 'primary',
                        onClick: 'onSubmit'
                    }
                ]
            }]
        };
    }
}

흐름:

  1. Textarea에 글자 수 카운터 자동 표시 (0 / 500)
  2. 사용자 타이핑에 따라 실시간 갱신
  3. 제출 시 최소 길이 검증

11. 알아두면 좋을 주의사항

  1. <textarea> 특성상 Enter가 줄바꿈 — 폼 제출 트리거 아님. Enter로 저장하려면 keydown Ctrl+Enter 별도 처리.
  2. maxLength 강제 방식 — HTML 표준 maxlength 속성으로 반영. 붙여넣기도 자동 제한.
  3. byteMaxLength: true는 자바스크립트 계산 — HTML 표준 아님. Va.Util.getByteLength() 사용.
  4. autoHeight와 resizeField 상충 — 자동 조절 시 리사이즈 비활성화('none') 권장.
  5. autoHeight 초기 300ms 지연 — 렌더링 후 계산. 첫 표시가 살짝 튈 수 있음.
  6. autoHeight에서 scrollHeight - 4 공식 — 4px 여유로 스크롤 방지. 테마 padding에 따라 조정 필요할 수 있음.
  7. keydown stopPropagation — Backspace/Delete 외 모든 키 버블링 차단. 모달 안에서 안전.
  8. change 이벤트는 blur 후 발생 — 실시간 감지엔 keyup 사용.
  9. getValue() 문자열 — 그대로 사용 가능.
  10. setValue()가 autoHeight 재계산 트리거 — 프로그래매틱 값 세팅 후 높이 자동 조절.
  11. visibleTextLength: true인데 maxLength 없으면 — 카운터의 분모가 undefined로 표시됨. 함께 지정 권장.
  12. masking은 여러 줄에 안 어울림 — 옵션은 있지만 실효 제한. 사용 자제.

12. textarea vs input vs monaco 선택

상황추천

한 줄 텍스트 input
여러 줄 일반 텍스트 textarea
긴 글 (게시글, 리뷰) textarea + visibleTextLength
자연스러운 높이 조절 textarea + autoHeight
코드 편집 (문법 강조) monaco / CodeMirror
리치 텍스트 별도 에디터
라벨 붙은 폼 필드 textareaField

참고