가장 최근에 개발한 최종 프로젝트 Smit을 진행하며 처음으로 사용성 테스트도 진행해보고 사용자 경험 개선을 위한 최적화를 경험해보았다.
그 과정에서 내가 담당했던 프로필 수정과 관련된 최적화 경험을 작성해보려고 한다.
프로필 이미지를 사용하는 모든 페이지에서 프로필 이미지의 로딩이 과하게 길어지는 문제가 발생했다. 특히, 마이 페이지에서 사용하는 프로필 이미지의 경우 페이지 진입 시 가장 상단에서 제일 먼저 보이는 요소이기 때문에 빠른 해결이 필요한 상황이었다.
어디서 문제가 발생하는지 찾기 위해 프로필 이미지를 사용하는 모든 컴포넌트를 확인한 결과, DB의 user 테이블에 이미지 주소가 아닌, 스토리지에 저장되어 있는 파일 이름을 저장하고 있었기 때문에 유저 이미지를 불러오기 위해 매번 getPublicUrl 요청을 하고 있는 것을 확인할 수 있었다.
const profileImg = browserClient.storage
.from("profile_img")
.getPublicUrl(user?.profile_img ?? "default").data.publicUrl;
이는 프로필 이미지 변경 시, 스토리지에 파일을 저장한 후 주소를 요청하지 않고 user 테이블에 파일 이름만 저장하고 있었기 때문에 발생한 문제였다.
// 프로필 업데이트
export const updateUserProfile = async (name: string, img: string) => {
const user = await fetchSessionData();
if (!user) {
throw new Error("로그인 상태가 아님");
}
await browserClient
.from("user")
// 여기에 들어가는 img가 주소가 아닌 파일 이름
.update<TablesUpdate<"user">>({ name, profile_img: img })
.eq("id", user.id);
};
user 테이블의 프로필 이미지의 기본 값을 기본 이미지 주소로 변경 후, 프로필을 수정할 때 스토리지에 저장한 파일의 주소를 받아 해당 주소를 저장하는 것으로 변경하여 불필요한 api 요청을 제거하여 로딩 속도를 개선할 수 있었다.
const profileSaveHandler = async () => {
// 이미지를 변경했을 경우
if (fileInputRef.current?.files && fileInputRef.current.files.length > 0) {
// 새 이미지를 스토리지에 저장
const { error } = await browserClient.storage
.from("profile_img")
.upload(`${user?.id}`, fileInputRef.current.files[0], {
upsert: true,
});
if (error) {
return;
}
// 저장한 이미지의 주소 요청
const url =
browserClient.storage.from("profile_img").getPublicUrl(user.id).data
.publicUrl +
"?t=" +
Date.now();
// 실제로 프로필을 수정하는 함수로 이미지 주소 보내기
updateProfile(url);
return;
}
// 이미지 변경 안 하면 기존 주소로 전송
updateProfile(user.profile_img);
};
모든 페이지에서 이미지 로딩 속도가 개선되었으나, 마이 페이지에서는 로딩이 바로 되었으면 좋겠어서 Next Image 태그에 속성을 추가하여 해결했다.
priority 속성
priority 속성은 Next.js 에서 제공하는 Image 컴포넌트의 속성으로 특정 이미지를 초기 페이지 로딩시 우선적으로 로드하도록 설정하는 속성이다.
이 속성이 적용된 이미지는 preload 태그를 통해 브라우저에 우선 로딩 요청을 보내어 브라우저가 해당 이미지를 우선적으로 로드할 수 있도록 한다.
비슷하게 HTML 기본 속성인 loading="eager" 설정이 있는데 두 속성은 차이가 존재하며 Next 에서도 prioriry 속성 사용을 권장하고 있다.
priority 속성과 loading="eager"의 차이
loading eager 속성은 이미지를 즉시 로드하도록 설정하는 HTML 표준 속성이다.
- priority는 Next.js의 이미지 최적화 메커니즘과 함께 작동하기 때문에, 성능을 유지하면서도 중요한 이미지를 우선적으로 로드할 수 있다. 반면, loading="eager"는 브라우저의 기본 동작을 바꾸는 것일 뿐, 최적화 기능이 없어서 예상치 못한 성능 저하가 발생할 가능성이 있다.
웹 성능 지표 중 하나인 LCP(사용자가 페이지를 로드할 때 가장 큰 콘텐츠가 화면에 렌더링되는 시간)는 사용자 경험에 있어 아주 중요한 부분인데, priority 속성을 추가함으로써 해당 부분을 많이 개선할 수 있었다.