🎯 프로젝트 소개
대부분의 날씨 정보 서비스들은 현재와 미래의 날씨 정보만을 직관적으로 제공하며, 과거의 날씨는 '지나간 정보'라는 이유로 제공하지 않거나 추가 클릭을 통해서만 확인할 수 있습니다. 하지만 우리는 어제 경험한 날씨를 통해 오늘의 체감 온도를 더 정확하게 예측할 수 있습니다. "어제보다 더 춥다" 또는 "어제보다 덜 덥다"와 같은 비교는 일상생활에서 매우 유용하게 활용됩니다. 이러한 사용자 경험을 바탕으로, 어제-오늘-내일의 날씨를 최고/최저 온도로 한눈에 비교할 수 있는 서비스를 기획하게 되었습니다.
🔄 프로젝트 발전 과정
초기 개발 (2023년)
2023년도의 저에게 이 프로젝트는 매우 도전적이었습니다. TypeScript와 WebPack을 처음 배우면서 시작한 프로젝트였기 때문입니다. 하지만 당시 회사에서 야근이 잦아 원하는 프로젝트 속도가 나오지 못했습니다. 또한 API 문서도 처음 읽게 되어 파악하기가 쉽지 않았습니다. 결국 기획한 의도대로라면 어제의 날씨를 제공한다는 점이 타 사이트에 비해 특이점인데, 이를 구현하지 못하고 오늘의 날씨를 기반으로 내일을 대비한다는 의미로 방향을 바꾸게 되었습니다.
리팩토링 (2024년)
처음 기획했던 방향이 아니기에 미련이 많이 남았고, 퇴사 후 2024년에 여유가 생기고 난 뒤 리팩토링을 진행하게 되었습니다. 그리하여 어제-오늘-내일의 날씨를 제공하는 기획대로의 사이트를 완성했습니다.
사용기술
- TypeScript: JavaScript의 타입 안정성을 확보하고, 실제 프로젝트에 적용하며 학습하고자 선택
- WebPack: 채용공고에서 종종 보이는 기술로 무엇인지 직접 경험해보고 싶어 선택
- 다중 API 활용:
- HTML5 Geolocation: 사용자의 현재 위치 좌표 획득을 위해 사용
- 카카오 맵 API: 위도/경도를 주소로 변환을 위해 사용
- 기상청 종관예보 API: 어제의 온도를 가져오기 위해 사용
- 기상청 단기예보 API: 오늘, 내일, 글피, 그글피의 데이터(온도, 날씨)를 가져오기 위해 사용
- 기상청 중기육상예보 API: 주간 날씨 데이터를 가져오기 위해 사용
- 기상청 중기기온조회 API: 주간 온도 데이터를 가져오기 위해 사용
초기 기획했을 땐 이 간단한 프로젝트에 이렇게 많은 API가 들어갈지 몰랐고, WebPack이 생각했던 것보다 러닝커브가 있어 많이 헤매었습니다. 지금은 결국 다 해결하게 되었고 프로젝트를 진행하면서 직면했던 문제와 해결 과정을 공유하고자 합니다.
🛠 직면했던 문제와 해결 과정
1. 초기 로딩 최적화
발생한 문제는 초기 로딩이 굉장히 느리다는 점이었습니다. 하지만 로딩 이후에는 데이터가 잘 나왔기에 WebPack 설정이 잘못된 것이라 판단하게 되었고 WebPack에서 할 수 있는 설정들을 진행하게 되었습니다.
// webpack.config.ts
const webpackConfig = (argv: { mode: string }): webpack.Configuration => {
const isProduction = argv.mode === "production";
return {
// 기본 설정
optimization: {
minimize: isProduction,
minimizer: [new TerserPlugin(), new CssMinimizerPlugin()],
usedExports: true, // Tree Shaking 활성화
sideEffects: true, // 사이드 이펙트 제거
splitChunks: { // 코드 스플리팅
chunks: 'all',
},
},
// 기타 설정
};
};
webpack.config에서 설정한 내용
- Tree Shaking 활성화로 미사용 코드 제거
- 코드 스플리팅을 통한 번들 최적화
- 프로덕션 모드에서 코드 압축 및 최소화
하지만 좀처럼 초기 로딩 속도는 개선되지 않아 webpack-bundle-analyzer를 통해 어떤 번들 사이즈가 큰지 확인하게 되었고, 온도 비교 차트를 그리는 라이브러리인 Chart.js의 사이즈가 크다는 것을 발견했습니다. 이에 초기 번들 사이즈를 줄이고 필요한 컴포넌트만 가져오기 위해 아래와 같이 수정했습니다
import {
Chart,
LineController,
LineElement,
PointElement,
LinearScale,
CategoryScale,
Tooltip,
Legend,
ChartOptions,
} from "chart.js";
Chart.register(
LineController,
LineElement,
PointElement,
LinearScale,
CategoryScale,
Tooltip,
Legend
);
데이터 로딩 상태 처리
아무리 개선이 되었다고 하더라도 장소를 알기 위한 HTML5 Geolocation API, 카카오 맵 API, 장소를 알게 된 후 그 장소의 날씨 API들까지 총 6개의 API를 불러와서 차트를 그리는 단계까지는 어느 정도의 시간이 소요되었습니다. 그래서 사용자 경험 개선을 위해 로딩 스피너를 구현하여 데이터 로딩 상태를 시각적으로 표시했습니다.
2. API 응답 시간에 따른 데이터 불일치 문제
API 갱신 시간 차이로 인한 오류
24시쯤 사이트에 접속했을 때 갑자기 모든 API 값을 받아오는 부분에서 오류가 발생했습니다. '어제-오늘-내일' 온도 차트 및 주간 온도 차트 모두에서 오류가 발생하여 빈 화면이 나오는 것을 발견했습니다. 기상청 API의 문서를 다시 살펴보니, API마다 데이터 갱신 시간이 달랐습니다.
- 종간 예보: 11시 갱신
- 단기예보: 아래 사진 참조
- 주간예보: 6시/18시 갱신
날씨 조회 API를 총 4가지를 사용하면서 개발을 조금 더 편하게 하기 위해 공통되는 데이터 갱신시간을 매개변수로 주어 진행하려 했지만, 공통되는 시간이 없어 오류가 발생한 것이었습니다. 이를 해결하기 위해 현재 시간을 체크하여 각 API의 base_time을 동적으로 설정했습니다.
//데이터 갱신 주기에 따른 시간 설정
export const UPDATE_HOURS = {
YESTERDAY: 11,
WEEKLY: 6,
WEEKLY_WEATHER: 12,
};
// 종간 예보(어제)
const getYesterdayBaseTime = () => {
if (currentHour < UPDATE_HOURS.YESTERDAY) {
return getFormattedDate(-2);
}
return DATES.yesterday;
};
// 단기 예보(오늘, 내일, 글피, 그글피)
const getShortTermBaseTime = () => {
// 0~1시는 전날 23시 데이터 사용
if (currentHour < 2) {
return {
date: getFormattedDate(-1),
time: "2300",
};
}
// 그 외 시간은 02시 데이터
// 시간대 마다 가져오는 정보(fcstValue 예보날짜, category)가 다르기 때문에 02시로 지정하여 사용
return {
date: getFormattedDate(0),
time: "0200",
};
};
다중 API 호출 에러 처리
또한 `Promise.all`을 사용했기에 한 군데에서 오류가 나면 차트를 그리기 위해 묶여있는 모든 데이터가 한 번에 오류가 발생하는 문제가 있었습니다. 이를 해결하기 위해 `Promise.allSettled`로 코드를 수정했습니다:
export const processShortTermForecast = async (userLocation: userLocation) => {
try {
const [yesterdayResult, shortTermResult] = await Promise.allSettled([
fetchYesterdayForecast(userLocation),
fetchShortTermForecast(userLocation),
]);
if (
yesterdayResult.status === "rejected" ||
shortTermResult.status === "rejected"
) {
throw new Error("데이터 가져오기 실패");
}
const yesterdayItems = yesterdayResult.value;
const todayItems = shortTermResult.value;
processShortTermData(yesterdayItems, todayItems);
createShortTermChart();
} catch (error) {
console.error("단기 예보 데이터 처리 중 오류 발생:", error);
throw error;
}
};
3. API 공지사항 확인의 중요성
이후 어느 정도 리팩토링을 완료한 뒤 배포까지 완료하였으나, 11월 말부터 갑자기 주간 예보의 일부가 오류가 나기 시작했습니다. 또한 개선했다고 생각했던 초기 로딩도 다시 문제가 되었습니다.
잘 돌아가던 사이트가 갑자기 안되니 API가 문제가 된 경우 밖에 없겠다는 생각이 들게 되어 곧장 원인을 찾기 위해 공공데이터포털에 접속했고, 8월에 등록된 API 변경 예정 공지를 발견했습니다. 당시 다른 프로젝트를 진행하느라 놓쳤던 공지사항이 11월 말에 실제로 적용되면서 발생한 문제였습니다.
그리하여 해당 개선사항에 맞게끔 다시 코드를 수정하게 되었고 현재는 아주 잘 돌아가게 되었습니다.
✏️ 배운 점 및 향후 과제
배운 점
1. API 문서 이해의 중요성
- 같은 기상청 API라도 각각의 용도(종관예보, 단기예보, 중기예보 등)에 따라 다른 변수명을 사용
- API마다 다른 데이터 갱신 주기(11시, 6시/18시 등)를 가짐
- 초기에는 공통된 시간으로 처리하려다 오류 발생
- API별 특성을 고려한 설계의 중요성을 깨달음
2. API 변경사항 모니터링의 중요성
- 잘 작동하던 서비스가 11월에 갑자기 오류 발생
- 8월에 공지된 API 스펙 변경사항을 놓쳐 발생한 문제
- 실제 서비스 운영 시에는 사용 중인 API들의 공지사항을 주기적으로 확인하는 것이 필수
3. 다중 API 연동 시 고려사항
- 여러 API를 연동할 때는 각 API의 특성을 개별적으로 고려해야 함
- 하나의 통일된 방식으로 처리하려 하면 오류 발생 가능성이 높아짐
- 유연한 에러 처리의 중요성(Promise.allSettled 적용 등)
향후 과제
1. 세부 지역 날씨 데이터 제공 문제
- 어제의 날씨 데이터는 사용자의 정확한 위치가 아닌, 가장 가까운 기상 관측소의 데이터가 필요
- 현재 사용자 위치에서 가장 가까운 관측소를 찾는 코드 작성 및 관측소 별 위도/경도를 알아야 함
- 위 작업들이 필요하나, 시간 관계상 현재는 보류 상태
2. 날씨 차트 UX 문제
- 일반적으로 날씨 차트는 '오늘'이 맨 왼쪽에서 시작
- 하지만 이 서비스는 '어제'부터 보여주기 때문에 사용자가 혼란을 겪을 수 있음
- 어제/오늘의 구분을 더 명확히 할 수 있는 디자인 개선이 필요해 보임
✨ 결과
Before
- 오늘, 내일 최저/최고 온도 차트만 제공
- 단순한 온도 비교
After
- 기능 개선
- 어제, 오늘, 내일 최저/최고 온도 차트 제공
- 오늘 및 미래의 날씨 확인 가능
- 사용자 경험 개선
- 한눈에 파악하기 위해 온도 비교 텍스트 삽입 (예: "어제보다 2도 높아요")
- 날씨 아이콘 추가로 직관적인 정보 전달
- 반응형 디자인으로 모바일 및 테블릿 PC 환경 지원
- 기술적 개선
- API 호출 최적화
- 데이터 갱신 시간 안정화
- 에러 처리 강화
'코딩 > 트러블슈팅' 카테고리의 다른 글
Notice와 WOD 메뉴의 공통 컴포넌트화 과정에서의 TanStack Query (0) | 2025.01.27 |
---|---|
크로스핏의 다양한 기록 정렬: 17:17과 3R+12, 누가 더 잘한 걸까? (0) | 2025.01.03 |
Tanstack Query - prefetchQuery로 공휴일 데이터 패칭 최적화하기 (0) | 2024.11.19 |
React-Quill 게시물 저장 방식 개선하기: HTML에서 Delta로 (0) | 2024.11.10 |
주니어 개발자의 보안 취약점 도전기: 총 30개의 취약점 100% 해결 (1) | 2024.10.22 |