Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions PR-rule.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
n주차 - 준/박서윤 워크북 과제 제출
# ✅ n주차 워크북 완료 🎉

**워크북을 완료한 챌린저분들, 수고 많으셨습니다!**
Expand Down
4 changes: 4 additions & 0 deletions week00/mission/.gitkeep
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
1. members
-> 서비스 사용자의 계정 및 프로필 정보

컬럼명
77 changes: 77 additions & 0 deletions week01/keyword/.gitkeep
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
- 외래키

**정의:**

한 테이블의 컬럼이 다른 테이블의 기본 키(PK)를 참조하는 키. 테이블 간의 관계를 맺어주는 연결고리 역할을 수행함.

**핵심 속성(제약 조건):**

참조 무결성: 외래 키는 참조하는 부모 테이블의 기본 키에 존재하는 값이거나, null값이어야 함. 즉, 존재하지 않는 '유령 데이터'를 참조할 수 없음.

→ 외래키는 관계의 신뢰성을 보장하기 위해 필요함. 예를 들어 수강신청 기록은 반드시 실존하는 학생에 의해 이루어져야한다는 규칙을 강제하기에 데이터는 일관성을 유지하고, 현실세계의 논리적 관계를 그대로 데이터베이스에 반영할 수 있게 됨.
- 기본키

**정의:**

테이블 내의 각 행(Row)을 유일하게 식별할 수 있는 값을 가진 컬럼 또는 컬럼들의 조합.

**핵심 속성(제약 조건):**

유일성(Uniqueness), 최소성(Minimality), 개체 무결성(Not Null). 테이블 내에서 절대 중복될 수 없으며, 반드시 값을 가져야 함.
→ 기본키는 데이터의 '신분증'과 같음. 이름은 같을 수 있어도 각자를 구분하는 주민등록번호가 있는 것처럼, 기본키가 있어야 수많은 데이터 속에서 원하는 특정 데이터를 정확히 찾아 수정하거나 삭제할 수 있음.
- ER 다이어그램

**정의:**

데이터베이스의 구조를 시각적으로 표현한 설계도. 데이터(개체), 데이터의 속성, 데이터 간의 관계를 한눈에 파악할 수 있게 함.

**핵심 요소:**

개체(Entity), 속성(Attribute), 관계(Relationship). 이 세 가지 요소를 사용하여 시스템의 데이터 구조를 논리적으로 모델링함.
→ ER 다이어그램은 집을 짓기 전의 '청사진'이다. 설계도 없이 집을 지으면 구조가 엉망이 되듯, ERD 없이 데이터베이스를 구축하면 데이터 중복과 불일치 문제가 발생하기 쉽다. 개발자와 설계자 간의 중요한 소통 도구이기도 함.

- 복합 키

**정의:**

두 개 이상의 컬럼을 조합하여 하나의 기본 키(PK)를 만드는 것.

**핵심 속성(제약 조건):**

단일 컬럼만으로는 행의 유일성을 보장할 수 없을 때 사용됨. 키를 구성하는 모든 컬럼의 조합이 테이블 내에서 유일해야 함.
→ 복합 키는 '어떤 학생'이 '어떤 과목'을 수강했는지와 같이, 두 개 이상의 조건이 결합되어야만 하나의 특정 상황을 정의할 수 있을 때 사용됨. 주로 테이블 간의 다대다(N:M) 관계를 해소하기 위한 연결 테이블에서 기본 키로 활용됨.

- 연관관계

**정의:**

테이블(개체)들 사이의 논리적인 연결을 의미하며, 주로 외래 키를 통해 구현됨.

**핵심 종류:**

1:1 (일대일), 1:N (일대다), N:M (다대다). 특히 N:M 관계는 물리적으로 직접 구현할 수 없어, 중간에 두 테이블을 1:N 관계로 연결해주는 '연결 테이블'을 필요로 함.
→ 연관관계는 흩어져 있는 데이터에 '맥락'과 '의미'를 부여하는 문법과 같음. 관계 설정이 없다면 데이터는 단순한 값의 나열일 뿐이지만, 관계를 통해 '부서에 소속된 사원', '학생이 수강하는 과목'처럼 유의미한 정보 시스템이 됨.

