ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [5] 개발 3 - 모델에 대한 고민
    4학년/Project-itda 2025. 4. 15. 14:02

     

    모델에 대한 고민이 있습니다 

     

     

    고민 1. 데이터를 어디까지 db에 저장해야하는가

    고민 2. 많이 넣기엔 성능 issue 가 있을 거 같음, 보기에 안 좋아짐

    고민 3. 데이터를 수평분리 혹은 수직분리 한다면 구분을 어찌해야하ㅡㄴ가

    고민 4. 업로드 데이터는 포맷을 어디까지 허용하여 저장하는가 ( mp3,pdf, mp4이런식으로 구분안해서 저장해도되는가 )

     

    애매~합니다. 우선 초안으로 짜본건 

    이렇게 되는데요... 짜다보니까 너무 방대해지고 정규화도 많이 되어서 멈췄었는데

     

    이제는 더 이상 물러날 곳이 없다!

     

     

    지피티한테 함 물어봤어요

     

    💭 고민 1: 데이터를 어디까지 DB에 저장해야 하는가

    핵심 질문:
    어떤 데이터는 "영구적 저장이 필요한가?" vs "일시적 or 캐시처럼 써도 되는가?"

    ✅ DB에 넣는 게 맞는 것들

    • 사용자 정보 (로그인 관련, 닉네임 등)
    • 프로젝트 정보 (이름, 소개, 팀원, 마감일 등)
    • 참여 정보 (누가 어떤 프로젝트에 참여하는지)
    • 업로드된 파일 메타정보 (파일명, 확장자, 업로드한 유저, 업로드일, 연결된 프로젝트 등)
    • 코멘트 (코멘트 내용, 작성자, 연결된 파일 등)
    • 일정/할 일 정보

    ⛔ 굳이 DB에 안 넣어도 되는 것들

    • 실시간 채팅 내용 (이건 NoSQL이나 Firebase, Redis 같은 쪽으로 가는 게 좋음. 나중에 대화 저장 옵션이 있으면 백업 식으로 따로 저장 가능)
    • 실시간 피드백 영상 스트림 내용 (WebRTC로 처리, DB 저장 NOPE)

     

    이건 ㅇㅋ 실시간관련 내용은 넣지 말라는 거잖아

    근데 채팅은 저장해야하는 거아닌가 ?ㅠ

     

     

     

     

     

    💭 고민 2: 많이 넣기엔 성능 이슈가 있을 듯

    걱정 ㄴㄴ, 다만:

    • 정규화 과도하게 하면 쿼리 너무 꼬여서 복잡해지고 느려짐 → 적당히 정규화하고, 필요한 곳은 Join 대신 Embedded document 또는 Redis 캐시 사용 고려
    • 파일 업로드 자체는 DB에 넣지 말고 S3 같은 외부 저장소 쓰고 → DB엔 URL만 저장!

    내말투 따라하네 킹받게...

     

    우선 정규화란 무엇인가

    User라는 모델에 피쳐가 id,name,project_name, project_role일 때

    여러 프로젝트에 참여하면 유저이름이 쓸대없이 반복된단말이지

     

    그래서 정규화하면 

    User 피쳐에 id,name

    ProjectUser 피쳐에 user_id | project_id, role

    Project 피쳐에 id | project_name일케하란 뜻이지...

     

     

    정규화를 과도하게 했을 때 문제점

    너어무 많이 쪼개져 있어서 

    정보를 찾을 때 테이블 3~4개정도 까지 조인해야

    조회가 가능할 수도 있대요

     

    쿼리가 ㅈㄴ느려진다이거죠

     

    그래서 적당히 정규화 + 캐시 or 임베딩이 필요하대요.

     

     

    그래서 적당히 정규화를 어케하는데 ㅠ

     

    그리고 Embedded document란?

    NoSQL에서 자주 쓰는 방식인데, 

    댓글 정보 같은 걸 따로 테이블 안 만들고 파일 데이터 안에 댓글을 리스트로 저장하자..와같은 것이지

    데이터 접근이 빠르고 수정이 어렵대요

     

     

    좀 더 물어보니까

     

    데이터 안에 다른 데이터를 그냥 냅다 같이 ! 합치기 ! 라네요

    File
    -----
    id | filename

    Comment
    -------------
    id | file_id (FK) | author_id | content

     

    일 때

     

     

    임베디드 해버리면 

    {
      "file_id": 123,
      "filename": "video.mp4",
      "comments": [
        {
          "comment_id": "c1",
          "author": "user1",
          "content": "수정 ㄱㄱ"
        },
        {
          "comment_id": "c2",
          "author": "user2",
          "content": "굿이에요"
        }
      ]
    }

     

    랑같이 냅다 넣어버리는거죠 

     

     

    그럼 임베디드 저장 방식은 언제 하는 게 좋을까?

    제가 우선 생각해보자면... 데이터 수정이 너무 잦을 땐 하지말고,

     조금만 필요할 때 하면 좋을 것 같은데...

    데이터가 강하게 연결되어 있고 (1:N) ✅ YES
    자주 같이 조회됨 ✅ YES
    댓글 수가 많지 않음 (수십~수백 이내) ✅ YES
    댓글만 따로 자주 수정/삭제함 ❌ NO
    댓글 수가 매우 많아질 수 있음 ❌ NO

    라고하네요

     

    조회가 너무 잦거나 많아지면 쓰지말래요 

     

     

    연결성이 강할때 잦은 수정이나 많은 데이터가 없을 때 하기 !!

     

     

    그럼 잇다 모델에서 임베디드 쓸 만한 곳을 찾아보자

     

    1. 파일 피드백 부분

    - 파일에 달린 "코멘트 리스트"

    {
      "file_id": "abc123",
      "filename": "project.mp4",
      "uploaded_by": "user1",
      "comments": [
        {
          "id": "c1",
          "user_id": "user2",
          "content": "여기 BGM 수정하면 좋겠어요"
        },
        {
          "id": "c2",
          "user_id": "user3",
          "content": "컷 잘라야 할 듯"
        }
      ]
    }

     

     

    2.유저와 프로젝트 사이

    -프로젝트에 달린 "유저 리스트"

    는 안될 것 같습니다.

     

    작업물에 달린 코멘트 ✅ 매우 적합 파일과 강하게 묶여 있고, 같이 조회
    유저의 친구 목록 ✅ 가능 간단한 배열 형태면 문제 없음
    채팅 기록 ❌ 안 됨 데이터 많고 쿼리 복잡함
    할 일 목록 (개인 기준) ✅ or ❌ 많지 않으면 Embedded, 필터/검색 필요시 정규화
    프로젝트 참여자 정보 ❌ 안 됨 참여자마다 역할, 업로드 등 복잡한 관계 있음

     

    라고 하네요 

     

     

     

    3. 유저와 친구목록

    - 유저에 달린 " 친구 리스트 "

    - 채팅 기록은 조회 정렬 쿼리가 자주 들어가서 ㄴㄴ

     

     

    그럼 임베디드는 1 3 두개만 하겠습니다

     

    💭 고민 3: 수평 / 수직 분리?

    이건 초기에까지는 크게 신경 안 써도 되는데, 나중에 확장 고려해서 기본 설계는 탄탄하게 잡자.

    수평 분리 (row 단위, scale-out)

    → 예: 프로젝트 수가 많아짐
    → 프로젝트 테이블을 사용자 ID 기준으로 샤딩

    수직 분리 (column 단위, 관심사 분리)

    → 예: 채팅, 코멘트, 유저 프로필 등 기능별 분리
    핵심 도메인 (User, Project, File)은 메인 DB에
    → 채팅, 로그, 알림 이런 건 별도의 DB or NoSQL로 분리

     

     

    나도 기초는 탄탄하게 잡아야 한다고 생각합니다.

     

    수평 분할?

    대량 데이터 가질 때 좋다............

    왜지 ? 생각해보면 

     

    Project의 피쳐에 name, info, deadLine이 있을 때, 프로젝트가 2025개까지 늘어난다치면

    Project테이블이 엄~~~청 길어질거임. 그래서 ? 

    그냥 Project모델을 앗사리 name으로 정한다... 맞나...?

     

    아 지피티한테 물어보니까 아니라네요 

    프로젝트가 2천만개 있으면 ...

    프로젝트를 "기간" 혹은 "ID"범위로 나누어서 저장한다.

    Name으로 나누기엔 단순 문자열이라 파티셔닝이 안된다구 하네요.

     

     

     

    수직 분할 ?

    수평분할이 객체가 엄청 많을 때 피쳐의 특정 범위로 나눈다 라면,

    수직은 플젝에 피쳐가 엄청 많아졌을 때 ( name,info,role,user,섬네일,tag,link,backuplink.......와같음)

    이 모든 내용이 한번에 필요하지 않다 >>>>>>>> 핵심 정보만 따로 빼서 테이블을 분리하자..네요

     

    왜 하냐? 의 핵심은

     수평 : 객체 너무 많아. DB느려져. 빨리찾자

    수직 : 모델 너무 무거워. 쓸 거만 분리하자

     

     

     

     

     

    💭 고민 4: 업로드 파일 포맷을 어디까지 허용할까?

    옵션 1. 확장자 따로 안 나누고 저장

    • ✅ 간단, 백엔드에서 MIME 타입으로 처리 가능
    • ❌ 사용자 UI에서 필터링이 불편함 (예: "영상만 보기" 등)

    옵션 2. 타입 구분 컬럼 추가 (type: video, audio, image, doc 등)

    • ✅ 검색/필터링/미리보기 구현할 때 유리
    • ✅ UX 측면에서도 정리된 느낌
    • ❌ 확장자 외에도 컨텐츠 타입 분류 로직 하나 더 생김

    🔥 추천: 파일 확장자 + 컨텐츠 타입 컬럼 둘 다 저장 (예: .mp4 + video) → 이러면 정리도 되고 확장자 제한 걸기도 쉬움!

     

     

    마지막 고민도 해결되었습니다.

     

    검색 필터링 미리보기 잘하기위해서....

    포맷을 좀 제한해야 겠습니다.

     

     

    그럼 다시 한 번 짜볼게요

     

    🎯 수직 분할할지 고민할 포인트 (컬럼 기준)

    ✅ 이 컬럼은 자주 쓰이는 핵심 정보인가?

    • ✔️ name, deadline, category, leader_id 같은 것들 → 👉 메인 테이블에 남겨두자 (ProjectMain)

    ✅ 이 컬럼은 부가정보인가? (가끔만 쓰거나 UI 보조용)

    • 🔹 썸네일, backup_link, 상세 소개글, tag, SNS 링크, 설정값 → 👉 서브 테이블로 분리 가능 (ProjectDetail)

    🎯 수평 분할할지 고민할 포인트 (데이터 양 기준)

    ✅ 이 테이블은 나중에 수만~수십만 건 생길 수 있는가?

    • 예: project_user, file_upload, comment, chat_log

    → 지금은 그대로 쓰고, 나중에 필요할 때:

    • 기간 기준: created_at 기준으로 파티션 나누기
    • ID 기준: project_id, user_id 범위로 쪼개기

    👉 PostgreSQL에서는 파티션 테이블 쓰면 나중에 자연스럽게 분리 가능하게 설계 가능

     

    을 기준으로 고민했습니다.

     

     

    지피티는 고칠 게 없다고 하긴 하는데.... 

    영 못미덥단 말이죠

    뭔가 빼먹어서 나중에 추가할 일 이 생길 것 만 같은 기분....

     

     

    지피티가 짜준 ERD예요 ㅋㅋㅋㅋㅋㅋ

    가독성 ㅈㄴ 안 좋네 

    나중에 제가 따로 작성하겠습니다

    728x90

    댓글

Designed by Tistory.
티스토리 친구하기