C 언어로 배열을 사용해 간단한 데이터베이스 구현하기

C 언어는 저수준 메모리 제어와 간결한 문법 덕분에 강력한 프로그래밍 언어로 손꼽힙니다. 이 기사에서는 배열을 활용해 간단한 데이터베이스를 구현하는 방법을 다룹니다. 배열은 정적 데이터 관리에 적합하며, 데이터 입력, 수정, 삭제 등의 기본 연산을 손쉽게 구현할 수 있습니다. 배열 기반 데이터베이스는 구조화된 데이터를 관리하는 첫걸음으로, 프로그래밍 기초를 탄탄히 다지는 데 유용한 주제입니다. C 언어의 배열로 데이터베이스를 직접 구현하며 기초적인 데이터 관리 기술을 익혀봅시다.

데이터베이스란 무엇인가?


데이터베이스는 데이터를 체계적으로 저장하고 관리하는 시스템을 의미합니다. 이는 정보를 효율적으로 검색, 수정, 삭제할 수 있도록 설계되었습니다.

데이터베이스의 기본 개념


데이터베이스는 데이터의 집합으로, 보통 테이블 형식으로 데이터를 저장합니다. 각 행(row)은 개별 레코드를, 각 열(column)은 속성(attribute)을 나타냅니다.

데이터베이스의 필요성


데이터베이스는 다음과 같은 이유로 중요합니다:

  • 효율적 데이터 관리: 데이터를 체계적으로 저장하여 필요할 때 쉽게 접근할 수 있습니다.
  • 데이터 무결성 유지: 중복 데이터를 방지하고, 데이터의 일관성을 유지합니다.
  • 확장 가능성: 데이터의 양이 증가하더라도 구조를 효율적으로 확장할 수 있습니다.

C 언어에서 배열을 사용하여 기본적인 데이터베이스를 구현하면, 데이터베이스의 핵심 개념과 데이터 구조의 설계 원리를 이해하는 데 큰 도움이 됩니다.

C 언어에서 배열을 사용하는 이유

배열의 특징


배열은 동일한 데이터 타입의 요소를 연속적으로 저장하는 자료 구조입니다. 배열을 사용하면 메모리를 효율적으로 관리할 수 있으며, 인덱스를 통해 요소에 빠르게 접근할 수 있습니다.

  • 연속적 메모리 할당: 배열은 메모리에 연속적으로 저장되어 데이터 접근 속도가 빠릅니다.
  • 고정된 크기: 선언 시 크기가 고정되어 있어 메모리 사용이 명확합니다.

데이터 관리에서 배열의 이점


C 언어에서 배열은 데이터베이스 구현에 적합한 이유를 제공합니다:

  • 데이터 저장: 여러 데이터를 정렬된 형태로 저장할 수 있습니다.
  • 빠른 검색: 인덱스를 통해 데이터 요소에 즉각적으로 접근할 수 있습니다.
  • 간단한 구현: 다른 복잡한 자료 구조보다 구현이 간단하여 초보자에게 적합합니다.

배열의 데이터베이스 활용


배열을 사용하면 데이터의 입력, 수정, 삭제, 검색과 같은 기본적인 데이터 관리 작업을 쉽게 수행할 수 있습니다.
예를 들어, 학생 정보를 저장하는 간단한 데이터베이스를 만들 때, 각 학생의 정보를 배열의 인덱스에 맞춰 저장하면 코드가 간결하고 효율적으로 작동합니다.

배열의 이러한 특징들은 데이터베이스 기초를 배우는 데 이상적이며, C 언어로 데이터 구조의 원리를 탐구하는 훌륭한 출발점이 됩니다.

데이터 구조 설계하기

배열 기반 데이터베이스의 구조


배열을 사용한 데이터베이스 설계의 첫 단계는 데이터를 저장할 구조를 정의하는 것입니다. 이 구조는 배열의 각 요소가 어떤 데이터를 포함해야 하는지 결정합니다.

구조체 활용


C 언어에서 구조체는 배열 기반 데이터베이스의 각 요소를 정의하는 데 유용합니다. 예를 들어, 학생 정보를 저장하려면 다음과 같은 구조체를 사용할 수 있습니다:

typedef struct {
    int id;             // 학생 ID
    char name[50];      // 학생 이름
    float grade;        // 학점
} Student;

