Secure Text Entry — Android에서 입력 보호와 비밀번호란

저자: IT Sectr 게시일: 2026-07-07 읽는 시간: 9 분

Secure Text Entry는 Android에서 입력된 문자가 실제 문자 대신 숨겨진 형태(점 또는 별표)로 표시되는 텍스트 입력 모드입니다. 이 모드는 비밀번호 필드, PIN 코드, CVV 코드 및 기타 기밀 정보에 사용됩니다. Secure Text Entry는 시각적 가로채기로부터 데이터를 보호할 뿐만 아니라 스크린샷, 화면 녹화 및 자동 수정 기능을 통한 유출도 방지합니다. Android Security Best Practices (2026)에 따르면, 사용자 인증 데이터를 처리하는 애플리케이션에는 숨김 입력이 필수 요구 사항입니다.

핵심 요점

  • Secure Text Entry — 비밀번호 입력 시 문자 대신 점을 표시하는 숨김 입력 모드.
  • 활성화 — XML에서 inputType="textPassword" 또는 코드에서 TYPE_TEXT_VARIATION_PASSWORD를 통해.
  • 보호 — 시각적 가로채기, 스크린샷 및 자동 수정/사전을 통한 유출 방지.
  • TransformationMethod — 문자 표시를 숨김 기호로 대체하는 Android 메커니즘.
  • 표시 토글 — TextInputLayout에서 endIconMode="password_toggle"을 통한 비밀번호 표시 기능.

Android에서 Secure Text Entry란

Secure Text Entry(보호된 텍스트 입력)는 입력된 각 문자의 표시를 마스킹 문자(일반적으로 점(•) 또는 별표(*))로 대체하는 Android 기능입니다. 이는 어깨 너머로 비밀번호를 읽는 행위(shoulder surfing)를 방지하고 입력된 데이터를 엿보는 눈으로부터 숨깁니다. 이 기능은 비밀번호 마스킹이라고도 하며 모바일 애플리케이션의 표준 관행입니다.

iOS에서 Secure Text Entry가 별도의 UITextField 설정인 것과 달리, Android에서는 이 기능이 PASSWORD 변형과 함께 inputType 속성을 통해 활성화됩니다. EditText가 inputType="textPassword"를 받으면 자동으로 PasswordTransformationMethod(문자 대체를 담당하는 클래스)를 적용합니다. 각 새 문자가 입력될 때마다 EditText는 TransformationMethod 인터페이스 메커니즘을 통해 즉시 마스킹 문자로 대체합니다.

Android Source Code (AOSP, 2026)에 따르면, PasswordTransformationMethod의 구현은 TextPaint 클래스를 사용하여 마스킹 문자를 렌더링합니다. 마스킹 문자의 크기는 필드의 글꼴 크기와 일치하여 단어 길이를 통한 정보 유출을 방지합니다 — 모든 문자의 너비가 동일하게 보입니다. 이는 입력된 데이터의 길이 분석에 기반한 공격으로부터 보호하는 데 중요합니다.

xml
<!-- Basic Secure Text Entry example -->
@+id/etPassword
android:layout_width="match_parent"
android:hint="Enter password"
android:inputType="textPassword"
android:maxLength="64"
android:importantForAutofill="yes" />

Secure Text Entry 작동 방식

Android의 Secure Text Entry 메커니즘은 android.text.method 패키지에 정의된 TransformationMethod 인터페이스를 기반으로 합니다. PasswordTransformationMethod는 getTransformation() 메서드를 재정의하여 표시용으로 대체된 문자 시퀀스를 반환하는 내장 구현입니다. Editable의 원본 텍스트는 변경되지 않으며 — 시각적 표현만 변경됩니다.

사용자가 문자를 입력하면 EditText가 dispatchEvent를 호출하고 문자를 InputConnection에 전달하여 Editable에 추가합니다. 그런 다음 EditText는 현재 TransformationMethod의 getTransformation() 메서드를 호출하여 원본 CharSequence를 가져와 마스킹 문자가 포함된 SpannableString을 반환합니다. 이 SpannableString이 원본 텍스트 대신 화면에 렌더링됩니다. 주요 특징은 변환 자체가 Editable 내용을 변경하지 않으므로 getText().toString()을 호출하면 실제 입력된 텍스트가 반환된다는 것입니다.

