학교 앱에서 4달 동안 급식 API가 멈춘다면

학교 앱에서 4달 동안 급식 API가 멈춘다면

작성자
태인태인
카테고리
⚗️ 프로젝트
작성일
2023년 11월 23일
태그
Web
DB
nodeJS

사건의 발단(1)

성일고 앱인 ‘쏙’의 주요 기능 중 하나는 바로 NEIS에서 급식 정보를 불러와 표시해주는 것이다. 그러던 어느 날, NEIS Open API 사이트에 다음과 같은 공지가 올라온다.
일시중지 기간이 뭐 이렇게 길어요..
일시중지 기간이 뭐 이렇게 길어요..
“Open API 조회 오류가 예상됩니다”
?!
비상이다.
잠깐, 내가 운영하고 있는 앱은 전국 단위의 학교를 대상으로 하는 서비스가 아닌 내가 재학중인 학교, 즉 단 1개의 학교를 대상으로 서비스하고 있기 때문에 우리학교의 데이터만 미리 가지고 있다가 서빙해주면 해결되는 문제이다.

해결해보자

먼저 현재 쏙의 API 서버를 살펴보자.
급식 데이터를 응답해주는 로직은 간단하다. NEIS에서 제공하는 Open API로 클라이언트에서 받아온 날짜 데이터를 파라미터로 넣어 요청을 보낸 뒤, 해당 요청 중 불필요한 정보를 제외한 급식 메뉴 값을 JSON 형태로 반환하는 것이다.
이때, 급식 데이터의 경우 한 번 값을 받아온 이후로 거의 변하지 않는다. 한 달 단위로 급식 데이터를 가져오니 더더욱 그렇다. 따라서 API 서버에서는 redis를 사용한 캐싱을 사용하고 있다.

캐시란?

사용자 입장에서 자주 사용하는 데이터를 더 빠르게 접근할 수 있도록 값을 임시로 저장해두는 저장소를 의미한다. 대부분의 어플리케이션에서 속도 향상을 위해 캐시를 사용한다.
 
캐시는 아래와 같은 경우에 유용하게 사용될 수 있다.
  1. 캐시 저장소에 접근하는 속도가 원본 데이터 저장소 접근 속도 보다 빠른 경우
  1. 동일한 데이터에 반복적으로 액세스하는 상황인 경우
  1. 잘 변하지 않는 데이터인 경우

Redis (REmote DIctionaly Server)

레디스는 고성능의 오픈소스 NoSQL 라이브러리이다. 레디스는 모든 데이터를 메모리에 저장하기 때문에 최적화된 데이터 읽기, 쓰기가 가능하다.
 
예를 들어, 6월의 급식 데이터를 처음으로 요청한다면 외부 API에서 받아온 데이터를 클라이언트에 응답하는 동시에 Redis에 저장하도록 한다. 이후 다시 6월의 급식 데이터 요청이 들어올 경우, 외부 API를 호출하지 않고 redis에 저장되어 있는 데이터를 가져와 응답해주는 것이다.
 
아래와 같이 구현 가능하다.
... app.get('/meal/:data', async (req, res) => { var date = req.params.date.toString(); var year = date.substring(0, 4); var month = date.substring(4, 6); const cacheKey = 'mealData_'+year+month; client.get(cacheKey, async (err, data) => { if (err) { console.error(err); return res.status(500).send('Internal Server Error'); } if (data) { // 캐싱된 데이터가 있을 경우 return res.status(200).send(JSON.parse(data)); } else { // 캐싱된 데이터가 없을 경우 try { const response = await axios.get('https://open.neis.go.kr/hub/mealServiceDietInfo'); const responseData = response.data; // API 결과 데이터 가공 로직은 생략 client.setex(cacheKey, 1440, JSON.stringify(responseData)); //24시간동안 저장 res.status(200).send(responseData); } catch (error) { console.error(error); res.status(500).send('Error fetching data'); } } }); }); ...
 
그런데 지금은 1440분, 즉 24시간동안만 데이터를 캐싱해두기 때문에 이번처럼 하루 이상 API가 중단되는 상황에서는 무용지물이 될 것이다. 점검이 시작되고 24시간이 지나면 다시 외부 API에 요청을 보낼 것이고, 급식 데이터 대신 오류를 받아올 것이기 때문이다.
 
따라서 캐시 유지 시간을 좀 더 길게 조절해보자. 30일로!
const CACHE_EXPIRATION = 30 * 24 * 60 * 60;
 
이제 해당 월의 정상 데이터가 1번만 서빙된다면, 이후에는 외부 API에서 값이 올바르게 반환되지 않더라도 문제없이 급식 데이터를 클라이언트에 전달할 수 있게 된다.
사실 생각해보면 이번 이슈 대응이 아니더라도 급식 메뉴가 1달동안 바뀔 가능성은 0에 수렴하기 때문에 캐시 만료 시간을 24시간이 아닌 30일로 설정하는 것이 바람직해보인다. 그래서 현재도 해당 정책을 유지중이다.

 
결국 NEIS 점검 기간 중에도 쏙은 급식 정보를 문제없이 제공할 수 있었다.
이렇게 해피엔딩인 줄 알았으나…
 

사건의 발단(2)

notion image
예???
점검이 끝나고 서비스 재오픈 첫날부터 먹통이 됐다는 기사가 헤드라인을 장식한 것이었다.
이후 며칠간 서비스 오류 발생과 이를 알리는 기사가 이어졌지만, 다행히 OPEN API에는 첫날을 제외하면 영향을 주지 않았다.

다행인 줄 알았다.
근데 왜 아직도 급식 데이터가 안 넘어오는 것인가…
notion image
총체적 난국이다
급식 정보 개방 정책이 변경되어서 학교에서 급식 식단을 등록할 때 식단공개확정 처리를 해야 API에도 해당 데이터가 반영된다는 것이다.
(학교 측에 대응을 요청했지만, 일개 학생은 힘이 없기 때문에 결과론적으로는 4달동안 NEIS API에 급식 식단이 등록되지 않았다는 무서운 이야기)
 

결국, 답은 하드코딩

………..
………..

댓글

guest