배열 선언


이제 구조체 배열을 사용하여 데이터베이스를 설계합니다.

#define MAX_STUDENTS 100
Student database[MAX_STUDENTS];

여기서 MAX_STUDENTS는 데이터베이스에 저장할 최대 레코드 수를 정의합니다.

설계 시 고려 사항


배열 기반 데이터베이스를 설계할 때 고려해야 할 점은 다음과 같습니다:

  • 최대 크기 설정: 배열은 고정 크기를 가지므로, 데이터베이스의 예상 크기를 적절히 설정해야 합니다.
  • 유효 데이터 관리: 배열의 크기와 실제 저장된 데이터의 개수를 추적하는 변수를 추가해야 합니다.
  int current_size = 0; // 현재 저장된 데이터 수
  • 데이터 구조 확장성: 배열이 꽉 찼을 경우, 새로운 데이터를 저장하려면 더 큰 배열로 복사하거나 동적 메모리를 사용해야 합니다.

이러한 설계를 통해 배열을 활용한 간단한 데이터베이스를 효율적으로 구현할 수 있습니다.

데이터 입력 및 출력 구현

데이터 입력 기능


배열 기반 데이터베이스에 데이터를 추가하려면 사용자로부터 데이터를 입력받아 배열에 저장하는 기능이 필요합니다. 다음은 데이터 입력을 구현한 코드 예제입니다:

#include <stdio.h>

void addStudent(Student database[], int *current_size) {
    if (*current_size >= MAX_STUDENTS) {
        printf("데이터베이스가 가득 찼습니다.\n");
        return;
    }

    Student new_student;
    printf("학생 ID를 입력하세요: ");
    scanf("%d", &new_student.id);

    printf("학생 이름을 입력하세요: ");
    scanf("%s", new_student.name);

    printf("학생 학점을 입력하세요: ");
    scanf("%f", &new_student.grade);

    database[*current_size] = new_student;
    (*current_size)++;
    printf("학생 정보가 추가되었습니다.\n");
}

데이터 출력 기능


데이터베이스에 저장된 모든 데이터를 출력하는 기능은 다음과 같이 구현할 수 있습니다:

void displayDatabase(const Student database[], int current_size) {
    if (current_size == 0) {
        printf("데이터베이스가 비어 있습니다.\n");
        return;
    }

    printf("ID\t이름\t학점\n");
    for (int i = 0; i < current_size; i++) {
        printf("%d\t%s\t%.2f\n", database[i].id, database[i].name, database[i].grade);
    }
}

데이터 입력과 출력의 흐름


입력과 출력은 아래와 같은 메인 함수에서 관리할 수 있습니다:

int main() {
    Student database[MAX_STUDENTS];
    int current_size = 0;

    int choice;
    do {
        printf("1. 학생 추가\n2. 데이터베이스 출력\n0. 종료\n");
        printf("선택하세요: ");
        scanf("%d", &choice);

        switch (choice) {
            case 1:
                addStudent(database, &current_size);
                break;
            case 2:
                displayDatabase(database, current_size);
                break;
            case 0:
                printf("프로그램을 종료합니다.\n");
                break;
            default:
                printf("잘못된 선택입니다.\n");
        }
    } while (choice != 0);

    return 0;
}

요약


이 코드를 통해 데이터 입력과 출력의 기본적인 기능을 구현할 수 있습니다. 이는 데이터베이스 관리의 핵심적인 부분이며, 배열 기반 데이터베이스의 작동 원리를 이해하는 데 중요한 단계입니다.

데이터 수정과 삭제

데이터 수정 기능


배열에 저장된 데이터를 수정하려면 수정할 데이터를 검색하고, 필요한 필드의 값을 변경하는 기능을 구현해야 합니다.

void modifyStudent(Student database[], int current_size) {
    if (current_size == 0) {
        printf("데이터베이스가 비어 있습니다.\n");
        return;
    }

    int id;
    printf("수정할 학생의 ID를 입력하세요: ");
    scanf("%d", &id);

    for (int i = 0; i < current_size; i++) {
        if (database[i].id == id) {
            printf("새 이름을 입력하세요: ");
            scanf("%s", database[i].name);

            printf("새 학점을 입력하세요: ");
            scanf("%f", &database[i].grade);

            printf("학생 정보가 수정되었습니다.\n");
            return;
        }
    }

    printf("ID %d에 해당하는 학생이 없습니다.\n", id);
}

