SVG_및_VectorDrawable_파싱_및_Path_적용 - boostcampwm-2024/and04-Nature-Album GitHub Wiki
SVG 파일과 VectorDrawable XML 파일을 파싱하여 Android Compose의 UI에서 사용할 수 있도록 한 과정을 정리하고자 한다.
프로젝트 초기에는 SVG 파일에서 path를 추출하지 못해 일단 하드코딩으로 path 데이터를 지정하였으나, 이후 path를 직접 추출하는 방식으로 변경을 시도하였다. 초기에 res/drawable
경로가 잘 되지 않아서 잠시 쉬는 시간을 갖고, assets
경로에 있는 SVG 파일과 res/drawable
경로에 있는 VectorDrawable XML 파일을 모두 활용할 수 있도록 두 경로의 파일을 파싱하는 작업에 도전하였다. 이 과정에서 발생한 문제와 해결 과정을 기록하였다.
처음 SVG
파일은 assets
경로에서 불러오는 데 성공하였으나, res/drawable
경로에 있는 VectorDrawable
XML 파일에서는 width
, height
, viewportWidth
, viewportHeight
값이 모두 0
으로 출력되는 문제가 발생하였다.
해당 문제의 원인은 VectorDrawable
XML 파일의 속성을 가져올 때 namespace
가 지정되지 않아서 발생한 것으로 파악되었다. Android에서 width
와 height
등 중요한 속성은 http://schemas.android.com/apk/res/android
라는 네임스페이스를 통해 접근해야 한다.
namespace
를 지정하여 width
, height
, viewportWidth
, viewportHeight
속성을 올바르게 파싱할 수 있도록 수정하였다. 코드 내에서 ANDROID_NAMESPACE
상수를 추가하고 이를 사용하여 getAttributeValue
호출 시 namespace
를 지정하여 중복 코드를 줄였다.
private const val ANDROID_NAMESPACE = "http://schemas.android.com/apk/res/android"
parser.getAttributeValue(ANDROID_NAMESPACE, "width")
위 문제를 해결한 후에도 width
와 height
값이 여전히 0
으로 출력되는 상황이 발생하였다. 로그를 확인한 결과, VectorDrawable
XML 파일의 속성 값이 dp
가 아닌 dip
로 출력되는 것을 확인하였다.
안드로이드 XML에서 dp
는 때때로 dip
으로 저장될 수 있다. 하지만 Float
로 변환하는 과정에서 dp
나 dip
를 제거해야 하는데, 코드에서 dp
만 replace
처리하고 있어서 dip
이 그대로 남아 Float
로 변환할 수 없는 문제가 있었다.
해결책으로 width
와 height
의 replace
메서드에서 dp
와 dip
를 모두 제거하도록 수정하였다.
width = rawWidth.replace("dp", "").replace("dip", "").toFloatOrNull() ?: 0f
파싱한 pathData
, viewportWidth
, viewportHeight
데이터를 사용하여 ClippingButton
을 구현할 때, 다양한 SVG 파일을 제대로 렌더링하지 못하는 상황이 발생하였다. 특히 세로 비율이 다른 SVG 파일을 화면에 맞게 표시하는 데 어려움이 있었다.
viewportWidth
와 viewportHeight
값을 사용하여 비율을 동적으로 설정하도록 하였다. 이를 통해 세로 비율이 다른 파일도 화면에 맞게 표시할 수 있도록 하였다.
Box(
modifier = modifier
.fillMaxWidth()
.aspectRatio(viewportWidth / viewportHeight)
.clip(CustomShape(path, viewportWidth, viewportHeight))
)
SVG
파일과 VectorDrawable
파일 중 어느 쪽이 더 효율적인지 결정하기 위해 용량을 비교하였다.
용량 비교 결과, SVG 파일이 VectorDrawable 파일보다 용량이 더 작았다. 따라서 파일 용량을 줄이기 위해 SVG 파일을 사용하는 것으로 결정하였다.
assets
파일과 drawable
파일에서 SVG
와 VectorDrawable
파일을 각각 불러와서 파싱하는 과정에서 차이점이 존재한다. 두 경로에서 파일을 불러오는 방식과 주의사항, 각각의 특성을 비교하여 아래에 정리하였다.
-
Assets 폴더 (
assets
)-
assets
폴더는 안드로이드 앱의 정적 리소스를 담는 디렉토리로, 일반적으로XML
이 아닌 정적 파일(예:.svg
,.txt
,.json
)을 포함한다. -
assets
파일을 접근하기 위해서는Context
의assets.open(fileName)
메서드를 사용하여InputStream
형태로 파일을 읽어온 후XmlPullParser
를 이용해 파싱해야 한다.
-
-
Drawable 폴더 (
res/drawable
)-
drawable
폴더는 주로XML
리소스 파일과Bitmap
파일을 포함하여 Android 컴포넌트에서 바로 접근할 수 있는 경로다. 여기에는VectorDrawable
로 변환된.xml
파일이 주로 위치하며,resources.getXml(resId)
메서드를 통해XmlPullParser
객체를 바로 얻을 수 있다. -
drawable
파일은 리소스 ID를 통해 쉽게 접근할 수 있으므로, 코드에서 파일 이름 대신 리소스 ID를 사용하여 호출하는 것이 일반적이다.
-
-
Assets 폴더
-
assets
의 SVG 파일을 파싱할 때는 네임스페이스가 필요하지 않다. 파일 내 속성에 직접 접근하여 파싱할 수 있다.
-
-
Drawable 폴더
-
drawable
의 VectorDrawable 파일에서는 네임스페이스가 반드시 필요하다. 속성(width
,height
,viewportWidth
,viewportHeight
)에 접근하기 위해서는http://schemas.android.com/apk/res/android
네임스페이스를 지정해야 한다.
-
-
Assets 폴더
-
assets
에서 불러온 SVG 파일에는dp
나dip
단위가 포함되어 있지 않다. 따라서 추가적인 단위 변환이나 제거 작업이 필요 없다.
-
-
Drawable 폴더
-
drawable
의 VectorDrawable 파일에서는width
와height
등의 속성값에dp
또는dip
단위가 붙어 있어Float
으로 변환하기 전 이를replace
로 제거해주어야 한다.dp
와dip
모두를 고려하여 변환 코드를 작성해야 한다.
-
-
Assets 폴더의 SVG 파일
-
SVG
파일은 상대적으로 파일 용량이 작으며, 주로 벡터 그래픽으로 표현되므로 용량 측면에서 효율적이다.
-
-
Drawable 폴더의 VectorDrawable XML 파일
-
VectorDrawable
파일은 Android 스튜디오에서 생성된 XML 포맷으로, SVG 파일을 변환하면서 용량이 더 커지는 경향이 있다. 동일한 그래픽이라도 SVG보다 더 많은 용량을 차지할 수 있다.
-
구분 | Assets 폴더 (SVG 파일) | Drawable 폴더 (VectorDrawable 파일) |
---|---|---|
접근 방식 | assets.open(fileName) 사용, InputStream으로 접근 | resources.getXml(resId) 사용, 리소스 ID로 접근 |
네임스페이스 필요 여부 | 필요 없음 | 필수(http://schemas.android.com/apk/res/android) |
단위 처리 | 단위 없음 | dp 및 dip 단위 제거 필요 |
파일 용량 | 상대적으로 작음 | 상대적으로 큼 |
assets
경로의 SVG 파일은 네임스페이스와 단위 제거가 필요 없으며 용량도 작아, 최적화를 위해 가능하면Path 추출 관련은 SVG
파일을 사용하는 방향으로 프로젝트를 진행하게 되었다.
본 트러블 슈팅 과정에서는 VectorDrawable
파일과 SVG
파일을 파싱하고 Android Compose에서 사용하는 과정에서 발생한 여러 문제를 해결하였다. 이를 통해 namespace
문제 해결, 단위 처리, 동적 비율 설정 등을 성공적으로 구현하였고, 최종적으로 SVG
파일을 사용하는 방향으로 결정하였다. 이번 과정을 통해 얻은 경험은 추후 유사한 파일 파싱 및 렌더링 문제 해결에 유용하게 활용될 수 있을 것이다.