- 정규화

**정의:**

데이터의 중복을 최소화하고 무결성을 향상시키기 위해, 정해진 규칙에 따라 테이블을 분해하는 과정. 데이터 변경 시 발생하는 이상 현상(Anomaly)을 방지하는 것이 주 목적임.

**핵심 속성(정보처리 실기 핵심):**

1NF(원자값), 2NF(부분 함수 종속 제거), 3NF(이행 함수 종속 제거), BCNF(결정자이면서 후보키가 아닌 것 제거) 등의 단계적 규칙을 적용하여 테이블 구조를 개선함.
→ 정규화는 잘 정리된 '서랍장'을 만드는 과정. 종류별로 물건을 나눠 담아 중복 구매를 막고(중복 최소화), 관리를 쉽게 만드는 것과 같음. 데이터 구조를 논리적이고 깔끔하게 만들어 장기적인 유지보수를 용이하게 하는 필수 설계 단계.

[정보처리 실기_데이터베이스06강_정규화](https://youtu.be/RXQ1kZ_JHqg?si=f0OPsoOWnJXSbqca)

- 반 정규화

**정의:**

정규화된 테이블에 대해, 시스템의 조회 성능 향상을 목적으로 의도적으로 데이터 중복을 허용하거나 테이블을 통합하는 기법.

**핵심 속성(제약 조건):**

읽기(SELECT) 성능은 향상되지만, 데이터 저장 공간이 낭비되고 입력/수정/삭제 시 데이터 불일치가 발생할 수 있어 일관성 유지가 어려워짐.
→ 반정규화는 서랍장에 잘 정리된 옷 중에서 '내일 당장 입을 옷을 미리 꺼내 의자에 걸어두는 것'과 같다. 아침에 찾는 시간(JOIN)을 줄여 매우 빠르지만, 방이 어수선해지고(중복) 다른 옷을 입고 싶을 때 다시 정리해야 하는(관리 복잡성) 비용이 따름. 반드시 정규화 이후, 성능 개선이 필요한 부분에 한해 신중하게 적용해야 함.
Empty file added week01/keyword/keyword.md
Empty file.
199 changes: 199 additions & 0 deletions week01/mission/.gitkeep
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
### **DB 설계**

- **모델**: 관계형 데이터베이스 모델을 기반으로 설계
- **핵심 엔티티(Entity)**:
1. **Users**: 서비스에 가입한 사용자 정보
2. **Regions**: 가게가 위치한 지역 정보
3. **Stores**: 미션이 부여되는 가게 정보
4. **Missions**: 사용자가 수행할 미션 정보
5. **User_Missions**: 사용자가 어떤 미션을 수행하고 있는지, 완료했는지 상태를 기록하는 테이블 (매핑 테이블)
6. **Reviews**: 사용자가 완료한 미션에 대해 작성한 리뷰
7. **Food_Categories & User_Food_Preferences**: 사용자의 음식 선호도를 관리하기 위한 테이블

### **1. users**

**설명**: 서비스 사용자의 계정 및 프로필 정보.

| 컬럼명 | 데이터 타입 | 제약 조건 | 설명 |
| --- | --- | --- | --- |
| id | BIGINT | PK, AI | 사용자 고유 식별자 |
| email | VARCHAR(255) | UNIQUE, NOT NULL | 로그인 이메일 |
| password | VARCHAR(255) | NOT NULL | 해시 처리된 비밀번호 |
| nickname | VARCHAR(50) | UNIQUE, NOT NULL | 닉네임 |
| gender | VARCHAR(10) | | 성별 ('MALE', 'FEMALE') |
| birth_date | DATE | | 생년월일 |
| address_main | VARCHAR(255) | | 주소 |
| total_points | INT | NOT NULL, DEFAULT 0 | 보유 총 포인트 |
| status | VARCHAR(15) | NOT NULL, DEFAULT 'ACTIVE' | 계정 상태 ('ACTIVE', 'INACTIVE') |
| created_at | DATETIME(6) | NOT NULL | 가입일 (밀리초 포함) |
| updated_at | DATETIME(6) | NOT NULL | 마지막 정보 수정일 (밀리초 포함) |
| deleted_at | DATETIME(6) | | 비활성화(탈퇴) 처리일 (밀리초 포함) |

### **2. food_categories**

**설명**: 음식 종류 (한식, 일식 등)

| 컬럼명 | 데이터 타입 | 제약 조건 | 설명 |
| --- | --- | --- | --- |
| id | BIGINT | PK, AI | 카테고리 고유 식별자 |
| name | VARCHAR(50) | UNIQUE, NOT NULL | 카테고리명 |
| created_at | DATETIME(6) | NOT NULL | 생성일 |
| updated_at | DATETIME(6) | NOT NULL | 수정일 |

### **3. user_food_preferences**

**설명**: users와 food_categories의 N:M 관계를 해소하기 위한 매핑 테이블.

| 컬럼명 | 데이터 타입 | 제약 조건 | 설명 |
| --- | --- | --- | --- |
| id | BIGINT | PK, AI | 매핑 고유 식별자 |
| user_id | BIGINT | FK | 사용자 ID (users.id) |
| food_category_id | BIGINT | FK | 카테고리 ID (food_categories.id) |
| created_at | DATETIME(6) | NOT NULL | 선호 등록일 |
| update_at | DATETIME(6) | NOT NULL | 선호 수정일 |

### **4. regions**

**설명**: 가게가 위치한 지역 정보.

| 컬럼명 | 데이터 타입 | 제약 조건 | 설명 |
| --- | --- | --- | --- |
| id | BIGINT | PK, AI | 지역 고유 식별자 |
| name | VARCHAR(100) | UNIQUE, NOT NULL | 지역명 |
| created_at | DATETIME(6) | NOT NULL | 생성일 |
| updated_at | DATETIME(6) | NOT NULL | 수정일 |

### **5. stores**

**설명**: 미션이 부여되는 가게 정보.

| 컬럼명 | 데이터 타입 | 제약 조건 | 설명 |
| --- | --- | --- | --- |
| id | BIGINT | PK, AI | 가게 고유 식별자 |
| name | VARCHAR(100) | NOT NULL | 가게 이름 |
| address | VARCHAR(255) | NOT NULL | 가게 상세 주소 |
| region_id | BIGINT | FK, NOT NULL | 소속 지역 ID (regions.id) |
| created_at | DATETIME(6) | NOT NULL | 생성일 |
| updated_at | DATETIME(6) | NOT NULL | 수정일 |

### **6. missions**

**설명**: 각 가게에 할당되는 미션의 원본 데이터.

| 컬럼명 | 데이터 타입 | 제약 조건 | 설명 |
| --- | --- | --- | --- |
| id | BIGINT | PK, AI | 미션 고유 식별자 |
| store_id | BIGINT | FK, NOT NULL | 소속 가게 ID (stores.id) |
| title | VARCHAR(255) | NOT NULL | 미션 제목 |
| description | TEXT | | 미션 상세 설명 |
| reward_points | INT | NOT NULL | 보상 포인트 |
| is_active | BOOLEAN | NOT NULL, DEFAULT true | 미션 활성화 여부 |
| created_at | DATETIME(6) | NOT NULL | 생성일 |
| updated_at | DATETIME(6) | NOT NULL | 수정일 |

### **7. user_missions**

**설명**: users와 missions의 N:M 관계를 해소하고, 사용자의 미션 수행 상태를 기록하는 매핑 테이블.

| 컬럼명 | 데이터 타입 | 제약 조건 | 설명 |
| --- | --- | --- | --- |
| id | BIGINT | PK, AI | 수행 기록 고유 식별자 |
| user_id | BIGINT | FK, NOT NULL | 사용자 ID (users.id) |
| mission_id | BIGINT | FK, NOT NULL | 미션 ID (missions.id) |
| status | VARCHAR(20) | NOT NULL | 미션 상태 ('IN_PROGRESS', 'COMPLETED') |
| created_at | DATETIME(6) | NOT NULL | 미션 시작일 |
| updated_at | DATETIME(6) | NOT NULL | 상태 변경일 (미션 완료일) |

### **8. reviews**

**설명**: 완료된 미션(user_missions)에 대해 작성된 리뷰.

| 컬럼명 | 데이터 타입 | 제약 조건 | 설명 |
| --- | --- | --- | --- |
| id | BIGINT | PK, AI | 리뷰 고유 식별자 |
| user_mission_id | BIGINT | UNIQUE, FK, NOT NULL | 완료된 미션 ID (user_missions.id) |
| user_id | BIGINT | FK, NOT NULL | 작성자 ID (users.id) |
| store_id | BIGINT | FK, NOT NULL | 가게 ID (stores.id) |
| rating | INT | NOT NULL | 별점 (1~5) |
| content | TEXT | NOT NULL | 리뷰 내용 |
| created_at | DATETIME(6) | NOT NULL | 작성일 |
| updated_at | DATETIME(6) | NOT NULL | 수정일 |
1. **users와 missions의 관계 → N:M (다대다)**

논리적 해석:

→ 한 명의 사용자는 여러 개의 미션을 수행할 수 있다.

하나의 미션(예: "12,000원 이상 식사")은 여러 사용자에 의해 수행될 수 있다.

물리적 설계:

→ N:M 관계는 관계형 데이터베이스에서 직접 표현할 수 없으므로, 중간에 매핑 테이블인 user_missions를 둔다.

→ users와 user_missions는 1:N 관계가 된다. (한 명의 유저는 여러 미션 수행 기록을 가짐)

→ missions와 user_missions는 1:N 관계가 된다. (하나의 미션은 여러 유저에 의해 수행됨)

따라서 user_missions 테이블은 user_id와 mission_id를 외래 키(FK)로 가진다.

1. **users와 food_categories의 관계 → N:M (다대다)**

논리적 해석:

→ 한 명의 사용자는 여러 음식 카테고리(한식, 중식 등)를 선호할 수 있다.

→ 하나의 음식 카테고리는 여러 사용자에게 선택될 수 있다.

물리적 설계:

→ 위와 동일하게 N:M 관계이므로, 매핑 테이블인 user_food_preferences를 생성한다.

→ user_food_preferences는 user_id와 food_category_id를 FK로 가져와 두 테이블을 연결한다.

1. **regions와 stores의 관계 → 1:N (일대다)**

논리적 해석:

→ 하나의 지역("안암동")에는 여러 가게가 포함될 수 있다.

→ 하나의 가게는 오직 하나의 지역에만 속한다.

물리적 설계:

→ 1:N 관계에서는 N쪽이 1쪽의 PK를 FK로 가진다.

따라서 stores 테이블이 regions 테이블의 PK인 id를 region_id라는 이름의 FK로 가진다.

1. **stores와 missions의 관계 → 1:N (일대다)**

논리적 해석:

→ 하나의 가게는 여러 종류의 미션(예: 금액 미션, 메뉴 미션)을 가질 수 있다.

→ 하나의 미션은 특정 가게 하나에만 종속된다.

물리적 설계:

→ missions 테이블(N쪽)이 stores 테이블(1쪽)의 PK인 id를 store_id라는 FK로 가진다.

1. **user_missions와 reviews의 관계 → 1:1 (일대일)**

논리적 해석:

→ 하나의 완료된 미션 수행 기록(user_missions)에 대해서는 단 하나의 리뷰만 작성할 수 있다.

→ 하나의 리뷰는 특정 미션 수행 기록 하나에 대해서만 작성된다.

물리적 설계:

→ 미션을 완료하지 않으면 리뷰를 쓸 수 없도록 강제하는 역할을 한다.

→ reviews 테이블이 user_missions의 PK인 id를 user_mission_id라는 FK로 가진다.

→ 이때 user_mission_id 컬럼에 UNIQUE 제약 조건을 걸어주어야 1:1 관계가 완성된다.

이렇게 하면 하나의 user_mission에 대해 두 개 이상의 리뷰가 생성되는 것을 원천적으로 차단할 수 있다.

![image.png](attachment:8b114e34-8e73-46d3-a9e7-eb1833a44c50:image.png)

https://www.erdcloud.com/d/TvdLkZEA7MbGNCfMp
84 changes: 84 additions & 0 deletions week02/keyword/keyword.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
- 데이터베이스 정규화

**제1정규형(1NF)**

→ 원자값을 갖도록 하는 것

→ 하나의 컬럼에 여러 개의 값이 들어가지 않도록 분리

**제2정규형(2NF)**

→ 제1정규형을 만족하고, 부분 함수 종속성을 제거하는 단계

→ 기본키가 여러 컬럼으로 구성된 복합키일 경우, 기본키의 일부에만 종속되는 컬럼을 별도의 테이블로 분리

**제3정규형(3NF)**

→ 제2정규형을 만족하고, 이행적함수 종속성을 제거하는 단계

→ 기본키가 아닌 일반 컬럼에 종속되는 컬럼을 별도의 테이블로 분리

(ex/ 학생 테이블에 학과명과 학과 전화번호가 모두 있는 경우, 학과 전화번호는 학과명에 종속되므로 별도의 학과 테이블로 분리)

**BCNF**

→ 제3정규형보다 더 엄격한 조건으로, 모든 결정자가 후보키 집합에 속하도록 하는 것

- 인덱스(Index)

정의:

→ 데이터베이스 테이블에서 원하는 데이터를 빠르게 찾기 위해 사용하는 자료구조(주소 정보)

→ 인덱스가 없으면 테이블 전체를 순차적으로 탐색해야 하므로 데이터 양이 많아질수록 검색 속도가 현저히 느려짐

**장점**

→ SELECT 쿼리의 검색 속도를 획기적으로 향상시킨다.

→ WHERE, JOIN, ORDER BY 등의 성능을 개선한다.

→ 시스템 전반의 부하를 줄여준다.

**단점**

→ INSERT, UPDATE, DELETE 연산의 속도가 저하될 수 있다.

→ 너무 많은 인덱스는 오히려 옵티마이저의 판단을 흐리게 하여 성능을 저하시킬 수 있다.

*어떤 컬럼에 인덱스를 걸어야 할지 신중하게 결정해야함*

*주로 고유성 정도가 높고, WHERE 절의 조건으로 자주 사용되는 컬럼에 인덱스를 생성하는 것이 좋음*

- ORM VS Raw SQL

**ORM (Object-Relational Mapping, 객체-관계 매핑)**: 프로그래밍 언어의 객체와 관계형 데이터베이스의 데이터를 자동으로 연결해주는 기술. (예: JPA, Hibernate, Django ORM)

**장점**

→ 생산성 향상 : SQL을 몰라도 객체지향적으로 DB를 다룰 수 있어 개발 속도가 빠르다.

→ 데이터베이스 종속성 감소 : DB를 변경해도 코드 수정이 거의 필요

→ 유지보수 용이성 : SQL문에 코드에 섞여 있지 않아 가독성이 높고 유지보수가 편하다.

**단점**

→ 세밀한 튜닝의 어려움 : 복잡하고 최적화된 쿼리를 자동으로 생성하기 어려움

→ 학습 어려움 : ORM 자체의 동작 방식과 내부 구조를 이해하는 데 시간이 필요

**Raw SQL (또는 SQL Mapper)**: 개발자가 **SQL 쿼리문을 직접 작성**하여 데이터베이스와 소통하는 방식. SQL Mapper는 작성된 SQL과 객체를 매핑해주는 라이브러리를 의미하기도 한다. (예: MyBatis, JDBC)

**장점**

→ 최고의 성능 : 개발자가 직접 쿼리를 작성하므로, 가장 최적화된 SQL 실행이 가능

→ 높은 자유도 : 어떤 형태의 복잡한 쿼리라도 자유롭게 작성하고 실행 가능

**단점**

→ 생산성 저하 : 반복적인 CRUD SQL을 직접 작성해야 하므로 개발 속도가 느림
→ 데이터베이스 종속성 : DB가 변경되면 해당 DB의 문법에 맞게 SQL을 수정해야한다.

한쪽이 절대적으로 우월하기보다는 ORM은 빠른 개발과 유지보스에 유리하고, 복잡한 통계 쿼리보다는 일반적인 CRUD 작업이 주를 이루는 서비스에 용이하다. Raw SQL은 성능이 매우 중요하거나, 복잡한 집계/ 통계 쿼리, 대용량 데이터 처리가 필요할 때 좋다.
Loading
Loading