App development/[project]review_talk

[디버깅]

Phantomer 2025. 7. 29. 16:48

- 크롤링 데이터가 제대로 안먹히는 현상

- 데이터 스키마를 어떻게 해야하는거지

커서가 또 먹통이 됐다

안그래도 느린데 가끔 먹통이된다

클로드 코드로 디버깅한다

데이터 베이스 문제가 생겨서 기존 db 삭제후 재시작

데이터 스키마에서 칼럼이 있는데 실제 데이터는 칼럼이 없다고 문제가 생기는데

' 무슨 말인지 하나도 모르겠다!!!'

좋은 질문이야. 이거 궁금해지는 게 당연해.

“스키마에는 칼럼이 있는데, 왜 실제 데이터에는 칼럼(이름)이 없어?”

이건 데이터가 어디에, 어떻게 저장되어 있느냐에 따라 달라.


💥 핵심 요약

스키마는 구조(이름+타입 등),

데이터는 값(value)만을 담고 있기 때문이야.


🔍 예시로 이해해보자

1. 스키마 정의 (설계도)

CREATE TABLE users (
  id INT,
  name VARCHAR(50),
  email VARCHAR(100)
);

2. 실제 데이터

1,김철수,chulsoo@email.com
2,이영희,younghee@email.com

CSV 같은 걸로 저장된 실제 데이터는

“값만” 들어 있고 칼럼 이름은 저장하지 않음.


📦 왜 칼럼이 없냐면?

✔️ 1.

공간 절약 / 효율

  • 대량 데이터를 저장할 때는 이름 없이 값만 저장하는 게 훨씬 효율적이야.
  • 이름을 계속 저장하면 데이터가 무거워져.

✔️ 2.

스키마는 별도로 관리

  • 데이터베이스 시스템(DBMS)은 이미 스키마 정보를 따로 가지고 있어.
  • 그래서 데이터 자체에 칼럼 이름을 반복해서 저장할 필요가 없어.
  • DB는 “첫 번째 칼럼은 id, 두 번째는 name…” 이런 식으로 매칭함.

🧠 정리

구분**내용**

스키마 테이블의 구조(칼럼 이름, 타입, 제약조건 등)
데이터 스키마에 따라 저장된 실제 값들 (칼럼 이름은 없음)
이유 효율성 때문 + 칼럼 정보는 스키마에 이미 있으니까

필요하면 JSON, Parquet, CSV 같은 포맷별로 칼럼이 있거나 없는 예도 정리해줄게!

학원에서 배운건 그냥 데이터 정제하고 정리하고 그걸로 결론내고 그런거였는데...

실제 데이터를 가져와서 칼럼을 뭐하고 이름은 뭐고 id는 뭐고,,,,,, 머리아파 ,,,,,,,,

클로드 코드에게 물어보자

문제 원인 분석

근본 원인: 데이터베이스 스키마 마이그레이션 문제

  1. 실제로 발생한 문제

    database.py의 CREATE_TABLES_SQL에는 is_crawled 컬럼이 정의되어 있음

    CREATE TABLE IF NOT EXISTS products (
    ...
    is_crawled BOOLEAN DEFAULT FALSE, # ✅ 스키마에 정의됨
    ...
    );

    하지만 기존 데이터베이스 파일에는 이 컬럼이 없었습니다. 이는 다음과 같은 상황에서
    발생할 수 있습니다:

  2. 스키마 변경 후 기존 DB 파일 유지: 코드에서 컬럼을 추가했지만, 기존 데이터베이스
    파일은 구 스키마로 남아있음

  3. CREATE TABLE IF NOT EXISTS의 한계: 테이블이 이미 존재하면 새로운 컬럼을
    추가하지 않음

  4. 실제 사용자 환경에서 발생 가능한 문제들

⏺ Read(app/database.py)
⎿ Read 47 lines (ctrl+r to expand)

⏺ 현재 코드의 문제점:

  1. 테이블 존재만 확인, 컬럼은 확인 안함 (126-141라인)

  2. 컬럼 마이그레이션 로직 없음

  3. 스키마 버전 관리 없음

  4. 실제 사용자가 겪을 수 있는 시나리오들

    🚨 문제 시나리오 1: 앱 업데이트
    사용자 A가 앱을 사용 중 → 개발자가 새 컬럼 추가한 버전 배포 → 사용자가 앱 업데이트
    → 기존 DB 파일은 구 스키마 → "no such column" 에러 발생

    🚨 문제 시나리오 2: 서버 재배포
    서버에 기존 데이터베이스 파일 존재 → 새 코드 배포 → 테이블은 존재하지만 컬럼 누락
    → 크롤링 시도 → "no such column: is_crawled" 에러

    🚨 문제 시나리오 3: 개발 환경별 차이
    개발자 A: 새로 DB 생성 (✅ 정상)
    개발자 B: 기존 DB 파일 사용 (❌ 에러)

    근본적인 해결방안

⏺ Write(app/database_migration.py)

마이그레이션은 또뭔데,,,,

