Search
🩹

실생활 코드 활용기 1 - 신점 지각 체크

AI custom autofill
Published
2025/01/27
Category
Programming
Tags
Daily Usage
우리 교회 청년부 찬양팀에서는 매주, 네이버 밴드에 신앙점검표 라는 게시글을 쓴다. (해당 주 동안 묵상한 말씀, 기도제목, 감사제목, 라인업 피드백, 콘티 묵상, 삶 등 여러가지 주제로 일주일간의 삶을 공유한다.)
매년 밴드 게시글을 체크하는 사람은, 일일이 게시글 날짜와 시간을 보고 지각여부를 체크한다.
2025년 밴드팀장이 되어 해당 업무(?)를 맡게 되었는데, 매번 체크하기 귀찮기도 했고 충분히 자동화를 할 수 있을 것 같아, 이렇게 글을 적게 되었다.

#1 요구사항 파악

매주 글을 쓰지 않은 인원들에 대해 지각비를 부여하기 위해, 밴드 게시글을 매주 체크한다.
해당 주 월~토요일 05:30분까지 올린 대상자는 통과
해당 주 토 05:31 ~ 일 23:59분까지 올리는 대상자에게는 지각벌금 2,000원
해당 주에 게시글을 올리지 않는 사람은 벌금 5,000원
복잡하지 않은 정책이며, 충분히 개발 가능한 요구사항이라고 판단!

#2 개발여부 확인

우선, 사전에 조사해야 할 건 Naver Band API 였다.
당연히 서비스 신청을 통해, ACCESS_TOKEN을 발급 받아야 한다!
필요한 API에는,
1.
해당 밴드 모임에 가입한 멤버 조회
해당 밴드에 가입된 유저를 대상으로 지각자 파악 필요
2.
해당 밴드 모임의 글 목록 조회
하지만,
1번 API는 보안이슈상 존재하지 않아 보였다.
(한번 뚫어볼까 하다가 블로그에 적합하지 않아보여 멈췄다..)
2번 API는 글 목록 조회 라는 API가 있었다.

#3 개발 방향성 정의

처음에는 최대한 모듈화를 통한 확장성있게 재사용성에 용이한 코드를 작성하려고 했다.
하지만, 찬양팀으로 함께 한지 3년차동안 바뀐거라고는 멤버와 시간룰 밖에 없었기에, 해당 변수만 constant 로 관리하기로 하고 개발에 들어갔다.
1.
해당 밴드 모임에 가입한 멤버는 얻을 수 없는데?
→ 멤버는 신입멤버 혹은 중간에 나가는 멤버에 대한 이벤트는 자주 발생하지 않기 때문에 멤버 리스트는 하드코딩 하기로 결정!
(등록되어 있는 멤버 프로필의 이름 사용; 이름을 무작정 바꾸지마라고 통보함 ㅎㅎㅎ)
2.
해당 밴드 모임의 글 목록 조회시, 날짜 범위를 둘 수 없는데?
최신 20개의 글만 제공하고, 그 이전 글은 해당 호출에 next_params라는 결과 값을 넣어 API 재호출
조회하고 싶은 날짜 (2025-01-06 ~ 2025-01-12)
조회하고 싶은 이전 날짜 (2025-01-01 ~ 2025-01-05)
조회하고 싶은 이후 날짜 (2025-01-13 ~ 2025-01-19)
→ 셋팅한 특정 날짜내 밴드 게시글만 필터링 대상에 적용 (설정한 시점 이후 글이 있는 경우 재호출 하지 않음)
3.
밴드키는 어디서 얻는가?
밴드 목록 조회 API 를 호출하여, 밴드 키를 얻고 해당 밴드 키를 글 목록 조회 파라미터로 넣는다. (해당 정보가 없어서 살짝 헤맸다..)

#4 코드

예외 처리같은 건 충분히 하지 않았습니다. 참고만 하시길 바래요.

가입한 밴드 리스트 조회

const getBandKey = async () => { const res = await axios.get(`${HOST}/v2/bands?access_token=${ACCESS_TOKEN}`, { headers: { 'Content-Type': 'application/json' }, }); return res.data.result_data.bands.find(band => band.name == '').band_key;; };
JavaScript
복사

밴드 글 목록 조회

const getPosts = async after => { const params = { access_token: ACCESS_TOKEN, band_key: SINJEOM2025, locale: LOCALE, ...(after && { after }), }; const url = `${HOST}${API}?${new URLSearchParams(params)}`; const res = await axios.get(url, { headers: { 'Content-Type': 'application/json' }, }); return res.data.result_data; };
JavaScript
복사

지각대상자 추출

const filterPenaltyTargetCrews = async (from, to) => { const penaltyTargetCrews = []; const fromTime = new Date(`${from} ${FROM_TIME}`).getTime(); const middleTime = new Date(`${to} ${MIDDLE_TIME}`); middleTime.setDate(middleTime.getDate() - 1); const toTime = new Date(`${to} ${TO_TIME}`).getTime(); let toContinue = true; let after = undefined; while (toContinue) { const { items, paging } = await getPosts(after); after = paging.next_params?.after; for (const item of items) { const postCreatedAtTime = new Date(item.created_at); const postCreatedAt = item.created_at; // 날짜 범위에 포함되는 경우 if (postCreatedAt >= fromTime && postCreatedAt < toTime) { // 제출 CREWS = CREWS.filter(crew => crew !== item.author.name); if (postCreatedAt > middleTime) { // 늦게 제출 penaltyTargetCrews.push({ crewName: item.author.name, fee: LATE_FEE, }); } } else if (postCreatedAt > toTime) { // 날짜 범위에 포함되지 않는 경우 (이전 날짜) } else { // 날짜 범위에 포함되지 않는 경우 (이후 날짜) toContinue = false; break; } } // 더이상 글이 존재하지 않는 경우 if (!after) { toContinue = false; } } // 글을 쓰지 않은 멤버 추출 CREWS.forEach(crew => { penaltyTargetCrews.push({ crewName: crew, fee: NOT_SUBMITTED_FEE }); }); return penaltyTargetCrews; };
JavaScript
복사

결과 코드

(async () => { // 날짜 설정 const startDate = '2025-01-13'; const endDate = '2025-01-19'; const penaltyCrews = await filterPenaltyTargetCrews(startDate, endDate); console.log(`\n[${startDate} ~ ${endDate}]`); penaltyCrews.forEach(({ crewName, fee }) => { console.log(`${crewName}: ${fee.toLocaleString()}`); }); })()
JavaScript
복사

예시

[2025-01-06 ~ 2025-01-12] 안혜인: 2,000원 김창수: 5,000원 김하윤: 5,000원 송인석: 5,000원 이종탄: 5,000원 조연채: 5,000원
Plain Text
복사
이렇게 하면, 우리 찬양팀 팀장님께서 엑셀에다가 손수 기록하신다.
엑셀에다가도 자동 업데이트를 할 예정이긴 했지만, 그건 팀장님 영역이라 여기까지가 나의 영역 범위 내 최대한의 자동화였다.
간만에 THIRD API를 활용하여 실생활에 적용하는 케이스라, 간단하게 기록을 해 보았다.
매우 효율적인; 빠르고 스트레스 받지 않는, 방향으로 삶의 귀찮은 문제들을 풀어낼 수 있다는 게 개발자의 가장 큰 메리트이지 않나 싶다.
재밌었다!!!