[카테고리:] 미분류

  • 나만의 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 요약, 키워드 추출, 그리고 정치적 프레이밍 분석까지 도전할 예정입니다. 앞으로도 기술적 여정과 그 결과들을 공유드릴게요.

  • 젬링 리제니어

    Ice Strike

    • Martial Tempo
    • Concentrated Effect
    • Primal Armament
    • Inspiration

    Herald of Ice

    • Magnified Effect
    • Elemental Focus
    • Cold Mastery

    Tempest Bell

    • Rageforged
    • Leverage
    • Heavy Swing
    https://mobalytics.gg/poe-2/builds/sanctum-attribute-stacker?widgets-state=eyJmN2Q4MjEwMi03ZTc3LTRhNDQtYWQyNC0zM2I2N2U4YWU3YmYiOnsiZmlsdGVycyI6eyJhY3RpdmVWYXJpYW50SWQiOiIwYTE5ZTVlMC1jMjY3LTQ3MjEtOTM4MS1hMmE0ODk4N2UwOGYifSwidHlwZW5hbWUiOiJOZ2ZEb2N1bWVudENtV2lkZ2V0Q29udGVudFZhcmlhbnRzVjEifX0
  • Bootstrap 시작 방법

    Bootstrap 다운로드: Compiled vs. Source Code

    1. Compiled (컴파일된) 버전:
      • 내용: 미리 컴파일된 CSS와 JS 파일들로 구성되어 있으며, 바로 프로젝트에 포함시켜 사용할 수 있음.
      • 사용 목적: 빠르게 시작하고자 할 때, 별도의 수정 없이 Bootstrap을 바로 사용하고자 할 때.
      • 다운로드 구성bootstrap.min.cssbootstrap.min.js 등의 파일이 포함되어 있음.
    2. Source (소스) 코드:
      • 내용: SASS 파일, JS 소스 파일 등이 포함되어 있으며, 커스터마이징이나 직접 컴파일을 하고자 할 때 사용.
      • 사용 목적: Bootstrap의 디자인이나 동작을 세부적으로 수정하고자 할 때.
      • 다운로드 구성: SASS 파일(.scss), JS 소스 파일 등이 포함되어 있음.

    Bootstrap 사용 방법

    1. Compiled 버전 사용하기

    1. Bootstrap 다운로드 페이지에서 컴파일된 버전을 다운로드합니다.
    2. 다운로드한 파일을 프로젝트 폴더에 복사합니다.
    3. HTML 파일에서 다음과 같이 CSS와 JS 파일을 포함시킵니다:
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Bootstrap Example</title>
      <link rel="stylesheet" href="path/to/bootstrap.min.css">
    </head>
    <body>
      <h1>Hello, Bootstrap!</h1>
      <script src="path/to/bootstrap.min.js"></script>
    </body>
    </html>
    

    장점:

    • 오프라인 사용 가능: 인터넷 연결이 없어도 Bootstrap을 사용할 수 있습니다.
    • 버전 관리 용이: 특정 버전의 Bootstrap 파일을 다운로드하여 사용하면, 프로젝트 내에서 동일한 버전을 유지할 수 있습니다.
    • 커스터마이징 용이: 직접 다운로드한 파일을 수정하거나 커스터마이징 할 수 있습니다. 예를 들어, 필요 없는 부분을 제거하거나, 직접 컴파일하여 최적화된 파일을 생성할 수 있습니다.
    • 로딩 시간 단축: 서버에 저장된 파일을 로드하기 때문에, 외부 서버로부터 파일을 불러오는 시간과 비교하여 로딩 속도가 빠를 수 있습니다.

    단점:

    • 초기 설정 번거로움: 파일을 다운로드하고, 프로젝트에 포함시키는 과정이 다소 번거로울 수 있습니다.
    • 파일 크기 증가: 프로젝트에 직접 파일을 포함시키면, 프로젝트의 크기가 커질 수 있습니다.

    2. CDN 사용하기

    CDN(Content Delivery Network)을 사용하면 파일을 다운로드하지 않고도 웹에서 바로 Bootstrap을 사용할 수 있습니다. CDN 링크를 HTML 파일에 포함시키기만 하면 됩니다.

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Bootstrap Example</title>
      <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
    </head>
    <body>
      <h1>Hello, Bootstrap!</h1>
      <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
      <script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.5.4/dist/umd/popper.min.js"></script>
      <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
    </body>
    </html>
    

    장점:

    • 간편함: HTML 파일에 몇 줄의 링크만 추가하면 되므로 설정이 매우 간편합니다.
    • 최신 버전 사용 가능: 항상 최신 버전의 Bootstrap을 사용할 수 있습니다.
    • 캐시 활용: CDN을 사용하면, 브라우저가 이미 캐시된 파일을 사용할 수 있어 로딩 속도가 빨라질 수 있습니다. 특히, 많은 사이트들이 동일한 CDN을 사용하기 때문에 사용자 브라우저에 캐시되어 있을 가능성이 높습니다.
    • 서버 부하 감소: 파일이 외부 서버(CDN)에 호스팅되기 때문에, 사용자의 서버 부하를 줄일 수 있습니다.

    단점:

    • 인터넷 의존성: 인터넷 연결이 없으면 Bootstrap을 사용할 수 없습니다.
    • 버전 관리 어려움: CDN에서 제공하는 최신 버전을 사용할 경우, 특정 버전을 유지하는 것이 어려울 수 있습니다.
    • 외부 서버 의존성: 외부 서버(CDN)에서 파일을 로드해야 하므로, 외부 서버의 상태에 따라 로딩 시간이 영향을 받을 수 있습니다. 예를 들어, CDN 서버가 느리거나 다운되면 영향을 받을 수 있습니다.
  • mysql 설치

    brew install mysql

    mysql 설치 후 secure installation 실행

  • usb

    http://www.wch-ic.com/downloads/CH341SER_EXE.html

  • Walking Disaster

    I haven’t been home for a while
    I’m sure everything’s the same
    Mom and Dad both in denial
    An only child to take the blame

    Sorry, Mom, but I don’t miss you
    Father’s no name you deserve
    I’m just a kid with no ambitions
    Wouldn’t come home for the world

    Never know what I’ve become
    The king of all that’s said and done
    The forgotten son

    This city’s buried in defeat
    I walk along these no name streets
    Wave goodbye to all
    As I fall…

    At the dead end I begin
    To burn the bridge of innocence
    Satisfaction guaranteed
    A pill-away catastrophe

    On a mission nowhere bound
    Inhibitions underground
    A shallow grave I
    Have dug all by myself

    And now I’ve been gone for so long
    I can’t remember who was wrong
    All innocence is long gone
    I pledge allegiance to a world of disbelief
    Where I belong

    A walking disaster
    The son of all bastards
    You regret you made me
    It’s too late to save me
    (You regret you made me
    It’s too late to save me)

    As far as I can tell
    It’s just voices in my head
    Am I talking to myself?
    ‘Cause I don’t know what I just said

    Far is where I fell
    Maybe I’m better off dead
    Am I at the end of nowhere
    Is this as good as it gets?

    And now I’ve been gone for so long
    I can’t remember who was wrong
    All innocence is long gone
    I pledge allegiance to a world of disbelief
    Where I belong

    A walking disaster
    The son of all bastards
    You regret you made me
    It’s too late to save me
    (You regret you made me
    It’s too late to save me)

    And now I’ve been gone for so long
    I can’t remember who was wrong
    All innocence is long gone
    I pledge allegiance to a world of disbelief
    Where I belong

    A walking disaster
    The son of all bastards
    You regret you made me
    It’s too late to save me
    (You regret you made me
    It’s too late to save me)

    I will be home in a while
    You don’t have to say a word
    I can’t wait to see you smile
    Wouldn’t miss it for the world

  • 안녕하세요!

    워드프레스에 오신 것을 환영합니다. 이것은 첫 글입니다. 바로 편집하거나 삭제한 다음 쓰기 시작하세요!