데이터 삭제 기능


데이터를 삭제하려면 삭제할 데이터를 찾은 후, 배열의 나머지 요소를 이동시켜 빈 자리를 채워야 합니다.

void deleteStudent(Student database[], int *current_size) {
    if (*current_size == 0) {
        printf("데이터베이스가 비어 있습니다.\n");
        return;
    }

    int id;
    printf("삭제할 학생의 ID를 입력하세요: ");
    scanf("%d", &id);

    for (int i = 0; i < *current_size; i++) {
        if (database[i].id == id) {
            for (int j = i; j < *current_size - 1; j++) {
                database[j] = database[j + 1];
            }
            (*current_size)--;
            printf("학생 정보가 삭제되었습니다.\n");
            return;
        }
    }

    printf("ID %d에 해당하는 학생이 없습니다.\n", id);
}

수정과 삭제의 흐름


수정과 삭제는 메인 프로그램에서 메뉴 옵션으로 제공할 수 있습니다.

int main() {
    Student database[MAX_STUDENTS];
    int current_size = 0;

    int choice;
    do {
        printf("1. 학생 추가\n2. 데이터베이스 출력\n3. 학생 정보 수정\n4. 학생 삭제\n0. 종료\n");
        printf("선택하세요: ");
        scanf("%d", &choice);

        switch (choice) {
            case 1:
                addStudent(database, &current_size);
                break;
            case 2:
                displayDatabase(database, current_size);
                break;
            case 3:
                modifyStudent(database, current_size);
                break;
            case 4:
                deleteStudent(database, &current_size);
                break;
            case 0:
                printf("프로그램을 종료합니다.\n");
                break;
            default:
                printf("잘못된 선택입니다.\n");
        }
    } while (choice != 0);

    return 0;
}

요약


수정과 삭제는 배열 기반 데이터베이스의 필수적인 기능으로, 데이터 관리에 유연성을 제공합니다. 이 구현을 통해 데이터를 실시간으로 변경하거나 제거할 수 있으며, 배열 구조의 장단점을 명확히 이해할 수 있습니다.

배열의 한계와 개선점

배열 기반 데이터베이스의 한계


배열은 간단하고 사용이 용이하지만, 데이터베이스 구현에서 다음과 같은 한계가 있습니다:

고정된 크기

  • 배열은 선언 시 크기가 고정됩니다. 데이터가 추가로 필요할 경우, 배열을 확장하는 것이 어렵습니다.
  • 데이터베이스 크기를 예측하지 못하면 메모리 낭비가 발생하거나, 저장 공간이 부족해질 수 있습니다.

삽입 및 삭제의 비효율성

  • 배열에서 데이터를 삭제하거나 중간에 삽입할 경우, 나머지 요소를 이동해야 합니다. 이는 데이터 크기가 커질수록 성능에 영향을 미칩니다.

동적 데이터 관리의 부족

  • 배열은 정적 메모리 할당에 의존하므로, 런타임에 동적으로 메모리를 조정하기 어렵습니다.

배열의 한계를 극복하기 위한 개선점

동적 배열 사용


동적 메모리 할당을 통해 배열의 크기를 유연하게 변경할 수 있습니다. C 언어에서는 mallocrealloc을 활용하여 배열 크기를 조정할 수 있습니다.

Student *database = (Student *)malloc(initial_size * sizeof(Student));
database = (Student *)realloc(database, new_size * sizeof(Student));

연결 리스트로 전환


배열 대신 연결 리스트를 사용하면 삽입 및 삭제 시 이동 비용이 발생하지 않습니다. 이는 데이터 크기가 자주 변하는 경우에 특히 유용합니다.

파일 기반 저장소 추가


데이터를 배열뿐만 아니라 파일에 저장하면 메모리 한계를 극복할 수 있습니다. 데이터는 필요할 때 메모리로 로드되며, 영속성이 보장됩니다.

최적화를 위한 추가 기능

  • 인덱스 활용: 배열에서 데이터를 검색하는 시간을 줄이기 위해 간단한 인덱스 매핑을 추가할 수 있습니다.
  • 다차원 배열 사용: 데이터를 분류 및 정렬하여 관리가 더 쉽도록 개선할 수 있습니다.

