티스토리 뷰

 

 

 

레퍼런스 AI웹서비스 제작노트 -1 | 국내 웹 섹션 레퍼런스 사이트 기획과 서버비 0원 구조 만들기

수업 시간에 늘 시키는 일이 있다.비전공자들이 많은 수업을 하다보니 많이 보는게 중요하다는 사실을 가르쳐 주는 일 그래서 섹션별로 레퍼런스를 찾아 보는 연습을 시킨다.예를 들어 앱 다운

uiweb.tistory.com

 

1편에서 구조를 잡고 이젠 캡쳐를 얼마나 정확히 할 수 있나가 핵심인데

사이트 주소 하나를 넣으면 헤더, 메인 비주얼, 서비스 소개, 푸터…
이렇게 섹션별 이미지로 잘라주는 것.

말은 쉬운데 국내 사이트들이 정말 제각각으로 만들어져 있어서
하나 고치면 하나 터지고, 하나 고치면 또 하나 터지고... 🙃

섹션별로 괴상하게 잘린 이미지들

 

캡처는 Playwright를 썼다.
코드로 크롬을 띄워서 페이지를 열고 스크린샷을 찍어주는 도구다.
화면 크기는 PC 기준 1920×1080으로 고정했다.

from playwright.async_api import async_playwright

async with async_playwright() as p:
    browser = await p.chromium.launch()
    page = await browser.new_page(viewport={"width": 1920, "height": 1080}, locale="ko-KR")
    await page.goto(url, wait_until="domcontentloaded", timeout=60000)
    try:
        await page.wait_for_load_state("networkidle", timeout=10000)
    except Exception:
        pass   # 광고·채팅 때문에 끝까지 안 기다려지는 사이트가 많다
    await page.screenshot(path="full.png", full_page=True)

 

networkidle(네트워크가 조용해질 때까지 기다리기)만 믿으면
광고나 채팅 위젯 때문에 영원히 안 끝나는 사이트가 많다.
그래서 10초만 기다리고 그냥 진행한다.

섹션을 나누는 기준은 HTML 구조로 잡았다.
사람 눈에는 여기까지가 메인 비주얼이 보이지만 컴퓨터는 모르니까.

  • 페이지에서 가로로 꽉 찬 큰 덩어리(화면 폭 45% 이상)를 찾는다. 보통 <section>이나 콘텐츠 영역의 직계 자식들이다.
  • 너무 긴 덩어리(화면 높이 2.5배 이상)는 다시 쪼갠다.
  • 구조로 못 찾는 사이트는 최후의 수단으로 화면 높이 단위로 자른다.

처음엔 폭 기준을 80%로 했다가
가운데 좁게 만든 사이트가 통째로 한 섹션이 돼서 45%로 내렸다.

여기까지는 순조로웠는데... 여기서부터 고생 시작.

1. 흰 화면만 찍힌다

첫 캡처 결과를 열었는데 섹션 절반이 하얀 빈 이미지 😱

범인은 스크롤 애니메이션이었다.
요즘 사이트는 스크롤해서 화면에 들어올 때 글자랑 이미지가 스르륵 나타나게 만든다.
그런데 캡처는 스크롤 없이 한 번에 찍으니 아직 안 나타난(투명한) 상태로 찍힌 거다.

세 가지를 같이 써서 해결했다.

 

① 지금 다 보이는 중이야하고 속이기
스크롤 애니메이션은 대부분 IntersectionObserver로 화면에 들어왔는지를 감지한다.
페이지가 열리기 전에 이걸 바꿔치기해서, 모든 요소가 처음부터 화면 안에 있다고 알려준다.

// 페이지 로드 전에 주입 (page.add_init_script)
window.IntersectionObserver = class {
  constructor(cb) { this.cb = cb; }
  observe(el) { this.cb([{ target: el, isIntersecting: true, intersectionRatio: 1 }], this); }
  unobserve() {} disconnect() {}
};

 

② 숨겨둔 스타일 강제로 풀기
AOS 같은 라이브러리가 걸어둔 투명도·이동 효과를 CSS로 덮어쓴다.

[data-aos], .aos-init, .wow, .fade-up, .reveal {
  opacity: 1 !important; transform: none !important; visibility: visible !important;
}

 

③ 끝까지 한 번 스크롤
찍기 전에 페이지를 천천히 끝까지 내렸다 올린다.
지연 로딩(lazy) 이미지가 이때 불러와진다.

2. 스크롤하면 내용이 바뀌는 섹션

화면에 고정된 채로 스크롤하면 내용이 바뀌는 섹션(sticky)은
전체 화면 한 장으로 찍으면 엉망이 된다.

그래서 섹션마다 그 위치로 스크롤해서 따로 찍고, 길면 이어 붙였다.
고정 섹션은 처음·중간·끝 장면 3개를 찍는다.

3. 스크롤 자체가 안 되는 사이트

