# 202221014 - Key-Value Store 구현

- 202221014 이규범

## 개요

C 프로그래밍 언어를 사용하여 간단한 Key-Value Store 프로그램을 직접 구현한다.  
이 프로그램은 데이터베이스에 Key-Value 쌍을 삽입하고, Key-Value 을 검색하고, Key-Value 쌍을 삭제하고, 데이터베이스의 모든 key-value 쌍을 출력한다.

## 프로젝트 목적

- 파일 I/O, 메모리 관리, 데이터 구조 및 오류 처리를 적용한다.
- 간단한 Key-Value Store 프로그램을 설계하고 구현한다.

## 주요 기능

```{note}
기존의 key-Value Store의 명령어는 'kv' 이지만 'Cheju Key-Value Store'를 줄여 'cv'라고 명명한다.
```

### 1. key-value 쌍 삽입

- **명령어:** `cv p,key,value`
- **설명:** 키 `key`에 값 `value`를 삽입한다.
  - `key`는 음이 아닌 정수여야 한다.
  - `value`는 쉼표(,)를 포함하지 않는 임의의 문자열이어야 한다.
- **입력 예시:**
  ```
  cv p,10,Seoul
  cv p,20,Busan
  cv p,30,Incheon
  ```
- **출력 예시:**
  ```
  (입력 명령 실행 후 출력 없음)
  ```

### 2. 키 값 검색

- **명령어:** `cv g,key`
- **설명:** 키 `key`에 대한 값을 검색한다.
  - `key`는 음이 아닌 정수여야 한다.
- **입력 예시:**
  ```
  cv g,10
  cv g,20
  cv g,30
  ```
- **출력 예시:**
  ```
  10,Seoul
  20,Busan
  30,Incheon
  ```

### 3. key-value 쌍 삭제

- **명령어:** `cv d,key`
- **설명:** 키 `key`에 대한 key-value 쌍을 삭제한다.
  - `key`는 음이 아닌 정수여야 한다.
- **입력 예시:**
  ```
  cv d,20
  cv g,20
  ```
- **출력 예시:**
  ```
  K not found (K=20)
  ```

### 4. 데이터베이스 지우기

- **명령어:** `cv c`
- **설명:** 데이터베이스에 저장된 모든 key-value 쌍을 삭제한다.
- **입력 예시:**
  ```
  cv c
  cv a
  ```
- **출력 예시:**
  ```
  database is empty
  ```

### 5. 모든 key-value 쌍 출력

- **명령어:** `cv a`
- **설명:** 데이터베이스에 저장된 모든 key-value 쌍을 출력한다.
- **입력 예시:**
  ```
  cv p,40,Gwangju
  cv a
  ```
- **출력 예시:**
  ```
  10,Seoul
  30,Incheon
  40,Gwangju
  ```

```{admonition} 참고 사항
-예외 처리-
잘못된 명령어: 명령어 형식이 올바르지 않거나 존재하지 않는 명령어를 사용하면 적절한 오류 메시지를 출력한다.
예기치 않은 오류: 파일 I/O 오류, 메모리 할당 오류 등 예기치 않은 오류가 발생하면 적절한 오류 메시지를 출력하고 프로그램을 종료한다.

* key-value 쌍은 `database.txt`라는 파일에 텍스트 형식으로 저장한다.
```

## 사용 기술

주요 기능들을 구현하기 위해 사용될 기술 및 구현 방법에 대한 자세한 내용을 설명한다.

### 1. 파일 I/O

key-value 쌍은 `database.txt`라는 파일에 텍스트 형식으로 저장된다. 따라서 파일 I/O 기술을 사용하여 데이터베이스에 액세스하고 데이터를 저장해야 한다.

- **`fopen()` 및 `fclose()` 함수:** 파일을 열고 닫는 데 사용된다.
- **`fgets()` 및 `fprintf()` 함수:** 파일에 문자열을 읽고 쓰는 데 사용된다.
- **`fscanf()` 및 `fprintf()` 함수:** 파일에서 형식화된 데이터를 읽고 쓰는 데 사용된다.

### 2. 메모리 관리

key-value 쌍을 메모리에 저장하기 위해 적절한 데이터 구조를 사용해야 한다. 일반적으로 다음과 같은 데이터 구조를 사용할 수 있다.

- **배열:** 단순하고 사용하기 쉬운 데이터 구조이지만, key-value 쌍의 개수가 많아질수록 비효율적일 수 있다.
- **연결 리스트:** key-value 쌍을 삽입하고 삭제하는 작업에 효율적이지만, 검색 작업에는 비교적 느릴 수 있다.
- **해시 테이블:** 검색 작업에 매우 효율적이지만, 메모리 할당 및 관리가 더 복잡할 수 있다.

프로그램의 규모와 성능 요구 사항에 따라 적절한 데이터 구조를 선택해야 한다.

### 3. 오류 처리

예상치 못한 오류가 발생할 경우 적절한 오류 메시지를 출력하고 프로그램의 동작에 영향을 미치지 않도록 해야 한다.

- **`errno.h` 헤더 파일:** 시스템 오류 코드를 정의한다.
- **`perror()` 함수:** 시스템 오류 메시지를 출력한다.
- **사용자 정의 오류 메시지:** 프로그램 내에서 발생하는 오류에 대한 메시지를 정의한다.

### 4. 테스트 케이스

프로그램의 기능을 철저히 검증하기 위해 테스트 케이스를 작성해야 한다. 테스트 케이스는 다음과 같은 내용을 포함해야 한다.

- **입력 데이터:** 다양한 유형의 입력 데이터를 포함해야 한다.
- **예상 출력:** 각 입력 데이터에 대한 예상 출력을 정의해야 한다.
- **실제 출력:** 프로그램을 실행하여 실제 출력을 확인해야 한다.

테스트 케이스는 수동으로 실행하거나 자동화 도구를 사용하여 사용한다.

- **예시**: 사용자가 key-value 쌍을 삽입하고, 전체 데이터베이스를 조회한 후, 특정 키에 대한 값 삭제 후 재조회.
- **입력**:
  ```
  cv p,50,Daejeon
  cv a
  cv d,50
  cv g,50
  ```
- **예상 출력**:
  ```
  10,Seoul
  30,Incheon
  40,Gwangju
  50,Daejeon
  K not found (K=50)
  ```
