-
[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'4학년 > Project-itda' 카테고리의 다른 글
[7] 개발외- 기능명세서는 진짜 중요했다. (3) 2025.05.08 [6]개발4 - 실제 모델 구축 (1) 2025.05.08 [4] 개발 2 - Front 초안 완성 (1) 2025.04.15 [Docker] 라이브 챗 구현해보기 (1) 2025.04.11 내가 하는게 바이브 코딩? (0) 2025.04.10