Android Developers Reference (2026)에 따르면, PasswordTransformationMethod는 각 문자에 MetricAffectingSpan을 추가하여 글리프를 점으로 대체합니다. 이러한 스팬은 텍스트 길이에 영향을 주지 않으므로 숨김 표시 상태에서도 커서와 입력 위치가 올바르게 유지됩니다. VisiblePasswordTransformationMethod도 있어 마지막 입력 문자를 짧은 시간 동안 표시합니다(iOS와 유사).

kotlin
// PasswordTransformationMethod - built-in masking
editText.transformationMethod = PasswordTransformationMethod.getInstance()

// VisiblePasswordTransformationMethod - shows last char
editText.transformationMethod = VisiblePasswordTransformationMethod.getInstance()

비밀번호 표시 토글

표시 토글(password visibility toggle)은 사용자가 양식을 제출하기 전에 입력한 비밀번호를 임시로 확인할 수 있는 기능입니다. Android에서는 app:endIconMode="password_toggle" 속성이 있는 TextInputLayout을 통해 이 기능이 구현됩니다. 눈 아이콘을 탭하면 필드가 textPassword와 textVisiblePassword 사이에서 전환됩니다.

TextInputLayout의 password_toggle 구현은 내부 EditText의 inputType을 자동으로 변경하고 아이콘을 애니메이션화합니다(눈 열기/닫기). 이러한 전환 중에 커서 위치가 재설정될 수 있으므로 TextInputLayout은 모드 변경 후 위치를 저장하고 복원합니다. 또한 표시 비밀번호로 전환할 때 자동 수정 및 제안이 활성화되지 않습니다 — 일반 텍스트가 아닌 TYPE_TEXT_VARIATION_VISIBLE_PASSWORD가 사용됩니다.

Material Design Guidelines (2025)에 따르면, 비밀번호 표시 아이콘은 필드가 포커스될 때뿐만 아니라 항상 표시되어야 합니다. 사용자는 언제든지 비밀번호를 확인할 수 있어야 합니다. 아이콘은 일정 시간 후에 자동으로 비밀번호를 숨기지 않아야 합니다 — 사용자 작업에 의해서만 가능합니다.

xml
<!-- TextInputLayout with password toggle -->
@+id/tilPassword
android:layout_width="match_parent"
app:endIconMode="password_toggle"
app:passwordToggleTint="@color/primary">

    @+id/etPassword
    android:inputType="textPassword"
    android:hint="Password" />

</com.google.android.material.textfield.TextInputLayout>

Secure Text Entry 프로그래밍 설정

Kotlin에서 Secure Text Entry의 프로그래밍 설정은 inputType을 설정하거나 setTransformationMethod()를 통해 수행됩니다. 두 접근 방식 모두 동일한 결과를 가져오지만 세부 사항이 다릅니다. inputType을 설정하면 자동 수정 및 제안도 추가로 구성되는 반면, setTransformationMethod는 문자 표시에만 영향을 줍니다.

TextInputLayout을 통한 비밀번호 토글 예제

kotlin
// Programmatic password visibility toggle
fun togglePasswordVisibility(til: TextInputLayout) {
    val editText = til.editText ?: return
    val currentType = editText.inputType
    val isPassword = (currentType and
        InputType.TYPE_TEXT_VARIATION_PASSWORD) != 0

    if (isPassword) {
        editText.inputType = InputType.TYPE_CLASS_TEXT or
            InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD
    } else {
        editText.inputType = InputType.TYPE_CLASS_TEXT or
            InputType.TYPE_TEXT_VARIATION_PASSWORD
    }

    // Restore cursor position
    val cursorPos = editText.selectionStart
    editText.setSelection(maxOf(0, cursorPos))
}

사용자 정의 TransformationMethod

kotlin
// Custom masking — shows only last 4 chars
class PartialPasswordTransformation : TransformationMethod {
    override fun getTransformation(source: CharSequence?,
        view: View?): CharSequence {
        val text = source?.toString() ?: ""
        if (text.length <= 4) return text

        val dots = "\u2022".repeat(text.length - 4)
        return dots + text.substring(text.length - 4)
    }

