이전에 진행했던 프로젝트에 새로운 기능을 추가하기 위해 작업을 하다가 발생한 에러에 대해 공유하도록 하겠다.
구현하려던 기능은 다음과 같다.
알림 목록 화면 내에 맨 밑 아이템을 클릭할 경우, 다시 앱에 온보딩 튜토리얼을 진행할 수 있도록 구현 하는 것
온보딩은 최초 로그인시 한번만 진행이 가능하기 때문에, 다시 온보딩을 진행하여 앱의 전체적인 기능을 체험하려면 회원 탈퇴를 해야지만 가능했기에, 다음과 같은 기능을 추가하게 되었다.
기능의 구현 자체는 어렵지 않으므로 순조롭게 작업을 진행하다가 아이템 레이아웃을 만들던 중에 제목과 같은 에러를 접하게 되었다.
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_restart_on_boarding"
android:layout_width="match_parent"
android:layout_height="130dp"
android:background="@color/gray_100"
android:paddingHorizontal="16dp"
android:paddingVertical="24dp">
<TextView
android:id="@+id/tv_lesson_list_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="😊나공이랑 대결을 하려면 어떻게 해야할까?"
android:textColor="@color/gray_400"
android:textSize="14dp"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_lesson_list_planning_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:text="튜토리얼 다시 해보기"
android:textColor="@color/gray_400"
android:textSize="12dp"
app:layout_constraintStart_toStartOf="@+id/tv_lesson_list_name"
app:layout_constraintTop_toBottomOf="@id/tv_lesson_list_name" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
[Fatal Error] item_restart_on_boarding.xml:19:31: Invalid byte 2 of 3-byte UTF-8 sequence.
처음 보는 에러 였고, 문제가 되는 부분은 맥에 내장된 emoji 를 사용한 부분이었다.
이전에도 앱에 emoji를 사용한 적이 있어, 그땐 별다른 에러가 발생하지 않았던 것 같은데 하면서 당황하던 중, 에러 자체는 쉽게 해결할 수 있었다.
해결법은 string value 로 빼내는 것 이었다.
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_restart_on_boarding"
android:layout_width="match_parent"
android:layout_height="130dp"
android:background="@color/gray_100"
android:paddingHorizontal="16dp"
android:paddingVertical="24dp">
<TextView
android:id="@+id/tv_lesson_list_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="@string/notificiation_restart_on_boarding_title"
android:textColor="@color/gray_400"
android:textSize="14dp"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_lesson_list_planning_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:text="@string/notification_restart_on_boarding_message"
android:textColor="@color/gray_400"
android:textSize="12dp"
app:layout_constraintStart_toStartOf="@+id/tv_lesson_list_name"
app:layout_constraintTop_toBottomOf="@id/tv_lesson_list_name"
tools:ignore="HardcodedText" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
정상적으로 빌드가 됨을 확인할 수 있었다.
그렇다면 둘의 차이는 무엇일까?
검색을 해본 결과
문자열 리소스 파일(strings.xml) 은 일반적으로 UTF-8 인코딩을 사용하며, 이 인코딩은 이모지와 같은 다양한 유니코드 문자를 올바르게 처리할 수 있다고 한다.
레이아웃 파일에 직접 문자열을 포함하는 경우, 인코딩 문제가 발생할 수 있지만, 문자열 리소스 파일을 사용하면 이러한 문제가 줄어든다.
그럼 레이아웃 파일은 UTF-8 인코딩을 지원하지 않는건가?
<?xml version="1.0" encoding="utf-8"?>
그건 아니다 UTF-8 인코딩을 지원하지만, 특정 환경이나 설정에서 인코딩 문제가 발생할 수 있고, 문자열 리소스 파일을 사용하면 문제를 완화 할 수 있는 것이다.