-
Notifications
You must be signed in to change notification settings - Fork 8
더미데이터 생성하고 실행하기
Jang Hyeok-su edited this page Sep 27, 2024
·
10 revisions
brew install python
python3 -m venv myenv
source myenv/bin/activate
pip3 install sqlalchemy faker pymysql cryptography
sqlalchemy -> SQL 쿼리를 Python 코드로 작성 가능(데이터베이스 테이블을 Python 클래스로 매핑해줌)
faker -> 더미데이터 생성 라이브러리
pymysql -> Python용 MySQL 클라이언트 라이브러리(MySQL 데이터베이스에 연결해서 SQL 쿼리를 실행해줌)
cryptography → 암호화 라이브러리, 해시 알고리즘(sha) 사용 시 필요
본문 하단의 스크립트를 로컬에 파일로 저장
ex) ~/Desktop/dummy.py
더미데이터를 넣을 데이터베이스를 실행
로컬 Mysql 도커는 스프링에서 create-drop으로 되어있어 스키마가 아예 없을 겁니다. 스프링을 실행하거나 MySQL에 직접 스키마 DDL을 날려서 테이블을 생성해주세요.
python3 dummy.py
성공!
특정 테이블의 데이터 수를 늘리고 싶다면 스크립트에 어떤 부분을 수정해야 하는지 작성해놓았으니 참고해주세요~
-
각 테이블 별 데이터의 수를 수정하고 싶으시면 아래 함수의 데이터 갯수를 늘리시면 됩니다.
def create_메서드명(파라미터...: int = 데이터 갯수):
-
가장 핵심인 템플릿 데이터는 create_dummy_data 함수에서 배치로 1000개씩 총 100번 반복하여 100,000개의 템플릿을 생성하고 있습니다. 그 이상의 데이터를 넣고 싶다면
create_dummy_data
함수의batch_size
나total_templates
를 키워주시면 됩니다.
from sqlalchemy import create_engine, Column, Integer, String, DateTime, Text, Boolean, ForeignKey
from sqlalchemy.orm import DeclarativeBase, sessionmaker
from faker import Faker
import random
from datetime import datetime
from typing import List, Optional
class Base(DeclarativeBase):
pass
# SQLAlchemy ORM을 사용하여 데이터베이스 모델을 정의
class Member(Base):
__tablename__ = 'member'
id: int = Column(Integer, primary_key=True)
name: str = Column(String(255), unique=True, nullable=False)
password: str = Column(String(255), nullable=False)
salt: str = Column(String(255), nullable=False)
created_at: datetime = Column(DateTime, nullable=False)
modified_at: datetime = Column(DateTime, nullable=False)
class Category(Base):
__tablename__ = 'category'
id: int = Column(Integer, primary_key=True)
name: str = Column(String(255), nullable=False)
is_default: bool = Column(Boolean, nullable=False)
member_id: int = Column(Integer, ForeignKey('member.id'), nullable=False)
created_at: datetime = Column(DateTime, nullable=False)
modified_at: datetime = Column(DateTime, nullable=False)
class Tag(Base):
__tablename__ = 'tag'
id: int = Column(Integer, primary_key=True)
name: str = Column(String(255), nullable=False)
created_at: datetime = Column(DateTime, nullable=False)
modified_at: datetime = Column(DateTime, nullable=False)
class Template(Base):
__tablename__ = 'template'
id: int = Column(Integer, primary_key=True)
title: str = Column(String(255), nullable=False)
description: Optional[str] = Column(Text)
category_id: int = Column(Integer, ForeignKey('category.id'), nullable=False)
member_id: int = Column(Integer, ForeignKey('member.id'), nullable=False)
created_at: datetime = Column(DateTime, nullable=False)
modified_at: datetime = Column(DateTime, nullable=False)
class SourceCode(Base):
__tablename__ = 'source_code'
id: int = Column(Integer, primary_key=True)
template_id: int = Column(Integer, ForeignKey('template.id'), nullable=False)
ordinal: int = Column(Integer, nullable=False)
content: str = Column(Text, nullable=False)
filename: str = Column(String(255), nullable=False)
created_at: datetime = Column(DateTime, nullable=False)
modified_at: datetime = Column(DateTime, nullable=False)
class TemplateTag(Base):
__tablename__ = 'template_tag'
template_id: int = Column(Integer, ForeignKey('template.id'), primary_key=True)
tag_id: int = Column(Integer, ForeignKey('tag.id'), primary_key=True)
created_at: datetime = Column(DateTime, nullable=False)
modified_at: datetime = Column(DateTime, nullable=False)
class Thumbnail(Base):
__tablename__ = 'thumbnail'
id: int = Column(Integer, primary_key=True)
template_id: int = Column(Integer, ForeignKey('template.id'), unique=True, nullable=False)
source_code_id: int = Column(Integer, ForeignKey('source_code.id'), unique=True, nullable=False)
created_at: datetime = Column(DateTime, nullable=False)
modified_at: datetime = Column(DateTime, nullable=False)
# Faker 라이브러리를 사용하여 현실적인 더미 데이터를 생성
def create_members(session: sessionmaker, fake: Faker, count: int = 1) -> List[Member]:
members = []
used_names = set()
while len(members) < count:
name = fake.user_name()
if name not in used_names:
members.append(Member(
name=name,
password=fake.sha256(),
salt=fake.sha1(),
created_at=fake.date_time_this_year(),
modified_at=fake.date_time_this_month()
))
used_names.add(name)
session.add_all(members)
session.commit()
print(f"Created {count} members")
return members
def create_categories(session: sessionmaker, fake: Faker, members: List[Member], categories_per_member: int = 5) -> List[Category]:
categories = []
used_names = set()
for member in members:
member_categories = 0
while member_categories < categories_per_member:
name = fake.word()
if (member.id, name) not in used_names:
categories.append(Category(
name=name,
is_default=(member_categories == 0),
member_id=member.id,
created_at=fake.date_time_this_year(),
modified_at=fake.date_time_this_month()
))
used_names.add((member.id, name))
member_categories += 1
session.add_all(categories)
session.commit()
print(f"Created {len(categories)} categories")
return categories
# 갯수 조절을 원한다면 메서드의 숫자를 변경하시면 됩니다
def create_tags(session: sessionmaker, fake: Faker, count: int = 1000) -> List[Tag]:
tags = [
Tag(
name=fake.word(),
created_at=fake.date_time_this_year(),
modified_at=fake.date_time_this_month()
) for _ in range(count)
]
session.add_all(tags)
session.commit()
print(f"Created {count} tags")
return tags
def create_template_batch(session: sessionmaker, fake: Faker, categories: List[Category], members: List[Member], tags: List[Tag], batch_size: int = 1000):
templates = []
source_codes = []
template_tags = []
thumbnails = []
for _ in range(batch_size):
template = Template(
title=fake.sentence(),
description=fake.text(),
category_id=random.choice(categories).id,
member_id=random.choice(members).id,
created_at=fake.date_time_this_year(),
modified_at=fake.date_time_this_month()
)
templates.append(template)
session.add(template)
session.flush() # This will assign an id to the template
# 항상 최소 1개의 소스 코드를 생성합니다
batch_source_codes = [
SourceCode(
template_id=template.id,
ordinal=j,
content=fake.text(),
filename=fake.file_name(),
created_at=fake.date_time_this_year(),
modified_at=fake.date_time_this_month()
) for j in range(max(1, random.randint(1, 5)))
]
source_codes.extend(batch_source_codes)
session.add_all(batch_source_codes)
session.flush()
# 중복 없는 태그 선택
selected_tags = random.sample(tags, min(random.randint(1, 5), len(tags)))
template_tags.extend([
TemplateTag(
template_id=template.id,
tag_id=tag.id,
created_at=fake.date_time_this_year(),
modified_at=fake.date_time_this_month()
) for tag in selected_tags
])
# 썸네일 생성 시 반드시 소스 코드가 존재함을 보장
thumbnails.append(Thumbnail(
template_id=template.id,
source_code_id=batch_source_codes[0].id, # 첫 번째 소스 코드를 사용합니다
created_at=fake.date_time_this_year(),
modified_at=fake.date_time_this_month()
))
session.add_all(template_tags)
session.add_all(thumbnails)
session.commit()
# 대량의 데이터(10만 개의 템플릿)를 배치 처리 방식으로 생성
def create_dummy_data(session: sessionmaker, fake: Faker):
members = create_members(session, fake)
categories = create_categories(session, fake, members)
tags = create_tags(session, fake)
total_templates = 100000
batch_size = 1000
for i in range(0, total_templates, batch_size):
create_template_batch(session, fake, categories, members, tags, batch_size)
template_count = i + batch_size
print(f"Created {template_count} templates with associated data")
def main():
engine = create_engine('mysql+pymysql://root:woowacourse@localhost:23306/code_zap', echo=False)
Session = sessionmaker(bind=engine)
session = Session()
fake = Faker()
create_dummy_data(session, fake)
session.close()
if __name__ == "__main__":
main()
- 백엔드 코드 컨벤션
- 백엔드 기술 스택 및 선정 이유
- 각종 인스턴스 설정 파일 및 구성 위치 가이드
- ERD (24.09.27)
- 백엔드 CI CD 동작 프로세스
- 로컬 DB 환경 설정
- 백엔드 로깅 전략
- 백엔드 로그 모니터링 구성도
- 스프링 메트릭 모니터링 구성도
- Flyway 로 스키마 관리
- 코드잽 서버 구성도
- Git Submodule 사용 메뉴얼
- 프론트엔드 코드 컨벤션
- 프론트엔드 기술 스택 및 선정 이유
- 프론트엔드 서비스 타겟 환경 및 브라우저 지원 범위 선정
- 프론트엔드 모니터링 및 디버깅 환경 구축
- 프론트엔드 테스트 목록
- 프론트엔드 라이브러리 기술 검토
- 프론트엔드 개발서버, 운영서버 빌드 및 배포 환경 구분
- 목표했던 타겟 환경과 디바이스에서 서비스 핵심 기능 동작 확인
- 프론트엔드 접근성 개선 보고서
- EC2 로그 확인 방법
- VSCode를 통한 EC2 인스턴스 SSH 연결 방법
- 터미널을 통한 EC2 인스턴스 SSH 연결 방법
- NGINX 설정 파일 접근 및 적용 방법
- DB 접속 및 백업 방법
- [QA] 배포 전 체크리스트
- CI 파이프라인 구축
- CD 파이프라인 구축
- 백엔드 CI CD 트러블슈팅
- Lombok Annotation Processor 의존성을 추가한 이유
- 2차 스프린트 기준 ERD
- DTO 검증하기
- ProblemDetail
- Fork된 레포지토리 PR에서 CI Secrets 접근 문제 해결
- AWS CloudWatch 모니터링
- 스프링 메트릭 모니터링 구축 방법
- 로깅과 Logback에 대해 알아보아요.
- 백엔드 CD 파이프라인 Ver.2
- 요청, 응답 로그에 correlationId 를 추가하자!
- 3차 스프린트 기준 ERD
- 더미데이터 생성하고 실행하기
- 쿼리 성능 개선 결과
- 테이블별 인덱스 설정 목록
- 사용자 증가 시 발생할 수 있는 문제 상황과 개선 방안
- k6를 사용한 서버 부하 테스트
- 6차 스프린트 기준 ERD
- Query Performance Improvement Results
- 테스트 전략 및 CI 설정
- CI CD 구조
- 배포 전, 로컬에서 로그인 기능 포함 테스트해보는 법
- stylelint 적용기
- 내 작업 브랜치 중간에 Merge된 동료의 작업물을 넣고 싶다면 pull vs rebase
- [TS] Webpack config
- [TS] Webpack 환경에서 MSW v2 이슈
- [TS] webpack에서 react‐router‐dom 적용 안됨
- 2024.07.28 새 기획 회의
- 2024.07.26 2차 데모데이 후 회의
- 2024.07.11 백엔드 논의 좀 할게요
- 2024.07.11 백엔드 ERD 회의
- 2024.07.09 깃 브랜치 전략, PR 템플릿 회의
- 2024.07.03 주제 선정 회의
- 2023.07.03 팀빌딩데이 킥오프 회의
- 2023.08.07 3차 스프린트 중간회고