좋아, 이 문제를 진짜 비전공자도 직관적으로 이해할 수 있게 찢어서 설명해볼게.
핵심은 이거야:

🎯 문제 요약 한 줄

“코드는 테이블에 is_crawled 칼럼이 있다고 생각하는데, 실제 DB엔 없다 → 그래서 앱이 터짐.”

📌 무슨 상황이냐면?

✅ 1. 코드 상에서는 테이블에 컬럼이 이렇게 정의돼 있어

CREATE TABLE IF NOT EXISTS products (
...,
is_crawled BOOLEAN DEFAULT FALSE
);

→ 여기 보면 is_crawled 라는 칼럼이 있다고 써있음.

❌ 2. 그런데 실제로 앱이 쓰는 DB 파일엔…

is_crawled 컬럼이 없어!!

왜 없냐?
→ 그 이유는 바로 CREATE TABLE IF NOT EXISTS 때문이야.

이 문장은:

“이 테이블이 없으면 새로 만들고,
이미 있으면 그냥 넘어가”

이 말이거든?

🧨 즉, 이런 일이 벌어짐:
• 예전 버전 앱: products 테이블 생성 (is_crawled 없음)
• 새 버전 앱: is_crawled 추가함 → 근데 기존 DB는 이미 테이블이 있음
• 그러니 새 컬럼이 추가가 안 됨 ❌
• 그런데 코드는 is_crawled이 있다고 믿고 사용함
• 결과 → no such column: is_crawled 에러 💥

🔥 비유로 설명하면
• 스키마 변경은 집 설계도를 바꾼 것
• 근데 기존 집은 안 고친 거야.
• 그래서 2층에 욕실 만들어놨어요~ 라고 했는데
정작 옛날 집에는 2층도, 욕실도 없음 → 사람이 들어가면 부딪힘

🛠️ 해결 방법은?

이건 “마이그레이션(Migration)” 문제야.
“스키마 바뀌면, 기존 DB에도 바뀐 내용을 반영해줘야 한다”는 뜻이지.

🔑 해결법
1. 스키마 버전 관리하기
2. 기존 DB에서 누락된 컬럼이 있는지 체크
3. 없으면 ALTER TABLE로 컬럼 추가

ALTER TABLE products ADD COLUMN is_crawled BOOLEAN DEFAULT FALSE;

4.    이 로직을 database_migration.py 같은 파일로 따로 관리하면 좋음

✋ 사용자 입장에서 발생할 수 있는 문제들

시나리오 설명 결과
앱 업데이트 새 컬럼 생겼는데 기존 DB는 그대로 앱 터짐
서버 재배포 DB 파일은 그대로, 코드만 바뀜 터짐
개발자 B 기존 DB 파일 써서 테스트 코드 에러 발생

✅ 핵심만 정리
• 스키마는 바뀌었는데, 실제 DB는 그대로면 문제 생김
• CREATE TABLE IF NOT EXISTS는 기존 테이블에 컬럼 안 추가함
• 그래서 기존 DB에서는 "is_crawled"이라는 컬럼이 없는 것처럼 행동
• 이걸 해결하려면 → DB 마이그레이션 로직 필요

필요하면 database_migration.py 파일 예제도 내가 짜줄게.
진짜 한 줄 한 줄 같이 만들어볼 수도 있고. 할래?

아~ db 설계도인 스키마는 바꿔놓고 실제 코드가 동작하는건 안바뀐거구나 
그걸 db도 스키마대로 고치는걸 마이그레이션? 

원님이 만들어놓은 상태창들은 어케 한걸까 ,,

또왜 이미지 오류가 ㄱ뜰까,,

└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Could not find a set of Noto fonts to display all missing characters. Please add a font asset for the missing characters. See:
https://flutter.dev/docs/cookbook/design/fonts
❌ 이미지 로딩 실패: https://img.danawa.com/images/mobile/MDNW/mainContent/430/43055.jpg?ver=20250729084017
❌ 오류: HTTP request failed, statusCode: 0,
http://192.168.35.68:8000/api/v1/special-deals/image-proxy?url=https%3A%2F%2Fimg.danawa.com%2Fimages%2Fmobile%2FMDNW%2FmainContent%2F430%2F43055.jp
g%3Fver%3D20250729084017
❌ 이미지 로딩 실패: https://img.danawa.com/images/mobile/MDNW/mainContent/430/43042.jpg?ver=20250728143656
❌ 오류: HTTP request failed, statusCode: 0,
http://192.168.35.68:8000/api/v1/special-deals/image-proxy?url=https%3A%2F%2Fimg.danawa.com%2Fimages%2Fmobile%2FMDNW%2FmainContent%2F430%2F43042.jp
g%3Fver%3D20250728143656
❌ 이미지 로딩 실패: https://img.danawa.com/images/mobile/MDNW/mainContent/430/43008.jpg?ver=20250724143107
❌ 오류: HTTP request failed, statusCode: 0,
http://192.168.35.68:8000/api/v1/special-deals/image-proxy?url=https%3A%2F%2Fimg.danawa.com%2Fimages%2Fmobile%2FMDNW%2FmainContent%2F430%2F43008.jp
g%3Fver%3D20250724143107
❌ 이미지 로딩 실패: https://img.danawa.com/images/mobile/MDNW/mainContent/430/43059.jpg?ver=20250729091500
❌ 오류: HTTP request failed, statusCode: 0,
http://192.168.35.68:8000/api/v1/special-deals/image-proxy?url=https%3A%2F%2Fimg.danawa.com%2Fimages%2Fmobile%2FMDNW%2FmainContent%2F430%2F43059.jp
g%3Fver%3D20250729091500
❌ 이미지 로딩 실패: https://img.danawa.com/images/mobile/MDNW/mainContent/430/43065.jpg?ver=20250729101431
❌ 오류: HTTP request failed, statusCode: 0,
http://192.168.35.68:8000/api/v1/special-deals/image-proxy?url=https%3A%2F%2Fimg.danawa.com%2Fimages%2Fmobile%2FMDNW%2FmainContent%2F430%2F43065.jp
g%3Fver%3D20250729101431
❌ 이미지 로딩 실패: https://img.danawa.com/images/mobile/MDNW/mainContent/430/43048.jpg?ver=20250728164635
❌ 오류: HTTP request failed, statusCode: 0,
http://192.168.35.68:8000/api/v1/special-deals/image-proxy?url=https%3A%2F%2Fimg.danawa.com%2Fimages%2Fmobile%2FMDNW%2FmainContent%2F430%2F43048.jp
g%3Fver%3D20250728164635

