평화롭게 마이페이지 프로필 수정 기능을 개발하던 중 이슈를 마주치게 됩니다.

프로필 수정 화면에서 데이터를 변경했음에도 불구하고 닉네임은 정상적으로 변경되지만 프로필 이미지의 경우 변경되지 않습니다.

현재 서버는 프로필 이미지가 변경되더라도 이미지 url 이 그대로 유지되며, url 을 호출할 때만 변경된 이미지가 반영되는 구조입니다. 따라서 url 이 변경되지 않아 Recomposition 이 발생하지 않기 때문에 기존 캐시된 이미지가 그대로 표출되는 것입니다.

Recomposition 이 발생하도록 url 에 조금의 변형(?)이 필요하다고 생각했고, 우리는 프로필 이미지 url 에 timestamp 라는 쿼리 파라미터를 추가하게 됩니다.

timestamp 를 설정함으로써 프로필 이미지가 Recomposition 이 발생하도록 하여 이슈를 해결할 수 있었습니다.

닉네임만 수정했는데도 프로필 이미지까지 recomposition 이 발생하는 것이었습니다. (생각보다 예제 화면에서는 엄청 티가 나지 않네요.)
이미지가 변경되지 않더라도 timestamp 로 인해 이미지 url 은 계속 변경되었기 때문에 recomposition 이 발생할 수밖에 없었습니다.
이미지 로딩에 Coil 라이브러리를 사용하고 있고, Coil 의 캐싱 처리를 제대로 사용하지 못할 뿐더러 불필요한 recomposition 을 최소화 하고 싶었기에 다시 한 번 문제 해결을 시작합니다.

이때 Coil 의 memoryCacheKey 속성을 발견합니다.
Coil 은 메모리 캐시에 저장을 할 때 키값을 기준으로 이미지를 저장합니다. 만약 키를 따로 설정하지 않으면 Coil 이 자체적으로 키를 설정하여 사용하게 됩니다.
기존에는 memoryCacheKey 를 따로 설정하지 않았기 때문에 Coil 이 자체적으로 설정하였고, 이때 url 이 변경될 때마다 각각 다른 키를 사용하여 메모리캐시에 저장되어 캐싱이 정상적으로 진행되지 않은 것이죠.
AsyncImage(
model = ImageRequest.Builder(LocalContext.current)
.data(profile.image)
.memoryCacheKey(profile.userId)
.build(),
contentDescription = null,
modifier = Modifier.size(120.dp).clip(CircleShape).background(Color.Gray),
contentScale = ContentScale.FillBounds,
)

timestamp 를 쿼리 파라미터로 추가하는 방식 대신 memoryCacheKey 속성을 사용하여 캐시 키를 설정했습니다. 이때 캐시 키는 userId 를 사용하였습니다. 이를 통해 프로필 이미지는 동일한 캐시 키를 갖게 되었고, 이미지가 변경됐을 때만 재로딩이 되도록 수정하였습니다.