| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | |||||
| 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| 10 | 11 | 12 | 13 | 14 | 15 | 16 |
| 17 | 18 | 19 | 20 | 21 | 22 | 23 |
| 24 | 25 | 26 | 27 | 28 | 29 | 30 |
| 31 |
- It
- CSS
- 위키피디아검색창
- kotlin
- 깃 꼬였을 때
- 파이썬 코테준비
- Python3
- git방식
- 깃 충돌 해결방법
- env사용
- 프론트엔드
- JavaScript
- 앱에 팝업띄우기
- 코테준비
- 코틀린
- 파이썬코테함수정리
- 앱개발
- 깃 충돌시
- HTML
- 깃협업
- 환경변수사용
- 앱개발기능추가
- dev
- 앱사용자행동추적
- frontend
- 앱사용자추적
- Git협업
- 파이썬 코테 함수
- 백엔드
- 개발자
- Today
- Total
zooooss
[Reactive Native] 캐시(Cache) 설계 - 크롤링 주기 설정(속도 최적화) 본문
사용이유
1. 개발 중인 어플에서 사용자가 요소를 선택할 때마다 매번 크롤링 => 로딩시간 지연
2. 사용자가 증가한다면 크롤링 횟수가 많아져 해당 웹사이트에서 내 서버를 차단할 확률이 높아짐.

사진과 같이 상세페이지에 접속할 경우 크롤링해야하는 요소가 많아 로딩시간이 지연되었습니다.
이를 매 접속마다 크롤링 하는 것은 비효율적이며, 유저들이 머무르지 않을 것이라 생각하였습니다.
따라서, 일주일을 주기로 두고 한 번 크롤링을 진행한 정보들을 어딘가에 담아두고 계속 재사용(빠르게) & 7일째에 재크롤링하여 정보 업데이트(이건 7일 이후 첫 사용자에 의한게 아니라 정해진 시간에 자동 업데이트 되도록)
를 구현하기 위해 캐시를 설계하게 되었다!
Node File System 모듈 사용
1. import문 생성

서버코드에 필요한 모듈들을 import 해주었고, 이에 대한 설명은 아래와 같음!
- fs/promises: Node.js의 파일 시스템을 Promise 기반으로 사용 (async/await 가능)
- path: 운영체제에 관계없이 경로를 안전하게 다룸 (/ vs \) -> 경로 처리 유틸리티!
- Buffer: URL을 안전한 파일명으로 변환할 때 사용
2. 캐시 디렉토리 경로 설정 및 디렉토리 생성 (+주기설정)