    override fun onFocusChanged(view: View?,
        sourceText: CharSequence?,
        focused: Boolean,
        direction: Int,
        previouslyFocusedRect: android.graphics.Rect?) {}
}

숨김 입력의 보안 측면

Secure Text Entry는 여러 수준에서 보호를 제공합니다. 시각적 마스킹은 어깨 너머 비밀번호 읽기(shoulder surfing)를 방지합니다 — 공공 장소에서 비밀번호 도난의 가장 일반적인 방법입니다. 자동 수정을 비활성화하면 비밀번호가 사용자 사전에 저장되는 것을 방지하여 예측 입력을 통한 유출을 차단합니다. 스크린샷 보호(FLAG_SECURE가 활성화된 경우)는 다른 애플리케이션이 필드 내용을 캡처하는 것을 방지합니다.

그러나 Secure Text Entry는 완전한 보호가 아닙니다. 시스템 수준에서 입력 가로채기(키로깅) 공격은 InputConnection에서 실제 문자를 얻을 수 있습니다. 접근성 서비스가 있는 악성 애플리케이션은 화면에 문자가 숨겨져 있어도 EditText 내용을 읽을 수 있습니다. 또한 적절한 인증서 검증과 함께 HTTPS를 사용하지 않는 경우 서버로 데이터 전송 중 SSL 스니핑으로 비밀번호가 노출될 수 있습니다.

OWASP Mobile Security Testing Guide (2025)에 따르면, Android에서 최대 비밀번호 보호를 위해 권장되는 사항은 다음과 같습니다: 중요한 필드에는 inputType="textPassword" + autofill 비활성화; 필요한 것보다 오래 메모리에 비밀번호를 캐시하지 않음; 애플리케이션 최소화 시 비밀번호 필드 지우기(onPause/onStop); 비밀번호 짧은 표시 중에도 마스킹 사용.

보호 수준Secure Text Entry추가 조치
시각적 가로채기문자 마스킹생체 인증, shoulder surfing 방지
스크린샷부분적(구현에 따라 다름)Window에 FLAG_SECURE
키로깅보호하지 않음안전한 입력이 있는 IME 사용
자동 수정/사전비활성화비밀번호에 대해 기본적으로 비활성화
네트워크 가로채기보호하지 않음인증서 고정이 있는 HTTPS

Secure Text Entry 모범 사례

Android 개발자는 숨김 입력을 작업할 때 몇 가지 핵심 관행을 따라야 합니다. 첫째, 비밀번호 필드에는 항상 endIconMode="password_toggle"이 있는 TextInputLayout을 사용하세요 — 이것이 현대 Material Design 표준입니다. 둘째, 비밀번호를 표시하는 기능을 비활성화하지 마세요 — 사용자는 특히 작은 키보드가 있는 모바일 장치에서 입력한 내용을 확인할 수 있어야 합니다.

Secure Text Entry는 적절한 자동 채우기 구성도 필요합니다. 비밀번호 필드의 경우 비밀번호 관리자가 데이터를 올바르게 채우고 저장할 수 있도록 항상 autofillHints="password" 또는 autofillHints="newPassword"를 지정하세요. 새 비밀번호 확인 필드의 경우 autofillHints="newPassword"를 사용하여 시스템이 현재 저장된 비밀번호로 채우는 것을 제안하지 않도록 합니다.

  • TextInputLayout — 표시 토글을 위해 endIconMode와 함께 Material Design TextInputLayout을 사용하세요.
  • Autofill — 관리자 지원을 위해 autofillHints="password"와 importantForAutofill="yes"를 추가하세요.
  • 지우기 — 애플리케이션 최소화 시 비밀번호 필드를 지우세요(onPause/onStop).
  • 길이 — 비밀번호 길이를 너무 엄격하게 제한하지 마세요(최소 8자, 엄격한 최대값 없음).
  • 생체 인식 — 수동 비밀번호 입력의 대안으로 생체 인식 로그인(BiometricPrompt)을 제공하세요.