gpt야 문제가 뭐니

좋아, 핵심 포인트는 이거네:

🔍 외부 서버에서 HTML이나 링크는 잘 가져와지는데, 이미지 로딩만 실패한다

이 경우, 이미지만 차단되는 상황이야. 즉, 크롤링은 되지만 img.danawa.com 쪽에서 이미지 리소스 요청만 막고 있을 확률이 높아.

✅ 원인 가능성 정리

  1. 이미지 서버 측 User-Agent 필터링
    • 일부 이미지 서버는 일반적인 브라우저 User-Agent가 아닌 요청을 차단해.
    • 예: curl이나 Python, Node 등에서 requests, axios, http 등으로 보낼 경우 차단.

  2. 이미지 서버 측 Referer 체크
    • img.danawa.com은 danawa.com이 아닌 도메인에서의 이미지 호출을 막아놨을 수 있음.
    • 이건 이미지 핫링크 방지 기술이라고 해.
    예: 외부 사이트에서 이미지를 퍼가는 걸 막기 위해.

  3. SSL 인증서 문제
    • 요청하는 서버가 HTTPS 요청 시 SSL handshake 문제를 겪고 있을 수도 있음.
    • 이 경우 statusCode: 0이 나올 수 있어.

✅ 해결 방법

🔧 1. User-Agent & Referer 헤더 추가해서 이미지 요청

백엔드에서 이미지 요청 코드에서 아래처럼 헤더 추가해봐:

import requests

headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36",
"Referer": "https://www.danawa.com"
}

image_url = "https://img.danawa.com/images/mobile/MDNW/mainContent/430/43055.jpg?ver=20250729084017"
res = requests.get(image_url, headers=headers)

with open("image.jpg", "wb") as f:
f.write(res.content)

🧪 이게 성공하면 문제는 확실히 User-Agent 또는 Referer 차단이야.

🔧 2. Proxy 서버에서 이미지가 아니라 URL만 프론트에 전달하게
• 이미지 프록시로 돌아가지 말고, 이미지 URL을 그대로 프론트에서 Image.network()로 쓰게 하는 방법도 있어.
• 단, 이 경우에도 CORS나 이미지 핫링크 방지가 있으면 여전히 안 보일 수도 있어.

🔧 3. 이미지 자체를 다운로드해서 우리 서버에서 제공
• 프록시로 매번 이미지 가져오는 게 아니라, 아예 서버에 저장하고 /media로 제공하는 방식.
• 크롤링 시점에 저장해두면 재요청도 필요 없고 안정성 올라감.

🚨 정리해서 조치 순서 추천
1. ✅ 백엔드에서 User-Agent, Referer 헤더 넣고 이미지 요청 시도
2. ⚠️ 그래도 안 되면 이미지 핫링크 방지로 판단하고:
• → 이미지 다운로드 방식으로 변경하거나,
• → 클라이언트에서 직접 불러오도록 우회.

필요하면 테스트 코드도 바로 만들어줄게.
사용 언어(Python? Node? 등)만 알려줘.

[] 오늘은 이미지 오류까지만 해결하자
[] 오늘의 특가를 하드코딩해서 이제 실시간으로 불러올 필요는 없게만들자
[] 그이후에 llm qwen 붙인거 잘작동하는지 보고 프롬프트 엔지니어링 단계로 다시 고고

'App development > [project]review_talk' 카테고리의 다른 글

GEMINI 에게 코드리뷰를 시켜보았다  (3) 2025.08.14
7.29  (1) 2025.07.29
리뷰톡 프로젝트 굳이 llm을 써야할까?  (1) 2025.07.29