아티워크(Artiwork) 개발기 - 1. 사용자 경험 개선

임경섭·2026년 6월 25일

Artiwork

목록 보기
1/2
post-thumbnail

최근에 아티워크가 새 단장을 마치고 리뉴얼 오픈을 했습니다!
아티워크는 작가의 작업 과정을 기록하고, 전시·공모 일정을 한눈에 확인할 수 있는 앱입니다.
현재 App Store, Google Play에 올라가 있으니, 궁금하신 분들은 한번 다운받아 사용해보시면 좋겠습니다.

이번 글에서는 개발하면서 마주쳤던 예기치 못한 문제 3가지와, 이를 어떻게 발견하고 해결했는지를 정리해 보려 합니다.

1. 달력 제스처 충돌 — 상하 스크롤과 좌우 스와이프가 동시에 잡히던 문제

달력 화면에는 두 가지 제스처가 공존합니다. 위아래로 스크롤 하여 달력의 확장 영역을 탐색하고, 좌우로 스와이프 시, 월 전환을 합니다. 그런데 손으로 하는 제스처다 보니 정확히 수직, 수평으로만 움직이지 않습니다. 두 방향이 동시에 인식되면서, 의도와 달리 달력이 대각선으로 끌려가는 현상이 생겼습니다.

원인은 세로 스크롤과 좌우 월 전환 제스처가 경쟁 상태(race condition)에 놓인 것이었습니다. 그래서 제스처에 우선순위를 부여하는 로직을 직접 구현했습니다.(react-native-gesture-handler)

if (type === 'month') {
      panGesture = panGesture.activeOffsetX([-6, 6]).failOffsetY([-24, 24]);
}
  • 좌우로 6px 이상 움직이면 Pan 제스처가 활성화됩니다.
  • Pan이 활성화되기 전에 상하로 24px 이상 움직이면 Pan이 실패(fail) 하고, 터치는 ScrollView의 세로 스크롤에 넘깁니다.

즉, 특정 방향 이동량이 임계값을 넘으면 해당 방향 스크롤에 우선권 부여하여 사용자가 원하는 방향으로 이동하게끔 수정했습니다.

2. 작업 사진 저장 시, 사용자 체감 시간 증가 - 비동기 업로드로 풀어내기

작업 사진을 등록하는 과정은 아래와 같이 긴 과정을 거칩니다.

사진 촬영 → 캡션 입력 → signed URL 발급 → S3 업로드 → picture/caption API 호출 → 홈 탭으로 이동

업로드 파이프라인이 길고 순차적으로 실행되다 보니 사용자가 작업 사진 등록을 기다리는 시간이 길었습니다.
홈 화면에서는 이미 스켈레톤 UI가 적용돼 있다는 점에 착안했습니다. 사용자를 먼저 홈으로 이동시키고, 업로드는 백그라운드에서 처리하는 방식입니다.

  • imageUri, task, date, caption을 payload로 먼저 고정한 뒤, void (async () => { ... })()로 화면과 무관하게 업로드를 실행
  • 서로 의존하지 않는 로컬 이미지 읽기와 signed URL 발급은 Promise.all로 동시에 실행

다만 한 가지를 고려하지 않았습니다. 사용자가 빠르게 홈 화면으로 이동을 했지만, 제대로 업로드가 완료됐는지 모릅니다. 그래서 전역 업로드 토스트를 만들어 진행 중·실패 상태를 앱 하단에 항상 노출했습니다.

결과적으로 즉시 화면을 복귀시켜 체감 대기 시간을 줄이고, 진행 상황을 한눈에 보여주면서 중복 제출까지 막을 수 있었습니다.

3. 미술달력 탭 이동시 데이터 지연 - prefetch로 성능 개선

미술 달력 탭에 진입하면 전시 공모 프로그램, 찜 목록, 광고 등 다양한 API를 호출합니다. 그래서 달력 프레임은 먼저 떠도, 그 안을 채우는 데이터가 한 박자 늦게 노출되는 현상이 있었습니다.

이를 React Query의 prefetch로 해결했습니다. 로그인.온보딩 완료 직후 usePrefetchProgramCalendar로 React Query 캐시에 선적재하고, 탭 버튼을 누르는 시점에도 한 번 더 호출해 최신 데이터를 보장했습니다.

이 조건을 통해서 “메인 탭(작업 달력 홈)에 정상 진입한 사용자”일 때만 백그라운드 prefetch를 돌렸습니다.

// _layout.tsx

// 로그인을 한, 작업 데이터를 불러오는 중이 아닌, 작업이 하나 이상 있을 때
// OAuth 가입자가 첫 작업 만든 뒤 약관 동의 화면에 있을 때 prefetch 동작
const canPrefetchProgram = !!session && !isTasksLoading && !!tasks && tasks.length > 0 && !needsOAuthPostTaskTerms;
  usePrefetchProgramCalendar(canPrefetchProgram);
// prefetchProgramCalendar.ts

// 미술달력 탭 진입 전 contests·ads(detail)·pin·programs 데이터를 React Query 캐시에 적재
export function prefetchProgramCalendarQueries(...) {
  return Promise.all([
    queryClient.prefetchQuery({ ... '/contests' ... }),
    queryClient.prefetchQuery({ ... '/ads' placement: 'detail' ... }),
    queryClient.prefetchQuery({ ... '/contests/pin' ... }),
    queryClient.prefetchQuery({ ... '/programs' ... }),
    queryClient.prefetchQuery({ ... '/programs/pin' ... }),
  ]);
}

마치며

3가지 모두 개발을 하며 "동작은 하지만, 사용자 입장에서 생각했을때 이런 부분은 불편하지 않을까?" 생각하며 개선할 점을 찾았습니다.

수직, 수평 제스처 동작을 점검하면서 웹과는 다른 모바일만의 인터랙션을 경험할 수 있었고, 업로드의 백그라운드 처리와 데이터 처리 타이밍 문제까지 차근차근 들여다볼 수 있었던 좋은 시간이었습니다.

profile
즐겁게 코딩 ૮₍ •̀ᴥ•́ ₎ა

0개의 댓글