요약


배열은 간단한 데이터베이스 설계에 유용하지만, 고정된 크기와 데이터 조작의 비효율성 같은 한계를 가지고 있습니다. 이를 극복하려면 동적 메모리 관리, 연결 리스트, 또는 파일 저장소를 결합한 하이브리드 접근 방식을 고려해야 합니다. 이러한 개선점을 통해 더 확장 가능하고 효율적인 데이터베이스 시스템을 구현할 수 있습니다.

응용 예제: 학생 정보 관리 시스템

학생 정보 관리 프로그램


학생 정보를 배열 기반 데이터베이스로 관리하는 프로그램을 만들어 보겠습니다. 이 프로그램은 학생의 ID, 이름, 학점을 저장하고, 데이터 입력, 출력, 수정, 삭제 기능을 제공합니다.

구조체 정의


학생 정보를 저장하기 위한 구조체를 정의합니다.

typedef struct {
    int id;             // 학생 ID
    char name[50];      // 학생 이름
    float grade;        // 학생 학점
} Student;

주요 기능 구현

  1. 학생 추가
    학생 정보를 입력받아 배열에 저장합니다.
   void addStudent(Student database[], int *current_size) {
       if (*current_size >= MAX_STUDENTS) {
           printf("데이터베이스가 가득 찼습니다.\n");
           return;
       }
       Student new_student;
       printf("학생 ID: ");
       scanf("%d", &new_student.id);
       printf("학생 이름: ");
       scanf("%s", new_student.name);
       printf("학생 학점: ");
       scanf("%f", &new_student.grade);

       database[*current_size] = new_student;
       (*current_size)++;
       printf("학생 추가 완료.\n");
   }
  1. 데이터 출력
    저장된 학생 정보를 출력합니다.
   void displayDatabase(const Student database[], int current_size) {
       if (current_size == 0) {
           printf("데이터베이스가 비어 있습니다.\n");
           return;
       }
       printf("ID\t이름\t학점\n");
       for (int i = 0; i < current_size; i++) {
           printf("%d\t%s\t%.2f\n", database[i].id, database[i].name, database[i].grade);
       }
   }
  1. 학생 수정
    특정 ID를 가진 학생의 정보를 수정합니다.
   void modifyStudent(Student database[], int current_size) {
       int id;
       printf("수정할 학생 ID: ");
       scanf("%d", &id);

       for (int i = 0; i < current_size; i++) {
           if (database[i].id == id) {
               printf("새 이름: ");
               scanf("%s", database[i].name);
               printf("새 학점: ");
               scanf("%f", &database[i].grade);
               printf("수정 완료.\n");
               return;
           }
       }
       printf("학생을 찾을 수 없습니다.\n");
   }
  1. 학생 삭제
    특정 ID를 가진 학생의 데이터를 삭제합니다.
   void deleteStudent(Student database[], int *current_size) {
       int id;
       printf("삭제할 학생 ID: ");
       scanf("%d", &id);

       for (int i = 0; i < *current_size; i++) {
           if (database[i].id == id) {
               for (int j = i; j < *current_size - 1; j++) {
                   database[j] = database[j + 1];
               }
               (*current_size)--;
               printf("삭제 완료.\n");
               return;
           }
       }
       printf("학생을 찾을 수 없습니다.\n");
   }

메인 프로그램


메인 함수는 사용자가 원하는 작업을 선택할 수 있도록 메뉴를 제공합니다.

int main() {
    Student database[MAX_STUDENTS];
    int current_size = 0;

    int choice;
    do {
        printf("1. 학생 추가\n2. 데이터베이스 출력\n3. 학생 정보 수정\n4. 학생 삭제\n0. 종료\n");
        printf("선택하세요: ");
        scanf("%d", &choice);

        switch (choice) {
            case 1:
                addStudent(database, &current_size);
                break;
            case 2:
                displayDatabase(database, current_size);
                break;
            case 3:
                modifyStudent(database, current_size);
                break;
            case 4:
                deleteStudent(database, &current_size);
                break;
            case 0:
                printf("프로그램 종료.\n");
                break;
            default:
                printf("잘못된 선택입니다.\n");
        }
    } while (choice != 0);

    return 0;
}

결과


