Python 기반 뉴스 추천 시스템: 개발 환경 및 데이터베이스 기초

본 문서에서는 Python 기반 뉴스 추천 시스템 개발 프로젝트의 주요 기술 개요, 개발 환경 설정 방법, 그리고 데이터베이스 설계의 기본 원칙을 다룹니다.

프로젝트 개요

본 프로젝트는 뉴스 추천 서비스를 개발하는 과정을 통해 다음과 같은 핵심 기술 및 개념을 학습하는 것을 목표로 합니다.

  • 데이터베이스 설계 및 ORM (SQLAlchemy) 활용
  • 분산 환경에서의 고유 ID 생성 (예: 스노우플레이크 알고리즘)
  • Redis를 이용한 데이터 캐싱 및 관리
  • Gitflow 워크플로우를 통한 효율적인 버전 관리
  • JWT (JSON Web Token) 기반 인증 시스템 구현
  • 객체 스토리지 (예: Qiniu Cloud Storage) 활용
  • 다중 계층 캐싱 전략 및 캐시 문제 해결 방안
  • RPC (Remote Procedure Call) 통신 메커니즘 (예: gRPC)
  • Elasticsearch를 이용한 전문 검색 시스템 구축
  • Socket.IO를 활용한 실시간 통신
  • APScheduler를 이용한 정기 작업 스케줄링
  • Supervisor를 이용한 프로세스 관리
  • 단위 테스트의 중요성 및 작성 방법

학습 목표

  • 뉴스 추천 서비스 사례를 통해 특정 비즈니스 로직 구현보다는 다양한 기술 스택 및 솔루션 이해에 중점.
  • 발생 가능한 기술적 문제에 대한 효과적인 해결 방안 습득.
  • 이전에 학습한 개발 지식의 심화 이해 및 강화.

제품 구성

이 프로젝트는 크게 세 가지 유형의 클라이언트로 구성됩니다.

  • 사용자 클라이언트: 개인화된 뉴스 콘텐츠를 제공받는 최종 사용자용 플랫폼으로, 모바일 웹, iOS 및 Android 앱으로 구성됩니다. 독서, 팔로우, 댓글, 지능형 챗봇(대화 로봇) 등의 기능을 포함합니다.
  • 미디어 제작자 클라이언트: 자가 미디어 작성자가 기사를 편집, 발행하고 운영 데이터를 확인할 수 있는 플랫폼입니다.
  • MIS 관리자 백엔드: 시스템 운영 관리를 위한 관리자 페이지로, 사용자 관리, 기사 검토 및 관리, 댓글 관리 등의 기능을 제공합니다.

개발 환경 설정: 가상 머신 활용

프로젝트 개발 환경은 가상 머신을 통해 구축됩니다. 실제 기업 서버 환경을 시뮬레이션하기 위해 GNOME 없는 텍스트 기반의 CentOS 7.2 환경을 사용합니다.

  • 가상 머신 설정:
    • 시작 전 NAT 모드로 네트워크 설정.
    • 기본 메모리 4GB, 호스트 메모리가 부족할 경우 2GB로 조정 가능.
  • SSH 접속:
    • Windows 환경에서는 Termius, Xshell과 같은 SSH 클라이언트를 사용하여 접속.
    • 접속 명령어: ssh python@자신의_IP주소
    • 시스템 사용자: root (비밀번호: chuanzhi), python (비밀번호: chuanzhi)
    • MySQL 사용자: root (비밀번호: mysql)
  • 주요 서비스 포트:
    • MySQL (MariaDB): 마스터 (3306), 슬레이브 (8306)
    • Redis 클러스터: 7000-7005
    • Redis 마스터/슬레이브: 6380, 6381
    • Redis Sentinel: 26380, 26381, 26382
    • Elasticsearch 5: 9200
  • Python 가상 환경:
    • workon toutiao 명령어를 사용하여 가상 환경 활성화.
  • 기본 명령:
    • 가상 머신 종료: sudo shutdown now
    • 가상 머신 재시작: reboot

PyCharm 원격 개발 환경 설정

