Tagby company 에서 기업협업을 진행하게 되었습니다.
2개월차 개발자로써 부족한 점이 너무나도 많다는 것을 깨닫게 되었습니다. 프로의 세계는 아무도 기다려주지 않고 그 아무도 관심을 가져주지 않기 때문입니다. 프로젝트를 완료하고는 다른 회사에 취직을 할 예정인데, 취직하기전 그리고 후에도 계속 CS나 자바스크립트에 대하여 공부할 예정입니다. 더 많은 것을 배워 귀찮은 것들을 프로그래밍화하여 편한 세상을 만들어야겠습니다.
이번 프로젝트 역시 귀찮은 일을 자동화 시스템으로 만드는 일을 했습니다. 스케줄러를 생성해서 매시간마다 같은 작업을 반복하는 기능을 구현했습니다.
PROJECT 설명
광고주에게 인스타나 네이버에 광고한 내용들이 얼마나 노출이 되었는지 확인시켜주기 위해 매시간마다 네이버나 인스타에 검색해서 회사에서 고용한 인플루언서가 노출이 되었는지 확인 후 노출이 되었다면 그 화면을 캡쳐해서 광고주에게 전달해야하는 것을 자동화 기능 구현
프로젝트 정보
- 기간 : 2022년 12월 12일 ~ 2023년 1월 5일 (4주)
- 팀원 : Frontend 2명, Backend 2명
- 레포지토리 : https://github.com/hosose/project-msg-tagby-
구현한 기능
1. 기본 API
- 항상 사용하는 DB 저장 및 불러오기 api 구현
- 스케줄러를 작동시키기 위한 schduler post
- 스케줄러 불러오는 scheduler get
- 스케줄러 수정하는 scheduler patch
- 스케줄러 삭제하는 scheduler delete
- 회사 api 접속하는 campaign get
- 캡쳐한 사진 불러오기
2. 스케줄러 API
- 모듈을 이용하여 스케줄러 기능 구현
- node-cron 모듈을 이용(1시간마다 함수 실행)
const cron = require('node-cron');
const task = cron.schedule(' 0 0 * * * *', async () => {
//1시간마다 함수 실행
}
- 스케줄러 실행 기간 설정 내에서 스케줄러 작동 구현
- 오늘이 1월 4일이면 만약 등록한 스케줄이 1월 3일 ~ 1월 6일이면 작동을 하고 기간 외의 시간이면 작동 상태를 변경하는 기능 구현
- waiting인 스케줄을 불러와서 기간이 되었으면 상태를 working으로 변경 -> working인 스케줄이 기간이 지나면 end로 변경
//대기상태의 스케줄
const waitingScheduler = await schedulerDao.getSchedulerDetailInfo(
`AND cj.state ='waiting'`
);
for (j of waitingScheduler) {
let startday = new Date(j.start_day);
let endday = new Date(j.end_day);
if (startday < today && endday > today) {
await schedulerDao.patchSchedulerWorking(j.idx);//기간내로 되면 working으로 변경
}
}
//working 상태의 스케줄
const scheduler = await schedulerDao.getSchedulerDetailInfo(
`AND cj.state ='working'`
);
for (i of scheduler) {
let startday = new Date(i.start_day);
let endday = new Date(i.end_day);
if (startday < today && endday > today) {
await schedulerDao.updateRunCount(i.idx);
await crawlingService.start(
i.campaign_idx,
i.keyword,
i.sns_type,
i.idx,
i.posting_url
);
} else if (endday < today) {
schedulerDao.patchSchedulerEnd(i.idx); //기간이 지나면 end 상태로 변경
}
}
3. Crawling API
- puppeteer, cheerio 모듈 사용
- sns_type, 검색어에 따른 url 생성
- 검색어는 배열로 받아와 map함수 이용하여 다시 url 배열로 생성
- 검색어는 encoding을 해야만 검색성공을 함
const urlResult = (sns_type) => {
const paramArr = searchParam.split(',');
const url = paramArr.map((param) => {
const encodedParam = encodeURI(param);
if (sns_type === 'BLOG') {
return {
uri: `https://search.naver.com/search.naver?where=view&sm=tab_jum&query=${encodedParam}`,
keyword: param,
};
} else {
return {
uri: `https://www.instagram.com/explore/tags/${encodedParam}/`,
keyword: param,
};
}
});
- instagram, naver crwaling
- html이 다른 두 사이트는 검색 방법이 다르다 (노출되는 url확인 가능)
const naverCrawling = async ($) => {
const lists = $('li.bx._svp_item');
let result = [];
await lists.each((i, list) => {
// const influencer = $(list).find('a.name').text().trim();
const blogUrl = $(list)
.find('div.total_wrap.api_ani_send > div > a')
.attr('href');
result.push({ i, blogUrl });
});
return result;
};
const instagramCrawling = async ($) => {
const lists = $('div._aabd._aa8k._aanf');
let result = [];
await lists.each((i, list) => {
const url = $(list).find('a').attr('href');
const blogUrl = `https://www.instagram.com${url}`;
result.push({ i, blogUrl });
});
return result;
};
- 노출되는 url 확인 후 고용한 인플루언서의 글 확인 및 캡쳐 작업 실행
- 고용한 인플루언서의 글 확인 후 유뮤에 따라 캡쳐
- 캡쳐 후 s3에 저장
- 저장된 s3 path 및 url DB에 저장
const postingUrl= async (sliceResult) => {
const urlArr = posting_url.split(',');
let result = [];
for (j of urlArr) {
if (sliceResult.includes(j)) {
result.push({ rank: urlArr.indexOf(j) + 1, url: j });
}
}
return result;
};
if (postingUrl[0]) {
let filename = `${campaign_idx}_${koreaNow
.toISOString()
.substr(0, 19)}.png`;
let screenshot = await page.screenshot({
fullpage: true,
path: `../backend/uploads/${filename}`,
});
let s3UploadImage = await uploadFile(
screenshot,
filename,
koreaNow.getFullYear(),
campaign_idx
);
await uploadPicture(
job_idx,
i.keyword,
s3UploadImage.key,
filename,
s3UploadImage.Location,
JSON.stringify(postingUrl)
);
await unlinkFile(filename);
}
4. DOCKER
- DOCKER 이용 서버 오픈
- docker file 작성 및 aws 서버에 오픈
느낀점
기업 협업은 앞서 말씀드렸듯이 프로의 세계에 들어온 느낌이었습니다. 누구도 기다려주지 않고 제 스스로 보고하고 진행해야하는 부담감이 더욱 컸습니다. 기능을 구현하는데 있어서는 많이 어렵다는 느낌은 들지 않았습니다. 대신 CTO님과의 소통에서 CS 관련 내용이나, 개발관련 이야기를 할 때 부족함을 많이 느꼈습니다. 처음부터 잘하는 사람이 어딨겠습니까?
모르는 것은 죄가 아니지만 배우려는 자세가 없는 것은 죄라고 생각합니다.
저는 배우려는 자세가 되어있고, CS나 개발관련 대화에 필요한 단어들을 숙지하여 더 좋은 회사에 취직하고 싶습니다.
구현 동영상
'코딩 개발' 카테고리의 다른 글
코딩테스트 - 숫자 짝꿍 (0) | 2023.01.17 |
---|---|
HTTP (0) | 2023.01.08 |
Node.js - Crawling(크롤링) (0) | 2022.12.14 |
Node.js - 스케줄러 (0) | 2022.12.13 |
2차 Project - BUGBUG (2) | 2022.12.09 |