이 프로그램은 학생 정보를 효율적으로 관리할 수 있는 배열 기반 데이터베이스를 제공합니다. 학생 추가, 수정, 삭제, 출력과 같은 기본 데이터베이스 관리 작업을 쉽게 수행할 수 있습니다.

요약


학생 정보 관리 시스템은 배열을 활용한 데이터베이스 구현의 실제 응용 사례로, 배열의 장점과 한계를 직접 체험하며 C 언어 프로그래밍 실력을 향상시키는 데 유용합니다.

연습 문제: 배열을 사용한 재고 관리 프로그램

과제 설명


배열을 사용하여 간단한 재고 관리 시스템을 구현해 보세요. 이 프로그램은 상품의 ID, 이름, 가격, 수량을 관리하며, 입력, 출력, 수정, 삭제 기능을 포함합니다.

요구사항

  • 구조체 정의: 상품 정보를 저장할 구조체를 작성하세요.
  • 데이터 입력: 사용자로부터 상품 정보를 입력받아 배열에 추가합니다.
  • 데이터 출력: 현재 배열에 저장된 모든 상품 정보를 출력합니다.
  • 데이터 수정: 특정 상품의 정보를 수정합니다.
  • 데이터 삭제: 특정 상품의 정보를 배열에서 삭제합니다.

구조체 예시

typedef struct {
    int id;             // 상품 ID
    char name[50];      // 상품 이름
    float price;        // 상품 가격
    int quantity;       // 상품 수량
} Product;

프로그램 설계

  1. 메뉴 제공: 사용자에게 수행할 작업(추가, 출력, 수정, 삭제)을 선택할 수 있는 메뉴를 만듭니다.
  2. 입력 기능: addProduct() 함수를 구현하여 상품 정보를 추가합니다.
  3. 출력 기능: displayInventory() 함수로 현재 재고 정보를 출력합니다.
  4. 수정 기능: modifyProduct() 함수로 특정 상품의 정보를 수정합니다.
  5. 삭제 기능: deleteProduct() 함수로 특정 상품을 삭제하고 배열을 정리합니다.

예상 결과


다음과 같은 기능을 가진 프로그램을 작성해야 합니다:

1. 상품 추가  
2. 재고 목록 보기  
3. 상품 정보 수정  
4. 상품 삭제  
0. 종료  

실제 구현 예시

#define MAX_PRODUCTS 100

void addProduct(Product inventory[], int *current_size);
void displayInventory(const Product inventory[], int current_size);
void modifyProduct(Product inventory[], int current_size);
void deleteProduct(Product inventory[], int *current_size);

출력 예

1. 상품 추가
상품 ID: 101
상품 이름: 사과
상품 가격: 1.5
상품 수량: 50
상품이 추가되었습니다.

2. 재고 목록 보기
ID    이름      가격     수량
101   사과      1.50     50

3. 상품 정보 수정
수정할 상품 ID: 101
새 이름: 배
새 가격: 2.0
새 수량: 40
상품 정보가 수정되었습니다.

4. 상품 삭제
삭제할 상품 ID: 101
상품이 삭제되었습니다.

도전 과제

  • 배열의 크기를 동적으로 변경하도록 프로그램을 확장해 보세요.
  • 상품 정보를 파일에 저장하고 다시 로드하는 기능을 추가해 보세요.

요약


이 연습 문제는 배열을 사용해 간단한 데이터베이스 시스템을 설계하고 구현하는 방법을 익히도록 돕습니다. 실습을 통해 배열 기반 데이터 관리의 원리와 실제 응용 능력을 향상시킬 수 있습니다.

요약


이번 기사에서는 C 언어로 배열을 활용해 간단한 데이터베이스를 구현하는 방법을 살펴보았습니다. 데이터베이스의 기본 개념과 배열의 장점, 데이터 입력, 출력, 수정, 삭제 기능을 단계별로 구현하며 배열 기반 데이터 관리의 기초를 다졌습니다.

또한 배열의 한계를 분석하고, 동적 메모리 할당과 연결 리스트 같은 대안도 제시했습니다. 마지막으로 학생 정보 관리 시스템과 연습 문제를 통해 이론과 실습을 접목할 수 있는 기회를 제공했습니다. 이를 통해 배열을 활용한 데이터베이스 설계와 구현 능력을 향상시킬 수 있기를 기대합니다.