로컬 Windows 환경의 PyCharm에서 코드를 작성하고, 원격 서버의 Python 인터프리터를 사용하여 코드를 디버깅하고 실행할 수 있도록 설정합니다.

  1. PyCharm에서 프로젝트를 열고, Tools 메뉴에서 Deployment > Configuration...을 선택합니다.
  2. 좌측 상단의 + 버튼을 눌러 새로운 서버를 추가하고, SFTP 타입을 선택합니다.
  3. 서버 이름을 설정하고 (예: Toutiao-VM), OK를 클릭합니다.
  4. Connection 탭에서 서버 정보를 입력합니다:
    • Host: 가상 머신의 IP 주소
    • Port: 22 (기본 SSH 포트)
    • Username: python
    • Password: chuanzhi
  5. Test Connection 버튼을 클릭하여 서버 연결을 확인합니다.
  6. Mappings 탭으로 이동하여 로컬 경로와 배포 경로를 설정합니다.
    • Local path: 로컬 프로젝트의 최상위 경로
    • Deployment path: 원격 서버의 프로젝트 경로 (예: /home/python/toutiao-backend)
  7. Settings (Preferences) > Project: [프로젝트명] > Python Interpreter로 이동합니다.
  8. 우측 상단의 톱니바퀴 아이콘을 클릭하고 Add...를 선택합니다.
  9. SSH Interpreter를 선택하고, Existing configuration을 사용하여 방금 설정한 배포 서버를 선택하거나, 새로운 SSH 연결 정보를 입력합니다.
  10. Interpreter: 필드에 원격 가상 환경 내의 Python 인터프리터 경로를 지정합니다 (예: /home/python/.virtualenvs/toutiao/bin/python).
  11. Path mappings 섹션에서 로컬 프로젝트 경로와 원격 서버의 프로젝트 경로가 올바르게 매핑되었는지 확인합니다.
  12. (선택 사항) Automatic Upload 옵션을 활성화하여 코드를 저장할 때마다 자동으로 원격 서버에 업로드되도록 설정할 수 있습니다.

참고: 초기 설정 후 PyCharm이 원격 환경을 로드하는 데 시간이 다소 소요될 수 있습니다.

제품 및 개발 프로세스

1. 제품 소개

이 프로젝트는 개인화 추천 기술을 기반으로 하는 뉴스 및 정보 제공 서비스입니다. 사용자는 모바일 웹, iOS 및 Android 애플리케이션을 통해 뉴스를 구독하고, 미디어 제작자는 콘텐츠를 게시하며, 관리자는 전체 시스템을 운영하는 구조를 가집니다.

2. 프로토타입 및 UI 설계

  • 제품 프로토타입: 제품 관리자가 제작하며, 제품의 기능적 구성과 사용자 흐름을 정의합니다. (예: Axure RP를 통해 제작된 index.html 파일로 기능 확인)
  • UI 효과 다이어그램: UI/UX 디자이너가 제작하며, 제품의 최종 시각적 디자인과 사용자 경험을 표현합니다.

3. 기술 아키텍처

본 프로젝트는 프론트엔드-백엔드 분리(SPA: Single Page Application) 아키텍처를 채택하여 개발됩니다.

4. 개발 팀 및 플랫폼

  • 최소 개발 팀 구성:
    • 제품 관리자 1명
    • UI 디자이너 1명
    • 프론트엔드 개발자 2~3명 (Flutter, Vue 등)
    • 백엔드 개발자 2~3명
    • 추천 시스템 개발자 2~3명
    • 챗봇 개발자 1~2명
    • 테스트 엔지니어 1~2명
  • 주요 개발 플랫폼:
    • GitLab: 소스 코드 버전 관리 및 협업을 위해 사용됩니다.
    • YApi: API 문서화 및 관리 도구로 활용됩니다.

데이터베이스 설계

효율적이고 견고한 데이터베이스 시스템은 프로젝트의 핵심 기반입니다. 다음은 데이터베이스 설계 시 고려할 사항들입니다.

1. 데이터베이스 설계 요구사항