왼쪽의 폴더 및 파일들과 함께 코드를 살펴보면!
캐시 디렉토리 경로를 정해주고, 유효기간은 7일로 설정하여 캐시 디렉토리 생성을 해준다.
- process.cwd(): 현재 실행 중인 디렉토리 경로
- path.join(): 경로를 OS에 맞게 결합 (Windows: \, Mac/Linux: /)
fs.access, fs.mkdir 등 파일시스템을 사용한 문법들은 이미 import문에 정의되어있는 것들을 사용한 것이니 이는 filesystem 사용법 참조하면 됨 ! (-내가 사용한 건 아래 정리!)
fs.access(경로)
- 역할: 파일/폴더 존재 여부 확인
- 동작: 존재하면 성공, 없으면 에러 발생
- 예외 처리: try-catch로 에러를 잡아서 폴더 생성 로직으로 분기
fs.mkdir(경로, { recursive: true })
- recursive: true: 상위 폴더까지 자동 생성 (Linux의 mkdir -p와 동일)
- 예시: crawlCache/details 생성 시 crawlCache도 자동 생성
3. 캐시 읽기 및 저장(나라별 페이지, 책별 상세페이지) + 파일명 변환
async function readCache(country) {
try {
const cacheFile = CACHE_FILES[country]; // 'kr' → krbooks.json
const data = await fs.readFile(cacheFile, 'utf-8'); // 파일 읽기
const cache = JSON.parse(data); // JSON 파싱
// 유효기간 검사
const now = Date.now();
if (now - cache.timestamp < CACHE_DURATION) {
console.log(`✅ ${country.toUpperCase()} 캐시 사용`);
return cache.data; // 캐시 데이터 반환
} else {
console.log(`⏰ ${country.toUpperCase()} 캐시 만료됨`);
return null; // 만료됨 → 크롤링 필요
}
} catch (err) {
console.log(`📝 ${country.toUpperCase()} 캐시 없음`);
return null; // 캐시 파일 없음 → 크롤링 필요
}
}
- 파일 읽기 시도 → 실패하면 catch로 이동 (파일 없음)
- JSON 파싱 → { timestamp: 1234567890, data: [...] } 형태
- 시간 비교 → 현재시간 - 저장시간 < 7일 확인
- 결과 반환
- 유효함 → 캐시 데이터 반환
- 만료/없음 → null 반환
async function writeCache(country, data) {
try {
await ensureCacheDir(); // 폴더 존재 확인/생성
const cacheFile = CACHE_FILES[country];
const cache = {
timestamp: Date.now(), // 현재 시간 저장
data: data, // 크롤링 결과
};
await fs.writeFile(
cacheFile,
JSON.stringify(cache, null, 2), // 보기 좋게 포맷팅
'utf-8'
);
console.log(`💾 ${country.toUpperCase()} 캐시 저장 완료`);
} catch (err) {
console.error(`❌ 캐시 저장 실패:`, err);
}
}
+ 그리고 URL에는 파일명으로 사용 불가능한 문자들이 많으니 이 부분은 따로 함수로 정의
function urlToFileName(url) {
return Buffer.from(url)
.toString('base64')
.replace(/[/+=]/g, '_');
}
4. 실제 API 엔드포인트 적용하는 부분
이제 정의해둔 캐시 읽기/쓰기 함수를 사용하는 kr, krdetail, us, usdetail 등의 코드를 살펴보겠습니다!
app.get('/kr-books', async (req, res) => {
try {
// 1. 캐시 확인
const cachedData = await readCache('kr');
if (cachedData) {
return res.json(cachedData); // 즉시 반환 (0.1초)
}
// 2. 캐시 없음 → 크롤링 실행
console.log('🔄 한국 베스트셀러 크롤링 시작...');
크롤링 시작 아래는 기존 크롤링 로직 코드와 같다.
이렇게 성공적으로 캐시설계구현이 되었습니다!
하지만, 현재 로직에 여전히 문제점이 있는데
사용자 A 접근 -> 크롤링 -> 캐시에 담음
사용자 B 접근(7일 이내 아무때나) -> 바로 보여줌
이렇기 때문에 아직 캐시에 담기지않은 데이터에 접근한 첫 사용자는 여전히 로딩시간에 맞딱들이게 됨!
===> 사용자 접속 전 모든 것 다 미리 크롤링 후 캐시에 담는 방식으로 고쳐야 함! -> 이후 진행 예정
이 시스템으로 실시간성이 중요하지 않은 데이터를 효율적으로 관리하며,
서버 부하와 크롤링 대상 사이트의 부담을 동시에 줄일 수 있었습니다!
더하여, 다른 팀원분이 사용하신 방법으로는 "Backend/scrappers에 배치크롤러들 생성"이 있다고 하여 이후에 코드 분석 후 차이점을 비교해 볼 예정입니다.
++추가 개선점 : 만료 전 백그라운드로 미리 갱신해놓는 방식
'STUDY > App' 카테고리의 다른 글
| [React Native] Amplitude로 앱 사용자 이벤트(행동) 추적하기 (0) | 2026.01.19 |
|---|---|
| [React Native] 웹뷰(WebView)로 위키피디아 창 띄워서 검색기능 제공하기 (0) | 2025.12.03 |
| [React Native] 북마크 기능 개발(AsyncStorage) (4) | 2025.11.13 |
| [React Native] 안드로이드 앱과 구글 시트 연동(vscode로 개발) (0) | 2025.11.03 |
| [React Native] apk 개발 환경 구축하기(vscode에서) (0) | 2025.11.03 |