From f4832dce744c3ff859e6250aebca673256e92667 Mon Sep 17 00:00:00 2001 From: chazicer Date: Thu, 19 Mar 2026 12:26:35 +0900 Subject: [PATCH 1/5] =?UTF-8?q?keyword:=200=EC=A3=BC=EC=B0=A8=20=ED=82=A4?= =?UTF-8?q?=EC=9B=8C=EB=93=9C=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- keyword/chapter00/keyword.md | 275 +++++++++++++++++++++++++++++++++++ 1 file changed, 275 insertions(+) create mode 100644 keyword/chapter00/keyword.md diff --git a/keyword/chapter00/keyword.md b/keyword/chapter00/keyword.md new file mode 100644 index 0000000..feea33d --- /dev/null +++ b/keyword/chapter00/keyword.md @@ -0,0 +1,275 @@ +# 1. PK,FK란? + +## PK: Primary Key + +기본키는 후보키 중에서 릴레이션의 각 튜플을 대표적으로 식별하기 위해 선택한 키이다. + +후보키가 여러 개 존재할 경우, 데이터베이스 설계자는 사용 환경을 고려하여 가장 적절한 후보키를 기본키로 선택한다. + +### 기본키 선택 기준 + +1. NULL 값을 가질 수 있는 속성은 기본키로 부적합하다. + + 기본키는 각 튜플을 명확하게 식별해야 하므로 NULL 값을 허용할 수 없다. + +2. 값이 자주 변경되는 속성은 기본키로 부적합하다. + + 기본키 값이 자주 바뀌면 참조 관계 유지와 데이터 관리가 복잡해진다. + +3. 가능한 한 단순한 후보키를 선택한다. + + 속성의 개수가 적고, 길이가 짧고, 다루기 쉬운 키가 선호된다. + +4. 하나의 릴레이션에는 기본키가 하나만 존재한다. + +### 기본키의 특징 + +- 중복된 값을 가질 수 없다. +- NULL 값을 가질 수 없다. + +## FK: Foreign Key + +외래키는 한 릴레이션의 속성(또는 속성 집합) 중에서 다른 릴레이션의 기본키를 참조하는 키이다. 이때 외래키가 다른 릴레이션의 대체키를 참조하는 것도 가능하다. 기본키로 선택받지는 못했지만 유일성과 최소성을 만족하는 대체키를 참조하더라도 관련있는 튜플을 구분가능하기 때문이다.! + +외래키는 릴레이션 간의 관계를 표현하며, 참조 무결성을 유지하는 데 사용된다. 참조 무결성이란 외래키가 참조하는 값이 반드시 참조 대상 테이블에 존재하도록 보장하는 제약이다. + +### 외래키의 특징 + +- 다른 릴레이션의 기본키를 참조한다. +- 동일한 값이 여러 번 나타날 수 있다. +- 경우에 따라 NULL 값을 가질 수 있다. +- 릴레이션 간 연결 역할을 한다. + +기본키는 한 릴레이션 내부에서 튜플을 식별하고, 외래키는 릴레이션과 릴레이션을 연결한다. + +# 2. ERD란? + +ERD(Entity Relationship Diagram)는 개체와 개체 간의 관계를 그림으로 표현한 다이어그램이다. +데이터베이스를 설계할 때 어떤 개체가 존재하는지, 각 개체가 어떤 속성을 가지는지, 그리고 개체들 사이에 어떤 관계가 있는지를 시각적으로 나타내기 위해 사용한다. + +예를 들어 쇼핑몰 데이터베이스를 설계할 때 회원, 상품, 주문과 같은 개체를 정의하고, +회원이 주문을 한다, 주문은 상품을 포함한다와 같은 관계를 ERD로 표현할 수 있다. + +## ERD의 구성 요소 + +1. 개체(Entity): 데이터로 관리할 대상. 예) 회원, 상품, 주문 + +2. 속성(Attribute): 개체가 가지는 정보. 예) 회원ID, 이름, 가격 + +3. 관계(Relationship): 개체와 개체 사이의 연관성. 예) 회원은 주문을 한다 + +## ERD의 역할 + +데이터베이스 구조를 설계할 때 전체 구조를 한눈에 파악할 수 있다. + +테이블 생성 전에 개체와 관계를 미리 정리할 수 있다. + +개발자, 기획자, 설계자 사이의 의사소통 도구로 활용된다. + +정리하면 ERD는 데이터베이스 설계도라고 볼 수 있다. + +# 3. 연관관계란? 그리고 연관관계를 설정하는 방법은? + +연관관계는 하나의 개체 또는 릴레이션이 다른 개체 또는 릴레이션과 서로 관련을 맺고 있는 상태를 의미한다. +개체 간의 연결 구조를 파악하고 표현하는 것이 연관관계이다. + +## 1. 1:1 관계 + +하나의 개체가 다른 하나의 개체와만 연결되는 관계이다. + +예) + +- 한 사람은 하나의 주민등록증을 가진다. +- 하나의 주민등록증은 한 사람에게만 속한다. + +## 2. 1:N 관계 + +하나의 개체가 여러 개의 다른 개체와 연결될 수 있는 관계이다. + +예) + +- 한 고객은 여러 주문을 할 수 있다. +- 한 학과에는 여러 학생이 속할 수 있다. + +## 3. N:M 관계 + +여러 개체가 서로 여러 개체와 연결될 수 있는 관계이다. + +예) + +- 한 학생은 여러 과목을 수강할 수 있다. +- 하나의 과목은 여러 학생에게 수강될 수 있다. + +--- + +관계형 데이터베이스에서는 이러한 연관관계를 주로 기본키와 외래키를 이용해 설정한다. + +## 1. 1:N 관계 설정 + +1:N 관계에서는 일반적으로 다수 쪽 릴레이션에 외래키를 둔다. + +예를 들어 고객과 주문의 관계에서, 한 고객은 여러 주문을 할 수 있으므로 주문 릴레이션에 고객의 기본키를 외래키로 둔다. + +예) + +- Customer(id, name) +- Order(id, customer_id, order_date) + +여기서 customer_id는 Customer의 기본키를 참조하는 외래키이다. + +## 2. 1:1 관계 설정 + +1:1 관계에서는 한쪽 릴레이션에 외래키를 두고, 그 외래키가 중복되지 않도록 설정하여 관계를 표현할 수 있다. + +예) + +- Person(id, name) +- Passport(id, person_id) + +이 경우 person_id에 UNIQUE 제약을 주면 1:1 관계를 표현할 수 있다. + +## 3. N:M 관계 설정 + +N:M 관계는 관계형 데이터베이스에서 직접 표현하지 않고, 별도의 연결 릴레이션을 만들어 두 개의 1:N 관계로 나누어 표현한다. + +예) + +- Student(id, name) +- Course(id, title) +- Enrollment(student_id, course_id) + +여기서 Enrollment는 학생과 과목을 연결하는 릴레이션이다. + +정리하면 연관관계는 개체와 개체 사이의 관련성을 의미하며, 관계형 데이터베이스에서는 주로 기본키와 외래키를 사용하여 이를 표현한다. + +특히 N:M 관계는 별도의 연결 릴레이션을 통해 구현도니다. + +# 3. 정규화란? + +정규화는 데이터의 중복을 줄이고, 이상 현상을 방지하기 위해 데이터를 구조적으로 분해하는 과정이다. + +정규화를 하는 이유는 하나의 테이블에 너무 많은 정보를 넣으면 데이터 중복이 발생하고, 삽입, 수정, 삭제 과정에서 여러 문제가 생길 수 있기 때문이다. + +## 정규화의 목적 + +- 데이터 중복 최소화 +- 데이터 일관성 유지 +- 이상 현상 방지 +- 데이터 구조의 안정성 향상 + +## 이상 현상의 종류 + +- 삽입 이상: 불필요한 데이터가 없으면 새로운 데이터 삽입이 어려운 현상 +- 수정 이상: 중복된 데이터 중 일부만 수정되어 불일치가 발생하는 현상 +- 삭제 이상: 하나의 정보를 삭제할 때 원하지 않는 다른 정보까지 함께 삭제되는 현상 + +정리해보면 정규화는 데이터를 올바르게 나누어 중복과 이상 현상을 줄이는 과정이다. + +# 4. 반 정규화란? + +반정규화는 정규화된 데이터베이스에서 성능 향상을 위해 일부 중복을 허용하거나 테이블을 다시 합치는 과정이다. + +정규화는 데이터 중복을 줄이고 구조를 안정적으로 만들지만, 테이블이 많이 나뉘면 조회 시 JOIN이 많아져 성능이 떨어질 수 있다. + +이때 조회 성능을 높이기 위해 의도적으로 중복을 허용하거나 구조를 단순화하는 것이 반정규화이다. + +## 반정규화의 목적 + +- 조회 성능 향상 +- JOIN 감소 +- 시스템 응답 속도 개선 + +## 반정규화의 특징 + +- 데이터 중복이 발생할 수 있다. +- 수정 시 일관성 관리가 더 어려워질 수 있다. +- 읽기 성능은 좋아질 수 있지만 쓰기 작업은 불리할 수 있다. + +정리해보면 반정규화는 성능 향상을 위해 정규화된 구조를 일부 완화하는 과정이다. + +# 5. DB에서의 상속 관계 표현은 어떻게 하는가? + +관계형 데이터베이스에는 객체지향 언어처럼 상속 개념이 직접 존재하지 않기 때문에, 테이블 설계를 통해 상속 관계를 간접적으로 표현한다. + +대표적으로는 3가지 방법이 있다. + +## 1. 하나의 테이블로 통합하는 방식 + +부모와 자식의 모든 속성을 하나의 테이블에 저장하는 방식이다. + +예를 들어 사람, 학생, 교수가 있을 때 모든 정보를 하나의 Person 테이블에 넣는 방식이다. + +장점 + +- 테이블 수가 적다 +- 조회가 단순하다 + +단점 + +- 사용하지 않는 컬럼이 많아질 수 있다 +- NULL 값이 많이 생길 수 있다 + +## 2. 부모 테이블과 자식 테이블로 분리하는 방식 + +공통 속성은 부모 테이블에 저장하고, 자식만의 속성은 별도의 자식 테이블에 저장하는 방식이다. + +예) + +- Person(id, name) +- Student(id, grade) +- Professor(id, major) + +장점 + +- 정규화된 구조를 유지할 수 있다 +- 공통 속성과 개별 속성을 명확히 분리할 수 있다 + +단점 + +- 조회할 때 JOIN이 필요하다 + +## 3. 자식마다 독립 테이블을 만드는 방식 + +부모의 공통 속성까지 각 자식 테이블에 모두 포함시키는 방식이다. + +예) + +- Student(id, name, grade) +- Professor(id, name, major) + +장점 + +- 조회가 단순하다 +- 테이블별 독립성이 높다 + +단점 + +- 공통 속성이 중복된다 +- 구조 변경 시 여러 테이블을 함께 수정해야 할 수 있다 + +DB의 상속 관계는 테이블 설계 방식으로 표현하며, 상황에 따라 통합 / 분리 / 중복 방식 중 하나를 선택한다. + +# 6. 인덱스란? + +인덱스는 데이터 검색 속도를 높이기 위해 사용하는 데이터 구조이다. 책의 맨 뒤에 있는 색인처럼, 원하는 데이터를 더 빠르게 찾을 수 있도록 도와준다. + +예를 들어 테이블에 데이터가 매우 많을 때, 인덱스가 없으면 DBMS는 처음부터 끝까지 데이터를 검사해야 할 수 있다. 하지만 인덱스가 있으면 특정 값을 빠르게 찾을 수 있다. + +## 인덱스의 장점 + +- 검색 속도 향상 +- 정렬 및 조건 검색 성능 향상 +- JOIN 성능 향상 가능 + +## 인덱스의 단점 + +- 인덱스를 저장하기 위한 추가 공간이 필요하다 +- INSERT, UPDATE, DELETE 시 인덱스도 함께 관리해야 하므로 성능 저하가 발생할 수 있다 + +## 인덱스를 사용하는 대표적인 경우 + +- WHERE 조건에 자주 사용되는 속성 +- JOIN에 자주 사용되는 속성 +- 정렬(ORDER BY)에 자주 사용되는 속성 + +정리하면 인덱스는 조회 성능을 높이기 위한 구조이지만, 저장 공간과 갱신 비용이 추가로 든다. \ No newline at end of file From cd47500e93f6a3e3743ae714ada953a5b7628be6 Mon Sep 17 00:00:00 2001 From: chazicer Date: Thu, 19 Mar 2026 15:49:23 +0900 Subject: [PATCH 2/5] =?UTF-8?q?keyword:=200=EC=A3=BC=EC=B0=A8=20=EB=AF=B8?= =?UTF-8?q?=EC=85=98=20=EC=A7=84=ED=96=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mission/chapter00/mission.md | 51 ++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 mission/chapter00/mission.md diff --git a/mission/chapter00/mission.md b/mission/chapter00/mission.md new file mode 100644 index 0000000..ac446ae --- /dev/null +++ b/mission/chapter00/mission.md @@ -0,0 +1,51 @@ +## 미션 기록 + +![](https://raw.githubusercontent.com/chazy-d/md-images/main/uploads/20260319153440090.png) + +## 미션 설명 + +IA와 WF를 기준으로, 이번 미션에서 반드시 필요한 로그인/회원가입, 홈, 미션, 리뷰 흐름만을 중심으로 데이터베이스를 설계했다. +지도/검색, 알림, 포인트 관리, 사장님 점포 관리 관련 테이블은 설계 대상에서 제외했다. + +핵심 개체는 사용자, 지역, 약관, 음식 카테고리, 가게, 미션, 리뷰로 선정했고, +회원가입과 미션 진행 흐름에서 필요한 관계를 표현하기 위해 사용자_약관동의, 사용자_선호카테고리, 사용자_미션, 리뷰_이미지 테이블을 추가했다. + +관계는 아래와 같이 정의했다. + +``` + +지역 : 사용자 = 1 : N + +지역 : 가게 = 1 : N + +음식 카테고리 : 가게 = 1 : N +→ 가게가 대표 카테고리 1개만 가진다고 가정 + +사용자 : 약관 = N : M + +사용자 : 음식 카테고리 = N : M + +가게 : 미션 = 1 : N + +사용자 : 미션 = N : M + +사용자 미션 : 리뷰 = 1 : 0..1 + +리뷰 : 리뷰 이미지 = 1 : N + +``` + +특히 사용자_미션(user_missions) 테이블을 중심으로 설계했다. +이 테이블은 사용자와 미션의 N:M 관계를 해소하는 동시에, 사용자가 어떤 미션에 도전했는지와 현재 상태가 진행중 / 성공 요청 / 완료 / 리뷰 작성 완료 중 무엇인지를 관리하는 역할을 한다. +이를 통해 홈 화면의 “내가 받은 미션”, 미션 탭의 진행 상태, 성공 요청, 리뷰 작성 가능 여부를 한 흐름으로 관리할 수 있도록 했다. + +또한 리뷰는 사용자와 가게를 직접 연결하지 않고 사용자_미션을 참조하도록 설계했다. +이렇게 하면 실제로 수행한 미션에 대해서만 리뷰를 남길 수 있고, 어떤 가게의 어떤 미션에 대한 리뷰인지도 자연스럽게 추적할 수 있다. +리뷰는 사용자 미션당 최대 1개만 작성 가능하도록 설계했다. + +회원가입 과정에서 필요한 약관 동의와 선호 음식 선택은 각각 사용자_약관동의, 사용자_선호카테고리 테이블로 분리하여 관리했다. +두 테이블은 별도의 id 없이 각 참조 키의 조합을 복합 기본키로 사용하여 중복 저장을 방지하도록 설계했다. + +포인트 상세 적립/사용 이력은 과제 범위에서 제외했지만, 홈과 마이페이지에서 현재 포인트를 표시할 수 있도록 users 테이블에 current_point 컬럼만 요약값으로 두었다. + +최종적으로는 users, regions, terms, user_term_agreements, food_categories, user_preferred_categories, stores, missions, user_missions, reviews, review_image 총 11개 테이블로 설계했다. \ No newline at end of file From 744ff78ff51cfee9622ec53214ae616babb04aa6 Mon Sep 17 00:00:00 2001 From: chazicer Date: Thu, 19 Mar 2026 20:58:08 +0900 Subject: [PATCH 3/5] =?UTF-8?q?keyword:=201=EC=A3=BC=EC=B0=A8=20=ED=82=A4?= =?UTF-8?q?=EC=9B=8C=EB=93=9C=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- keyword/chapter01/keyword.md | 268 +++++++++++++++++++++++++++++++++++ 1 file changed, 268 insertions(+) create mode 100644 keyword/chapter01/keyword.md diff --git a/keyword/chapter01/keyword.md b/keyword/chapter01/keyword.md new file mode 100644 index 0000000..77a9013 --- /dev/null +++ b/keyword/chapter01/keyword.md @@ -0,0 +1,268 @@ +# DB Join이란? + +DB Join은 두 개 이상의 릴레이션을 공통된 속성을 기준으로 연결하여 하나의 결과로 조회하는 연산이다. + +관계형 데이터베이스에서는 데이터를 하나의 테이블에 모두 저장하지 않고, 여러 테이블로 나누어 저장하는 경우가 많다. + +이때 필요한 데이터를 함께 조회하기 위해 Join을 사용한다. + +![](https://raw.githubusercontent.com/chazy-d/md-images/main/uploads/20260319203224302.png) + +예를 들어 학생 테이블과 동아리 테이블이 따로 존재할 때, 학생이 속한 동아리의 이름과 카테고리를 함께 보고 싶다면 두 테이블을 Join하여 조회할 수 있다. + +즉, Join은 분리되어 저장된 데이터를 다시 연결해서 원하는 형태의 결과를 얻기 위한 방법이라고 볼 수 있다. + +## Join을 사용하는 이유 + +- 여러 릴레이션에 나누어 저장된 데이터를 함께 조회할 수 있다. +- 정규화된 데이터 구조를 유지하면서도 필요한 정보를 한 번에 볼 수 있다. +- 중복 저장을 줄이고, 필요한 시점에 데이터를 조합할 수 있다. + +정리해보면 Join은 관계형 데이터베이스에서 분리된 테이블들을 연결하여 원하는 데이터를 조회하는 연산이다. + +# Join 종류들 + +Join은 데이터를 어떻게 연결할 것인지에 따라 여러 종류로 나뉜다. + +## 1. INNER JOIN + +두 릴레이션에서 조건에 맞는 행만 조회하는 방식이다. + +가장 기본적인 Join이다. + +예를 들어 학생 테이블과 동아리 테이블을 INNER JOIN하면, + +동아리 ID가 서로 일치하는 데이터만 결과에 포함된다. + +즉, 양쪽 테이블에 공통으로 존재하는 데이터만 조회된다. + +--- + +![](https://raw.githubusercontent.com/chazy-d/md-images/main/uploads/20260319204131644.png) + +## 2. LEFT OUTER JOIN + +왼쪽 릴레이션의 데이터는 모두 유지하고, + +오른쪽 릴레이션에서 조건에 맞는 데이터가 있으면 함께 가져오는 방식이다. + +조건에 맞는 오른쪽 데이터가 없으면 그 부분은 NULL로 채워진다. + +즉, 왼쪽 테이블 기준으로 전체를 보고 싶을 때 사용한다. + +--- + +## 3. RIGHT OUTER JOIN + +오른쪽 릴레이션의 데이터는 모두 유지하고, + +왼쪽 릴레이션에서 조건에 맞는 데이터가 있으면 함께 가져오는 방식이다. + +조건에 맞는 왼쪽 데이터가 없으면 그 부분은 NULL로 채워진다. + +즉, 오른쪽 테이블 기준으로 전체를 보고 싶을 때 사용한다. + +--- + +## 4. FULL OUTER JOIN + +양쪽 릴레이션의 데이터를 모두 유지하면서 연결하는 방식이다. + +조건이 맞는 데이터는 하나의 행으로 합쳐지고, + +맞지 않는 데이터는 없는 쪽이 NULL로 채워진다. + +즉, 양쪽 테이블의 전체 데이터를 모두 보고 싶을 때 사용한다. + +다만 MySQL에서는 FULL OUTER JOIN을 직접 지원하지 않기 때문에, + +보통 LEFT JOIN과 RIGHT JOIN 결과를 조합하는 방식으로 구현한다. + +--- + +## 5. CROSS JOIN + +한 릴레이션의 모든 행과 다른 릴레이션의 모든 행을 모두 조합하는 방식이다. + +즉, 가능한 모든 경우의 수를 만드는 Join이다. + +예를 들어 학생 3명과 과목 4개가 있으면 결과는 12행이 된다. + +사용 목적이 분명할 때는 유용하지만, + +데이터 양이 많으면 결과가 매우 커질 수 있으므로 주의해야 한다. + +--- + +## 6. SELF JOIN + +하나의 릴레이션을 자기 자신과 Join하는 방식이다. + +예를 들어 직원 테이블에서 + +직원과 관리자 관계를 같은 테이블 안에서 표현하고 있다면, + +직원 테이블을 자기 자신과 Join하여 직원 이름과 관리자 이름을 함께 조회할 수 있다. + +즉, SELF JOIN은 같은 테이블 안의 데이터들끼리 관계를 표현할 때 사용한다. + +--- + +## 기타 Join 방식 + +### 1. 등가조인 (Equi Join) + +등가조인은 두 릴레이션의 속성 값이 서로 같은 경우를 조건으로 연결하는 Join이다. + +즉, `=` 연산자를 사용하여 조인하는 가장 일반적인 형태이다. + +예) + +`Student.club_id = Club.club_id` + +정리하면 등가조인은 같은 값을 기준으로 연결하는 Join이다. + +--- + +### 2. 비등가조인 (Non-Equi Join) + +비등가조인은 =`이 아닌 비교 연산자(`<`,` >`,` BETWEEN` 등)를 사용하여 연결하는 Join이다. + +예를 들어 점수 테이블과 등급 테이블을 조인할 때, + +점수가 특정 범위 안에 속하는지에 따라 등급을 매기는 경우 비등가조인을 사용할 수 있다. + +정리하면 비등가조인은 값의 범위나 크기 비교를 기준으로 연결하는 Join이다. + +--- + +### 3. 자연조인 (Natural Join) + +자연조인은 이름이 같고 의미도 같은 속성을 자동으로 찾아 조인하는 방식이다. + +즉, 두 릴레이션에 공통된 속성이 있으면 이를 기준으로 자동으로 연결한다. + +다만 어떤 컬럼이 기준이 되는지 명시적으로 드러나지 않아, 실무에서는 가독성과 안정성 때문에 명시적인 JOIN을 더 많이 사용한다. + +정리하면 자연조인은 공통 속성을 자동으로 기준 삼아 연결하는 Join이다. + + + +# 트랜잭션이란? + +트랜잭션은 데이터베이스에서 하나의 논리적 작업 단위로 묶어서 처리하는 연산의 집합이다. + +즉, 여러 개의 SQL문이 하나의 작업을 이루는 경우 그 전체를 하나의 단위로 보고 처리하는 것이다. + +예를 들어 계좌 이체를 생각해보면, + +1. A 계좌에서 돈을 출금하고 +2. B 계좌에 돈을 입금해야 한다. + +이 두 작업은 반드시 함께 처리되어야 한다. 출금만 되고 입금이 되지 않으면 데이터가 잘못된 상태가 된다. + +이처럼 트랜잭션은 모두 수행되거나, 모두 수행되지 않아야 하는 작업 단위이다. + +## 트랜잭션의 특징 + +트랜잭션은 보통 ACID라는 네 가지 특성을 만족해야 한다. + +![](https://raw.githubusercontent.com/chazy-d/md-images/main/uploads/20260319204642584.png) + +### 1. 원자성 (Atomicity) + +트랜잭션에 포함된 작업은 모두 실행되거나 모두 실행되지 않아야 한다. + +즉, 일부만 수행되고 나머지가 실패하는 것은 허용되지 않는다. + +--- + +### 2. 일관성 (Consistency) + +트랜잭션 실행 전과 후에 데이터베이스는 항상 일관된 상태를 유지해야 한다. + +즉, 트랜잭션이 끝난 뒤에도 잘못된 데이터 상태가 남아 있으면 안 된다. + +--- + +### 3. 격리성 (Isolation) + +동시에 여러 트랜잭션이 실행되더라도, 각 트랜잭션은 서로 간섭받지 않고 독립적으로 수행되는 것처럼 보여야 한다. + +즉, 다른 트랜잭션의 중간 결과 때문에 잘못된 결과가 나오면 안 된다. + +--- + +### 4. 지속성 (Durability) + +트랜잭션이 성공적으로 완료되면, 그 결과는 영구적으로 저장되어야 한다. + +즉, 완료 후 시스템 장애가 발생하더라도 변경된 내용이 유지되어야 한다. + +정리해보면 트랜잭션은 여러 작업을 하나의 단위로 처리하여 데이터의 정확성과 안정성을 보장하는 개념이다. + +# Join on 과 where의 차이점 + +Join에서 `ON`과 `WHERE`는 모두 조건을 작성할 때 사용되지만, 역할이 서로 다르다. + +## 1. ON + +`ON`은 두 릴레이션을 어떤 조건으로 연결할 것인지를 지정하는 부분이다. + +즉, Join의 기준이 되는 조건을 작성한다. + +예) + +``` +SELECT* +FROM Student s +JOIN Club c +ON s.club_id= c.club_id; +``` + +여기서 `s.club_id = c.club_id`는 + +학생과 동아리를 어떤 기준으로 연결할지 결정하는 조건이다. + +--- + +## 2. WHERE + +`WHERE`는 Join이 이루어진 후, + +조회 결과에서 어떤 행을 걸러낼 것인지를 지정하는 부분이다. + +즉, 결과 집합에 대한 필터 역할을 한다. + +예) + +``` +SELECT* +FROM Student s +JOIN Club c +ON s.club_id= c.club_id +WHERE c.category='스터디'; +``` + +여기서 `WHERE c.category = '스터디'`는 Join 결과 중에서 스터디 카테고리에 해당하는 행만 남기는 조건이다. + +--- + +## ON과 WHERE의 차이 + +- `ON`은 테이블 간 연결 조건 +- `WHERE`는 연결된 결과에 대한 필터 조건 + +느낌이다. + +--- + +## OUTER JOIN에서 중요한 이유 + +INNER JOIN에서는 `ON`과 `WHERE`의 차이가 크게 느껴지지 않아 체감이 안될수 있다. 하지만 OUTER JOIN에서는 차이가 중요하다. + +예를 들어 LEFT JOIN에서 오른쪽 테이블 조건을 `WHERE`에 넣으면, NULL인 행이 제거되어 결과가 INNER JOIN처럼 바뀔 수 있다. + +따라서 OUTER JOIN에서는 연결 조건은 ON에 쓰고, 최종 결과를 제한하는 조건만 WHERE에 쓰는 것이 중요하다. + +정리해보면 `ON`은 Join의 연결 기준, `WHERE`는 Join 결과의 필터 조건이다. \ No newline at end of file From b534415eb91e1e6d63e86e10d1b1db2417ef9a5d Mon Sep 17 00:00:00 2001 From: chazicer Date: Thu, 19 Mar 2026 21:02:52 +0900 Subject: [PATCH 4/5] =?UTF-8?q?keyword:=201=EC=A3=BC=EC=B0=A8=20=ED=82=A4?= =?UTF-8?q?=EC=9B=8C=EB=93=9C=20=EC=A0=95=EB=A6=AC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- keyword/chapter01/keyword.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/keyword/chapter01/keyword.md b/keyword/chapter01/keyword.md index 77a9013..f3dd339 100644 --- a/keyword/chapter01/keyword.md +++ b/keyword/chapter01/keyword.md @@ -1,4 +1,4 @@ -# DB Join이란? +# 1. DB Join이란? DB Join은 두 개 이상의 릴레이션을 공통된 속성을 기준으로 연결하여 하나의 결과로 조회하는 연산이다. @@ -20,7 +20,7 @@ DB Join은 두 개 이상의 릴레이션을 공통된 속성을 기준으로 정리해보면 Join은 관계형 데이터베이스에서 분리된 테이블들을 연결하여 원하는 데이터를 조회하는 연산이다. -# Join 종류들 +# 2. Join 종류들 Join은 데이터를 어떻게 연결할 것인지에 따라 여러 종류로 나뉜다. @@ -126,7 +126,7 @@ Join은 데이터를 어떻게 연결할 것인지에 따라 여러 종류로 ### 2. 비등가조인 (Non-Equi Join) -비등가조인은 =`이 아닌 비교 연산자(`<`,` >`,` BETWEEN` 등)를 사용하여 연결하는 Join이다. +비등가조인은 =이 아닌 비교 연산자(<, >, BETWEEN 등)를 사용하여 연결하는 Join이다. 예를 들어 점수 테이블과 등급 테이블을 조인할 때, @@ -148,7 +148,7 @@ Join은 데이터를 어떻게 연결할 것인지에 따라 여러 종류로 -# 트랜잭션이란? +# 3. 트랜잭션이란? 트랜잭션은 데이터베이스에서 하나의 논리적 작업 단위로 묶어서 처리하는 연산의 집합이다. @@ -201,7 +201,7 @@ Join은 데이터를 어떻게 연결할 것인지에 따라 여러 종류로 정리해보면 트랜잭션은 여러 작업을 하나의 단위로 처리하여 데이터의 정확성과 안정성을 보장하는 개념이다. -# Join on 과 where의 차이점 +# 4. Join on 과 where의 차이점 Join에서 `ON`과 `WHERE`는 모두 조건을 작성할 때 사용되지만, 역할이 서로 다르다. From cb61acd14e211dd5b8c91314a124b80889c7925b Mon Sep 17 00:00:00 2001 From: chazicer Date: Thu, 19 Mar 2026 23:03:02 +0900 Subject: [PATCH 5/5] =?UTF-8?q?mission:=201=EC=A3=BC=EC=B0=A8=20=EB=AF=B8?= =?UTF-8?q?=EC=85=98=20=EC=A7=84=ED=96=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mission/chapter01/mission.md | 153 +++++++++++++++++++++++++++++++++++ 1 file changed, 153 insertions(+) create mode 100644 mission/chapter01/mission.md diff --git a/mission/chapter01/mission.md b/mission/chapter01/mission.md new file mode 100644 index 0000000..f608f15 --- /dev/null +++ b/mission/chapter01/mission.md @@ -0,0 +1,153 @@ +## 미션 기록 + +### 이전 ERD 설계 수정 + +![](https://raw.githubusercontent.com/chazy-d/md-images/main/uploads/20260319224601134.png) + +마이페이지 와이어프레임에는 닉네임, 이메일, 전화번호가 표시되므로, 이를 조회할 수 있도록 users 테이블에 nickname, email, phone_number 속성을 추가했다. + +### 1. 리뷰 작성하는 쿼리 +![](https://raw.githubusercontent.com/chazy-d/md-images/main/uploads/20260319223506847.png) + +```sql +INSERT INTO reviews ( + user_mission_id, + rating, + content, + created_at, + updated_at +) +VALUES ( + :user_mission_id, + :rating, + :content, + NOW(), + NOW() +); +``` +리뷰 작성 화면에서 사용자가 별점과 리뷰 내용을 입력한 뒤 저장 버튼을 눌렀을 때 실행되는 쿼리이다. +reviews 테이블에 user_mission_id, rating, content를 저장하여 어떤 미션 수행에 대한 리뷰인지 연결되도록 설계했다. +사진 첨부 기능은 제외했기 때문에, 리뷰 이미지 관련 테이블은 사용하지 않았다. + +리뷰 등록 후 user_missions의 상태를 REVIEWED로 변경하는 로직도 함께 처리할 수 있을 것 같다. + + +### 2. 내가 진행중, 진행 완료한 미션 모아서 보는 쿼리(페이징 포함) + +![](https://raw.githubusercontent.com/chazy-d/md-images/main/uploads/20260319223734745.png) + +```sql +SELECT + um.user_mission_id, + um.status, + um.challenged_at, + um.completed_at, + m.mission_id, + m.mission_content, + m.reward_point, + s.store_id, + s.name AS store_name +FROM user_missions um + JOIN missions m + ON m.mission_id = um.mission_id + JOIN stores s + ON s.store_id = m.store_id +WHERE um.user_id = :user_id + AND ( + (:tab_type = 'IN_PROGRESS' AND um.status IN ('IN_PROGRESS', 'SUCCESS_REQUESTED')) + OR + (:tab_type = 'COMPLETED' AND um.status IN ('COMPLETED', 'REVIEWED')) + ) +ORDER BY COALESCE(um.completed_at, um.challenged_at) DESC + LIMIT :page_size OFFSET :offset; +``` + +사용자가 미션 탭에서 현재 진행 중인 미션과 완료한 미션을 구분하여 조회할 수 있도록 작성한 쿼리이다. +user_missions를 중심으로 missions, stores를 조인하여 미션 내용, 보상 포인트, 가게 이름을 함께 조회한다. +:tab_type 값에 따라 진행 중(IN_PROGRESS, SUCCESS_REQUESTED) 또는 완료(COMPLETED, REVIEWED) 상태의 미션만 조회하도록 조건을 분리했다. +또한 LIMIT과 OFFSET을 사용하여 페이지 단위로 데이터를 불러올 수 있도록 페이징 처리를 적용했다. + +### 3. 마이 페이지 화면 쿼리 + +![](https://raw.githubusercontent.com/chazy-d/md-images/main/uploads/20260319223746788.png) + +```sql +SELECT + u.user_id, + u.nickname, + u.email, + u.phone_number, + u.current_point, + u.created_at, + r.name AS region_name +FROM users u + JOIN regions r + ON r.region_id = u.region_id +WHERE u.user_id = :user_id; +``` + +마이페이지 화면에서 사용자 기본 정보를 조회하기 위한 쿼리이다. +users 테이블에서 닉네임, 이메일, 전화번호, 현재 포인트, 가입일을 조회하고, regions 테이블과 조인하여 사용자가 속한 지역명도 함께 가져오도록 했다. +이를 통해 마이페이지에서 사용자 계정 정보와 현재 상태를 한 번에 보여줄 수 있다. + +### 4. 홈 화면 쿼리 (현재 선택된 지역에서 도전이 가능한 미션 목록, 페이징 포함) + +![](https://raw.githubusercontent.com/chazy-d/md-images/main/uploads/20260319223759787.png) + +```sql +// 도전 가능한 미션 목록 +SELECT + m.mission_id, + m.mission_content, + m.reward_point, + s.store_id, + s.name AS store_name +FROM missions m +JOIN stores s + ON s.store_id = m.store_id +WHERE s.region_id = :selected_region_id + AND m.is_active = TRUE + AND NOT EXISTS ( + SELECT 1 + FROM user_missions um + WHERE um.user_id = :user_id + AND um.mission_id = m.mission_id + ) +ORDER BY m.created_at DESC +LIMIT :page_size OFFSET :offset; + +--- + +// 홈 상단 진행도 쿼리 + +SELECT + r.region_id, + r.name AS region_name, + r.mission_goal_count, + COUNT(um.user_mission_id) AS completed_count +FROM regions r + LEFT JOIN stores s + ON s.region_id = r.region_id + LEFT JOIN missions m + ON m.store_id = s.store_id + LEFT JOIN user_missions um + ON um.mission_id = m.mission_id + AND um.user_id = :user_id + AND um.status IN ('COMPLETED', 'REVIEWED') +WHERE r.region_id = :selected_region_id +GROUP BY r.region_id, r.name, r.mission_goal_count; +``` + +도전 가능한 미션 목록 쿼리와 홈 상단 진행도 쿼리를 나누었다. + +#### 1. 도전 가능한 미션 목록 쿼리 설명 + +현재 선택한 지역(:selected_region_id)에 속한 가게들의 미션 중에서, 아직 사용자가 도전하지 않은 미션만 조회하도록 구성했다. +이를 위해 NOT EXISTS를 사용하여 user_missions에 이미 존재하는 미션은 제외했다. +또한 LIMIT과 OFFSET을 사용하여 한 번에 일정 개수의 미션만 불러오도록 페이징 처리하였다. + +#### 2. 홈 상단 진행도 쿼리 설명 + +홈 화면 상단의 진행도(7/10)를 계산하기 위한 쿼리이다. +현재 선택된 지역에 속한 미션 중에서 사용자가 완료한 미션 수를 집계하여 completed_count로 조회하고, regions 테이블의 mission_goal_count와 함께 사용하여 진행도를 표시할 수 있도록 했다. +이를 통해 별도의 진행도 테이블 없이도 지역별 미션 완료 현황을 계산할 수 있다. \ No newline at end of file