[카테고리:] Python

  • 나만의 Django Web 개발 준비

    이 글은 Django로 본격적인 웹 서비스를 만들기 위해 개발 환경을 셋업하고, 앱 구조, 데이터베이스 설정, 프론트엔드까지 프로젝트 초기 구조를 어떻게 잡아야 할 지에 대해 정리한 것이다.


    개발 개요

    • 백엔드 프레임워크: Django
    • 데이터베이스: NAS에 설치된 Docker 기반 PostgreSQL
    • 프론트엔드 프레임워크: Bootstrap (CDN 이 아닌 → Static 방식)
    • 앱 구조 전략: apps/ 폴더 하위에 앱을 모듈처럼 분리 관리
    • 민감정보 보호: .env를 통한 환경변수 관리

    1. Python 가상환경 및 패키지 설치

    # 가상환경 생성
    python -m venv venv
    
    #가상환경 활성화
    source venv/bin/activate  # (Windows는 venv\Scripts\activate)

    기본적인 의존성 패키지를 설치한다.

    • django: 웹 프레임워크
    • psycopg: PostgreSQL용 Python 드라이버
    • python-dotenv: .env 파일로 환경변수 관리
    pip install django "psycopg[binary]" python-dotenv

    2. 프로젝트 및 앱 구조 설계

    프로젝트 생성

    .을 입력해서 위치를 잘 구성하는것이 중요하다. 코드를 이렇게 작성하면 settings.py, urls.py 등 프로젝트 전체에서 사용하게 될 부분이 config라는 직관적인 이름으로 관리 될 수 있기 때문에 구조를 이렇게 하기로 했다.

    django-admin startproject config . # '.'을 입력한다는 점 주의

    manage.py가 위치한 루트에 config/ 폴더가 생성됨.

    앱 구조 전략

    웹페이지를 만들다 보면 이런 저런 앱들이 많아 질 수 있다. 폴더 구조 상 이런 저런 이름의 폴더가 많이 만들어지면 헷갈릴 수 있으므로 apps/ 라는 폴더 안에 모든 앱을 만들기로 했다.

    • 예: apps/blog, apps/wiki, apps/home

    다만, 이렇게 하면 큰 단점이 하나 생기는데 앱을 만들 때마다 각 앱의 apps.py 내부에 name field 부분을 폴더 구조에 맞게 변형 해줘야 하고, config/settings.py에 앱을 등록 할 때도 폴더 경로가 반영되게 해야 된다는 점이다. 다소 불편 할 수는 있겠지만 이렇게 해 두면 나중에 코드를 볼 때 이 앱이 어느 폴더에 있는지 직관적으로 알아 보기 쉬울 것 같다는 판단이다.

    혹시 나중에 테스트용 개발중인 앱을 만든다면 dev/ 폴더를 만들어서 그 안에서 사용하다가 어느정도 개발이 완료되면 apps/ 폴더로 옮길 수도 있고, 직관적인 관리가 되지 않을까 하는 생각이다.

    아무튼, 이렇게 폴더 구조를 이용해서 앱을 만들려고하면 다소 귀찮아지는 건 사실이기 때문에 별도의 스크립트를 만들어서 사용하기로 했다.

    #!/bin/bash
    
    APP_NAME=$1
    
    APP_PATH="apps/$APP_NAME"
    
    mkdir -p "$APP_PATH"
    
    django-admin startapp "$APP_NAME" "$APP_PATH"
    
    sed -i '' "s/name = '$APP_NAME'/name = 'apps.$APP_NAME'/g" "$APP_PATH/apps.py"

    이 스크립트의 동작은 간단하다.

    ./makeapp.sh blog라고 입력한다면, apps/blog라는 폴더를 먼저 만든 다음에 blog 앱 생성을 수행한다. 그리고 apps.py폴더 안에 있는 name 필드 값을 apps.를 붙인 이름으로 수정한다.

    앱이 생성되었다면 config/settings.py에 앱을 등록한다.

    INSTALLED_APPS = [
        ...
        'apps.blog',
        'apps.wiki',
        'apps.home',
    ]

    이런식으로 각 앱의 apps.py에서 작성된 name 필드값, 즉 ‘apps.앱이름’ 형태로 지정되어 있어야 한다.


    3. PostgreSQL 연결 설정 (NAS 사용)

    PostgreSQL을 NAS에 Docker로 이미 설치 해두었고 유저와 DB도 생성해 놓은 것을 사용할 예정

    .env 파일 설정

    DB_NAME=mydb
    DB_USER=myuser
    DB_PASSWORD=secret
    DB_HOST=192.168.0.100
    DB_PORT=5432

    settings.py 수정

    from dotenv import load_dotenv
    
    load_dotenv()
    
    DATABASES = {
    
        'default': {
    
            'ENGINE': 'django.db.backends.postgresql',
    
            'NAME': os.getenv('DB_NAME'),
    
            'USER': os.getenv('DB_USER'),
    
            'PASSWORD': os.getenv('DB_PASSWORD'),
    
            'HOST': os.getenv('DB_HOST'),
    
            'PORT': os.getenv('DB_PORT'),
    
        }
    
    }

    4. Bootstrap을 Static 방식으로 설정

    static 디렉토리 구성

    전역적으로 사용할 수 있도록 다음과 같은 구조로 배치:

    project_root/
    └── static/
        └── bootstrap/
            ├── css/
            │   └── bootstrap.min.css
            └── js/
                └── bootstrap.bundle.min.js

    settings.py에 static 설정

    STATIC_URL = 'static/'
    STATICFILES_DIRS = [
        BASE_DIR / 'static',
    ]

    템플릿에서 사용 예시

    {% load static %}
    
    <link rel="stylesheet" href="{% static 'bootstrap/css/bootstrap.min.css' %}">
    
    <script src="{% static 'bootstrap/js/bootstrap.bundle.min.js' %}"></script>

    5. 템플릿 구조 설계 (base.html 포함)

    apps/home/templates/home/base.html 에 base.html을 위치시키고, 다음처럼 구조화함:

    <!DOCTYPE html>
    
    <html lang="ko">
    
    <head>
    
        <meta charset="UTF-8">
    
        <title>{% block title %}My Site{% endblock %}</title>
    
        {% load static %}
    
        <link rel="stylesheet" href="{% static 'bootstrap/css/bootstrap.min.css' %}">
    
    </head>
    
    <body>
    
        {% block content %}
    
        {% endblock %}
    
    </body>
    
    </html>

    다른 앱에서는 이렇게 상속:

    {% extends "home/base.html" %}

    → 각 앱의 templates/앱이름/xxx.html 구조를 유지하면 템플릿 네임스페이스가 명확하고 유지보수가 쉬움

  • 방송사 저녁뉴스 기사 자동 수집기 구축기

    목적과 배경

    뉴스는 사회를 읽는 창입니다. 특히 저녁 시간대에 방송되는 주요 종합뉴스 프로그램은 각 방송사마다 다루는 이슈와 시각이 뚜렷하게 드러나는 대표적인 콘텐츠입니다.

    목표: KBS, MBC, SBS, JTBC, TV조선, 채널A 6개 방송사의 저녁 메인뉴스 프로그램에서 다룬 뉴스 제목과 기사 링크를 자동으로 수집하고, 이를 PostgreSQL에 저장한 뒤 정치 이슈 및 주제별 편향성을 분석하는 시스템을 만드는 것입니다.

    이 작업은 단순한 크롤링이 아닌, 프론트엔드의 다양한 렌더링 방식, 비동기 콘텐츠 로딩, 자바스크립트로 조작되는 UI 등을 고려해야 했던 도전적인 여정이었습니다.

    🛠️ 수행한 작업 요약

    • Selenium + BeautifulSoup 기반 크롤러 구현
    • 6개 방송사별 HTML 구조 및 렌더링 방식 분석
    • 날짜별 기사 목록 수집
    • 중복 저장 방지 및 PostgreSQL 연동
    • WebDriverWait을 도입하여 불안정한 수집 이슈 개선

    🖥️ 방송사별 파싱 로직 및 난이도

    방송사주요 프로그램로딩 방식구현 난이도 요약난이도 (1~5)
    MBC뉴스데스크.js 기반 정적 HTML.js 파일에서 날짜별 URL 추출 필요⭐⭐
    KBS뉴스9JS 렌더링, 동적 anchor 생성WebDriverWait 필수⭐⭐⭐⭐
    SBS8뉴스정적 HTML메타태그에서 정보 추출 필요⭐⭐
    JTBC뉴스룸SPA 구조, 더보기 버튼 반복동적 로딩 반복 처리⭐⭐⭐⭐
    TV조선뉴스9/뉴스7공식 API 제공catid (평일/주말) 주의
    채널A뉴스AJS 달력 조작 기반달력 JS 객체 수동 조작 필요⭐⭐⭐⭐

    ⚠️ 구현 시 주의사항 요약

    • 페이지 로딩 대기: time.sleep() 대신 WebDriverWait 사용 권장
    • 중복 기사 저장 방지: URL 기준 ON CONFLICT DO NOTHING 처리
    • 달력 JS 제어: 채널A의 경우 내부 JS 객체(now) 수정 및 JS 함수 호출 필요
    • 공식 API 활용: TV조선처럼 API가 제공되면 최우선 활용

    🔄 현재 시스템 구조 요약

    • 방송사별로 기사 목록을 가져오는 get_articles(broadcaster, date) 통합 함수 구현
    • 기사 제목, URL, 날짜, 순서, 방송사 정보를 포함한 DataFrame 생성
    • PostgreSQL 테이블 articles에 중복 없이 삽입
    • .env 파일로 DB 접속정보 보호
    • tqdm을 통한 수집 진행 상태 시각화

    📅 앞으로의 마일스톤

    1. [✔ 완료] 방송사별 기사 제목/링크 수집
    2. [🛠 진행 중] 기사 본문, 기자 이름 수집 기능 추가
    3. [🔁 예정] Ollama 기반 기사 요약/키워드 자동 추출
    4. [📊 예정] 방송사별 키워드 통계 분석 및 시각화
    5. [📆 장기 목표] 뉴스 편향성 분석 및 월별 리포트 자동화

    💬 마무리하며

    이번 프로젝트는 단순한 웹 크롤링을 넘어, 방송사마다 상이한 웹페이지 구조자바스크립트 기반 렌더링, 동적 콘텐츠 제어를 직접 제어하면서 수집 시스템을 구축해본 의미 있는 경험이었습니다.

    다음 단계에서는 이 데이터를 기반으로 한 LLM 요약, 키워드 추출, 그리고 정치적 프레이밍 분석까지 도전할 예정입니다. 앞으로도 기술적 여정과 그 결과들을 공유드릴게요.

  • 파이썬 리스트, 배열, ndarray 비교

    주요 차이점 비교

    특징리스트 (list)배열 (array.array)ndarray (numpy.ndarray)
    데이터 타입혼합 가능동일한 타입만 저장동일한 타입만 저장
    차원1차원, 다차원은 중첩 구조로 표현1차원다차원 지원
    메모리 효율성상대적으로 비효율적효율적매우 효율적
    연산 속도느림빠름매우 빠름
    고급 연산미지원미지원지원 (벡터화, 선형대수, 통계 등)
    용도일반적인 데이터 저장 및 조작단순 숫자 데이터수학 연산, 대규모 데이터 분석
  • BeautifulSoup HTML 파싱 코드

    from urllib.request import urlopen
    from urllib.error import HTTPError
    from bs4 import BeautifulSoup
    
    def getBS(url):
        try:
            html = urlopen(url)
    
        except HTTPError as e:  #페이지를 읽을 수 없을 때 예외 처리
            print(e)
            return None
        
        try:
            bsObj = BeautifulSoup(html.read(),'html.parser')
    
        except AttributeError as e: #태그를 찾을 수 없을 때 예외 처리
            print(e)
            return None
        
        return bsObj

    기본 함수

    names = bsObj.find_all(name="span",attrs={"class":"green"})
    for name in names:
        print(name)

    span class가 green인 항목들을 모두 가져오기

  • 윈도우에서 파이썬 가상환경 만들기

    1. 원하는 버전의 파이썬 다운로드
    2. venv를 이용해서 가상환경 생성
    3. 가상환경 활성화/비활성화

    파이썬 다운로드

    Python Releases for Windows | Python.org에 접속해서 원하는 버전의 파이썬을 다운받아 설치한다. PATH 환경변수에 추가하는 것은.. 글쎄 굳이 필요가 없을 듯 하다. 어짜피 가상환경을 생성해서 거기서만 쓸 것이기 때문에.

    venv를 이용해서 가상환경 생성

    별다르게 설정을 하지 않았다면 파이썬이 설치되는 경로는 C:\Users\사용자명\AppData\Local\Programs\Python 이다.

    터미널을 열어서 다음과 같이 입력한다.

    C:\Users\사용자명\AppData\Local\Programs\Python\Python버전명\python.exe -m venv 원하는가상환경이름

    가상환경 활성화

    터미널에서 다음과 같이 입력한다

    ./가상환경이름/Scripts/Activate

    가상환경 비활성화

    터미널에서 다음과 같이 입력한다

    deactivate
  • Python Pandas

    import pandas as pd
    from sklearn.model_selection import train_test_split
    import pandas as pd
    from sklearn.model_selection import train_test_split
    sub Test(rngSource as range)
    
     dim i as Integer
     for i = 1 to 10
      code
     next i
    
    
    end sub