kotlin
// Full password field with autofill and cleanup
class SecurePasswordField {
    private fun setupPasswordField(til: TextInputLayout) {
        val editText = til.editText ?: return
        editText.inputType = InputType.TYPE_CLASS_TEXT or
            InputType.TYPE_TEXT_VARIATION_PASSWORD
        editText.setAutofillHints(View.AUTOFILL_HINT_PASSWORD>)
        editText.importantForAutofill = View.IMPORTANT_FOR_AUTOFILL_YES
    }

    fun clearOnPause(editText: EditText) {
        editText.text?.clear()
    }
}

자주 묻는 질문

textPassword와 textVisiblePassword의 차이점은 무엇인가요?

textPassword는 입력된 모든 문자를 숨기고 자동 수정을 비활성화합니다. textVisiblePassword도 자동 수정을 비활성화하지만 문자를 명확하게 표시합니다. textVisiblePassword는 비밀번호 표시를 토글할 때 사용됩니다 — 보안을 위해 자동 수정 및 제안이 비활성화된 상태로 유지되므로 일반 텍스트가 아닙니다.

비밀번호 마스킹용 사용자 정의 문자를 만들 수 있나요?

네, TransformationMethod 인터페이스를 구현하는 사용자 정의 클래스를 만드세요. 원하는 대체 문자가 포함된 CharSequence를 반환하는 getTransformation() 메서드를 재정의하세요. editText.transformationMethod = CustomPasswordTransformation()을 통해 설정합니다. 보안을 위해 문자는 고정폭이어야 합니다.

비밀번호 표시 기능을 비활성화하는 것이 권장되지 않는 이유는 무엇인가요?

작은 화면과 터치 키보드가 있는 모바일 장치에서는 비밀번호 입력 시 오류 가능성이 데스크톱보다 훨씬 높습니다. 입력한 비밀번호를 확인할 수 있는 기능은 입력 오류를 줄이고 비밀번호 재설정 요청 수를 감소시켜 사용자 경험을 개선하고 지원 부하를 줄입니다.

앱 스크린샷으로부터 비밀번호를 보호하려면 어떻게 해야 하나요?

Activity 또는 Dialog 창에 FLAG_SECURE 플래그를 설정하세요: window.setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE). 이렇게 하면 전체 창에 대해 스크린샷과 화면 녹화가 방지됩니다. 하지만 일반 콘텐츠에 대한 스크린샷도 비활성화되므로 바람직하지 않을 수 있습니다.

비밀번호 필드의 자동 채우기는 어떻게 작동하나요?

Android 8.0(API 26)부터 Autofill Framework는 inputType을 통해 비밀번호 필드를 자동으로 감지합니다. 올바른 작동을 위해 importantForAutofill="yes"를 설정하고 autofillHints("password", "newPassword", "emailAddress")를 지정하세요. Gboard와 비밀번호 관리자는 이러한 속성을 사용하여 저장된 비밀번호를 제안합니다.

요약

  • Secure Text Entry — PasswordTransformationMethod를 통해 문자를 마스킹 기호(점)로 대체하는 숨김 입력 모드.
  • 활성화 — inputType="textPassword" 또는 TYPE_TEXT_VARIATION_PASSWORD의 프로그래밍 설정을 통해.
  • PasswordTransformationMethod — Editable을 수정하지 않고 문자 표시를 대체하는 내장 Android 클래스.
  • 표시 토글 — endIconMode="password_toggle" 및 TYPE_TEXT_VARIATION_VISIBLE_PASSWORD와 함께 TextInputLayout을 통해 구현.
  • 보호 — shoulder surfing, 스크린샷(FLAG_SECURE 사용 시), 자동 수정 및 사전 저장 방지.
  • Autofill — 비밀번호 관리자 지원을 위해 importantForAutofill 및 autofillHints="password"를 추가.
  • 모범 사례 — TextInputLayout 사용, 최소화 시 필드 지우기, 비밀번호 길이를 엄격히 제한하지 않기.

턴키 방식의 모바일 애플리케이션을 개발해 드립니다

IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.

프로젝트 논의

더 읽어보기