뉴스 추천 서비스의 사용자 클라이언트 프로토타입을 기반으로 데이터베이스를 설계합니다. 다음 요소들을 상세하게 정의해야 합니다.

  • 테이블 구조
  • 각 필드의 데이터 타입, NULL 허용 여부, 기본값
  • 색인(Index) 설계
  • 데이터베이스 엔진 선택

2. 주요 고려사항

  • 필드 중복 설계 (공간-시간 트레이드오프): 쿼리 성능 향상을 위해 일부 필드를 중복하여 저장하는 비정규화 전략을 고려할 수 있습니다. 이는 저장 공간을 더 사용하는 대신 쿼리 속도를 높이는 방식입니다.
  • 필드 타입 선택:
    • 정수형 필드 크기: INT(M)에서 M은 표시 너비를 의미하며, 저장 가능한 값의 범위와는 관계가 없습니다. 숫자가 지정된 너비보다 작을 경우 ZEROFILL 속성을 사용하면 앞에 0이 채워집니다.
      CREATE TABLE `test_int_display` (
          `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
          `val_3` INT(3) UNSIGNED ZEROFILL DEFAULT NULL,
          `val_6` INT(6) UNSIGNED ZEROFILL DEFAULT NULL,
          PRIMARY KEY (`id`)
      ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
      
      INSERT INTO `test_int_display` (`val_3`, `val_6`) VALUES (1, 1);
      INSERT INTO `test_int_display` (`val_3`, `val_6`) VALUES (12345, 12345);
      -- 결과: val_3은 '001', '12345' (3자리 초과 시 잘림 없이 표시)
      --       val_6은 '000001', '012345' (6자리 미만 시 0으로 채워짐)
      

      INT(M)M 값은 표시 너비에 영향을 주지만, 필드가 저장할 수 있는 실제 값의 범위는 변경하지 않습니다.

    • CHAR vs. VARCHAR:
      • CHAR: 고정 길이 문자열로, 조회 성능이 빠르지만 공간 낭비가 발생할 수 있습니다.
      • VARCHAR: 가변 길이 문자열로, 공간을 절약할 수 있지만 CHAR에 비해 조회 성능이 약간 떨어질 수 있습니다.
    • 주요 MySQL 데이터 타입:
      타입 크기 설명
      CHAR(L) L 바이트 고정 길이 문자열 (0~255 문자)
      VARCHAR(L) 문자열 길이 + 1 또는 2 바이트 가변 길이 문자열 (0~65535 문자)
      TINYINT(L) 1 바이트 정수 (-128~127 또는 0~255 UNSIGNED)
      SMALLINT(L) 2 바이트 정수 (-32768~32767 또는 0~65535 UNSIGNED)
      MEDIUMINT(L) 3 바이트 정수 (-8388608~8388607 또는 0~16777215 UNSIGNED)
      INT(L) 4 바이트 정수 (-2147483648~2147483647 또는 0~4294967295 UNSIGNED)
      BIGINT(L) 8 바이트 정수 (매우 큰 범위)
      FLOAT 4 바이트 단정밀도 부동 소수점 수
      DOUBLE 8 바이트 배정밀도 부동 소수점 수
      DECIMAL(L, D) 가변 정확한 고정 소수점 수
      DATE 3 바이트 날짜 (YYYY-MM-DD)
      DATETIME 8 바이트 날짜 및 시간 (YYYY-MM-DD HH:MM:SS)
      TIMESTAMP 4 바이트 타임스탬프 (YYYYMMDDHHMMSS, 2037년까지)
      TIME 3 바이트 시간 (HH:MM:SS)
      TEXT 문자열 길이 + 2 바이트 최대 65535자 문자열
  • 색인 (Index): 조회 성능을 크게 향상시키지만, 데이터 삽입, 삭제, 수정 작업의 속도를 저하시킬 수 있습니다.
  • 고유 제약 (Unique Constraint): 특정 컬럼의 모든 값이 중복되지 않도록 보장하여 데이터 무결성을 유지합니다.
  • 외래 키 (Foreign Key):

    테이블 간의 관계를 설정하여 데이터의 참조 무결성을 보장합니다. 외래 키 제약을 추가하는 SQL 구문은 다음과 같습니다.

    ALTER TABLE 자식_테이블_이름
    ADD CONSTRAINT [제약_이름] FOREIGN KEY (자식_테이블_컬럼, ...)
    REFERENCES 부모_테이블_이름 (부모_테이블_컬럼, ...)
    ON DELETE 참조_옵션
    ON UPDATE 참조_옵션;
    

    ON DELETEON UPDATE 참조 옵션의 동작 방식:

    • CASCADE: 부모 테이블의 레코드가 업데이트/삭제될 때, 자식 테이블의 관련 레코드도 함께 업데이트/삭제됩니다.
    • SET NULL: 부모 테이블의 레코드가 업데이트/삭제될 때, 자식 테이블의 외래 키 필드 값이 NULL로 설정됩니다. (외래 키 필드가 NULL을 허용해야 합니다.)
    • NO ACTION / RESTRICT: 자식 테이블에 관련 레코드가 존재할 경우, 부모 테이블의 레코드 업데이트/삭제를 허용하지 않습니다. RESTRICT는 즉시 제약을 확인합니다.
    • SET DEFAULT: 부모 테이블의 변경 시 자식 테이블의 외래 키를 기본값으로 설정합니다. (InnoDB 엔진은 현재 이 옵션을 지원하지 않습니다.)
  • MySQL 데이터베이스 엔진 선택:

    MySQL은 다양한 스토리지 엔진을 제공하며, 각 엔진은 특정 사용 사례에 최적화된 특징을 가집니다. 현재 MySQL에서 사용 가능한 엔진을 확인하려면 SHOW ENGINES; 명령을, 기본 엔진을 확인하려면 SHOW VARIABLES LIKE 'storage_engine'; 명령을 사용할 수 있습니다.

    • InnoDB:
      • ACID 준수 트랜잭션 지원, 커밋, 롤백, 크래시 복구 기능 제공.
      • 행(row) 레벨 잠금 지원, 다중 사용자 환경에서 높은 동시성 및 성능 제공.
      • 외래 키 제약 조건 지원.
      • 주로 높은 데이터 무결성과 트랜잭션이 요구되는 애플리케이션에 적합하며, MySQL의 기본 엔진입니다.
    • MyISAM:
      • 트랜잭션을 지원하지 않음.
      • 테이블 레벨 잠금을 사용하며, 읽기 작업이 많은 환경에서 빠른 삽입 및 조회 성능을 보임.
      • `.frm` (테이블 정의), `.MYD` (데이터), `.MYI` (인덱스) 세 가지 파일로 구성됨.
      • 주로 단순한 웹 애플리케이션, 데이터 웨어하우스, 읽기 전용 작업에 적합합니다.
    • MEMORY:
      • 모든 데이터를 메모리에 저장하여 매우 빠른 데이터 접근 속도를 제공.
      • HASH 및 BTREE 인덱스 지원.
      • 서버 재시작 시 데이터가 소실되므로, 임시 데이터 저장이나 캐싱 목적으로 주로 사용됩니다.

    스토리지 엔진 선택 전략: 데이터베이스 내의 각 테이블은 요구사항에 따라 다른 스토리지 엔진을 사용할 수 있습니다. 트랜잭션과 데이터 무결성이 중요한 테이블에는 InnoDB를, 읽기 작업이 많고 트랜잭션이 필요 없는 로그 또는 아카이브 테이블에는 MyISAM이나 Archive를, 임시 데이터 저장에는 MEMORY 엔진을 사용하는 등 유연하게 선택하는 것이 전체 데이터베이스 시스템의 성능을 최적화하는 데 중요합니다.

프로젝트 데이터베이스 이해

GitLab 프로젝트 그룹에 참여하여 toutiao-backend 저장소를 클론하고, 프로젝트의 SQL 파일을 분석하여 데이터베이스 스키마와 구조를 이해하는 것이 중요합니다.

태그: python MySQL Redis sqlalchemy Gitflow

6월 21일 00:53에 게시됨