아무래도 완벽한 코드를 한번에 작성하는 것은 어려운가보다. 그래서 위치기반 기능에서 발견한 약간의 버그들을 리팩토링했다.
이건 상상도 못한 이유였다. 나는 서울에 거주하면서 서울에서만 위치 테스트를 진행했고 지방에서는 테스트를 하기 어렵다는 생각이 들었다. 하지만 브라우저 자체에 위도 경도를 넣어주면 해당 주소로 접속이 가능하다는 것을 알고 여러 지역을 토대로 테스트를 진행했다.
간단하게 브라우저에서 위치를 변경하는 방법은

개발자 도구에서 sensors에 들어가면 위도 경도를 바꿀수가 있다. 위에 이미지에서 보면 location이라고 있는데 이 옵션을 others로 변경해주면 위도 경도 인풋이 활성화된다.
이제 주소를 다른 도시로 이동하고 실행해봤는데 제대로 동작하지 않았다. 그래서 카카오맵을 통해 받는 주소를 확인해보니
const currentLocation = `${mapResult[0].region_1depth_name} ${mapResult[0].region_2depth_name}`;
광역시 이상의 도시에서는 구까지만 location에 들어가고 그 외의 지역에서는 시까지만 locatioin이 필요하다. 하지만 mapResult[0].region_2depth_name에서 00시 00구까지 반환되는 것을 확인할 수 있었다. 현재 우리 서비스는 00도 00시이런식으로 string값만 들어간다. 그래서 00도 00시 00구은 우리 로직상 구분할 수가 없는 것이다.
const replaceEmpty = mapResult[0].region_2depth_name.split(' ');
const currentLocation = `${mapResult[0].region_1depth_name} ${replaceEmpty[0]}`;
그래서 한번의 가공을 더 거쳐줬다. 00시 00구라는 문자열에서 가운데 빈칸을 기준으로 나눠 문자열 배열을 만들어 준다. 그리고 배열 index 1번에 있는 지역구는 필요가 없기 때문에 0번만 사용해준다. 그러면 우리가 원하는 대로 동작이 가능해진다.
이렇게 했을때 잘 되야하는데 전주로 위치를 저장한후 실행했을때 제대로 동작하지 않았다. 그래서 다시 location을 확인해보니 전라북도가 아니라 전북특별자치도로 확인이 되었다. 그 외에도 강원도도 강원특별자치도로 확인했다. 그래서 우리가 지정한 location상수값에 이름을 변경해줬다. 이후에는 잘 동작한다!
이런 실수는 참 아쉽다. 조금더 제대로 조사 및 검색해서 적용해야겠다.
지금까지는 localstorage에 유저의 로케이션값을 저장했다. 하지만 이렇게 하다보니 처음 유저가 페이지에 접근하고 일부로 새로고침을 하지 않는 이상 아무런 변화가 일어나지 않는다. 당연히 next내부에서는 변한게 없기 때문이다. 그래서 사용자가 위치허용을 하면 바로 적용이 되도록 localstorage를 사용하지 않고 state를 사용했다.
...
const [userLocation, setUserLocation] = useState<string[]>([]);
const getAddress = (mapResult: any, mapStatus: any) => {
if (mapStatus === window.kakao.maps.services.Status.OK) {
const currentLocation = `${mapResult[0].region_1depth_name} ${mapResult[0].region_2depth_name}`;
const replaceEmpty = mapResult[0].region_2depth_name.split(' ');
const currentLocation = `${mapResult[0].region_1depth_name} ${replaceEmpty[0]}`;
const { id, list } = LOCATIONS[mapResult[0].region_1depth_name];
if (id > 10) {
const singleLocation = [currentLocation];
setUserLocation([currentLocation]);
return;
}
...
currentLocation,
`${mapResult[0].region_1depth_name} ${nearByLocation}`,
];
setUserLocation([...userLocationList]);
}
};
location을 넣지않고 리스트를 불러올때는 잘 동작한다. 하지만 location을 추가해서 리스트를 불러오면 상단에 해당하는 액티비티까지는 문제없지만 이후에 추가로 불러오는 리스트에 같은 액티비티가 껴서 오는 것을 확인했다. 그래서 코드를 디버깅을 실시했다.
그 결과 백엔드나 불러오는 로직자체는 아무런 문제가 없었다. 이 문제는 무한스크롤을 동작할때에만 생긴다는 것을 알았다. 그래서 무한 스크롤 로직을 확인해보니
const loadMoreActivities = useCallback(async () => {
startTransition(async () => {
if (!infinityCursorId) return;
const result = await getActivities({
type: sort,
cursor: infinityCursorId,
size: 5,
});
setInfinityCursorId(result.cursorId);
setInfinityActivities((prev) => [...prev, ...result.activities]);
});
}, [infinityCursorId, sort]);
로케이션이 포함되지 않았던 것이다.
...
switch (type) {
case 'recent':
activities = await db.activity.findMany({
...baseQuery,
where: location ? { location } : {},
orderBy: {
createdAt: 'desc',
},
});
break;
우리가 데이터를 불러오는 로직을 확인해보면(최신순일때만 대표적으로 확인해보겠다.) location이 있을때에만 location에 해당하는 것을 불러온다. 그럼 처음 리스트를 불러올때는 location이 있기 때문에 해당하는 것을 잘 불러오지만 이후에 무한 스크롤을 통해 불러오는 리스트에는 모든 리스트를 다시 불러오기 때문에 중복되는 액티비티가 확인되는 것이다.
const loadMoreActivities = useCallback(async () => {
startTransition(async () => {
if (!infinityCursorId) return;
const result = await getActivities({
type: sort,
cursor: infinityCursorId,
size: 5,
location,
});
setInfinityCursorId(result.cursorId);
setInfinityActivities((prev) => [...prev, ...result.activities]);
});
}, [infinityCursorId, location, sort]);
그래서 간단하게 location을 추가해주니 이후에는 잘 동작한다.
지금은 location을 기반으로 액티비티를 불러오면 지정한 size보다 작을 경우에 다른 리스트를 붙여준다. 쉽게 얘기하면 5개를 요청했는데 해당 액티비티가 2개밖에 없다면 추가로 원래 리스트를 붙여주는 것이다.
if (location && activities.length < size) {
const remainingSize = size - activities.length;
const additionalActivities = await db.activity.findMany({
...baseQuery,
where: {
location: { not: location },
},
take: remainingSize,
orderBy: {
createdAt: 'desc',
},
});
activities = [...activities, ...additionalActivities];
}
이 로직을 통해서 그런 동작이 이뤄진다. 하지만 여기에서 문제는 size와 activites의 length가 같은 경우에는 아무런 조치를 취할수가 없다는 것이다. 만약 여기에서 size === activities.length같은 조건부를 붙여도 이게 5개보다 더 있는지 이게 마지막인지 확인이 안된다. 우리가 전문적인 백엔드개발자가 아니다보니 다음 리스트를 미리 확인하는 일은 조금 어려웠다. 이건 조금더 고민해보고 리팩토링을 하거나 기능을 수정해야 할 것 같다.
매번 코드 수정을 하는데 계속 수정할게 나오다니...양파같은 놈... 그래도 완성도가 높아지고 있다는 증거니까 나름 뿌듯하다. 일단 마지막에 정리한 문제점을 빠르게 수정하고 넘어가야겠다. 실제로 주변 지인들이 시연해보면서 지역선택을 했는데 다른 지역리스트가 섞여서 오다보니 조금 헷갈린다는 의견이 있었는데 사용자 의견을 반영해서 아예 해당하는 액티비티만 불러오도록 해도 좋을 것 같다.
다음에는 위치기반 슬라이드에 좌우 스크롤 대신 좌우 스크롤 버튼을 추가해주도록 하겠다. 라이브러리도 많지만 엄청 어려운 기능을 동반하지 않기 때문에 직접 구현해보려고 한다.