fullpage.js처럼 한 화면씩 넘기는 사이트나
body가 아니라 안쪽 박스가 스크롤되는 사이트는
전체 캡처를 해도 첫 화면 높이만 찍힌다.

이런 곳은 찍기 전에 막아둔 걸 풀어준다.

  • overflow: hidden으로 잠긴 박스 → visible로
  • 화면 높이(100vh)에 고정된 박스 → 높이 자동으로
  • position: fixed / absolute로 띄워놓은 앱 전체 영역 → 일반 흐름으로

4. 배민처럼 휠을 굴려야 넘어가는 사이트

배민은 풀어도 풀어도 화면이 한 장이었다.
마우스 휠을 굴려야 다음 장면으로 넘어가는 구조라서다.

그래서 진짜로 휠을 굴리면서 장면이 바뀔 때마다 찍었다.

장면이 바뀌었는지는 처음엔 이미지 지문(phash)으로 비교했는데
배민처럼 단색 배경에 글자만 바뀌는 화면은 지문이 거의 같게 나와서 놓쳤다.
그래서 색 차이를 직접 비교하는 방식으로 바꿨다.

그랬더니 이번엔
배민페이 / 전국특가 / 선물하기처럼 배치는 똑같고 글자만 다른 장면이 줄줄이 찍혔다 ㅋㅋ
레퍼런스로는 한 장이면 충분한데...

그래서 화면을 12×8칸으로 나눠서 칸마다 "배경 말고 뭔가 있는 정도"를 재는 배치 지문을 만들었다.
배경색이랑 배치가 같으면 하나만 남긴다.

배민 중복 장면 -> 정리된 결과

 

5. 헤더가 사라진다

상단에 고정된 헤더는 다른 섹션을 찍을 때마다 위에 같이 찍혀서 숨겨야 한다.
그런데 숨기고 나니... 정작 헤더 섹션 자체가 없어졌다.

그래서 숨기기 전에 헤더만 한 장 따로 찍는다.

여기서 욕심을 더 냈다.
헤더 레퍼런스는 사실 메뉴 펼친 모습이 더 궁금하니까
첫 메뉴에 마우스를 올려서 드롭다운·메가메뉴가 펼쳐진 상태로 찍게 했다.

await page.mouse.move(menu_x, menu_y)   # 첫 메뉴에 마우스 올리기
await page.wait_for_timeout(700)        # 펼쳐지는 애니메이션 기다리기
# 호버로 새로 나타난 요소들의 아래 끝까지 잘라서 캡처

 

첫 메뉴가 안 펼쳐지면 옆 메뉴로 4개까지 시도하고
아무것도 안 펼쳐지는 사이트는 헤더 띠만 찍는다.

아이브릭스 펼친 헤더

 

6. 막힌 사이트

GitHub Actions 서버가 미국에 있다 보니
해외 접속을 막는 사이트, 봇 확인 창을 띄우는 사이트,
새벽 점검 페이지(은행...)가 나왔다.

  • 제목이나 본문에 “Access Denied”, "보안 확인" 같은 말이 있으면 → 차단으로 보고 건너뜀
  • 내용이 거의 없는 페이지 → 실패 처리
  • 3번 연속 실패하면 → 수집 목록에서 자동으로 빠짐
  • 은행 점검을 피하려고 수집 시간은 오전 10시로

한국 서버를 따로 둘까도 고민했는데
몇 곳 때문에 서버비를 내는 건 이 프로젝트랑 안 맞아서 과감히 패스했다.

7. 리뉴얼인지 아닌지

같은 사이트를 다시 찍었을 때 진짜 리뉴얼인지는 이렇게 본다.

  • 섹션 순서·종류·높이(20% 이내)가 비슷한 게 60%가 안 되면 → 리뉴얼
  • 섹션 개수가 3개 이상 달라지면 → 리뉴얼
  • 나머지는 배너 이미지만 바뀐 걸로 보고 → 업로드 안 함, 확인 날짜만 갱신

 

총 정리를 해보면,

흰 화면 IntersectionObserver 바꿔치기 + 숨김 CSS 해제 + 끝까지 스크롤
고정(sticky) 섹션 섹션 위치로 스크롤해서 따로 찍기
스크롤 잠금 overflow·높이 고정 풀기
휠 넘김 사이트 휠 굴리며 장면별 촬영 + 배치 지문으로 중복 제거
헤더 숨기기 전에 따로, 메뉴 펼친 상태로
막힌 사이트 감지해서 건너뛰고, 3번 실패하면 제외

 

이렇게 해서 국내 사이트 대부분은 꽤 잘 잘린다.
완벽하진 않지만 이상하게 잘린 건 관리자 화면에서 숨기면 된다. (이건 4편에서)

다음 편은 어떤 사이트를 찍을지, GDWEB 목록이랑 AI 검수 이야기다.
AI로 AI 사이트 거르는 거 

 

베타버전 링크 - 아직 베타라 분류가 어색한 섹션이 있을 수 있음

도메인변경 
https://ref.jjinmango.kr/

반응형