포트폴리오/[IoT 기반 피지컬 AI 교육일지]

[ 15일차 기록 ] 조립 PC 재고 관리 프로그램 개발기 #6 (리팩토링 및 안정화)

개발자혜콩 2026. 3. 3. 13:28

1. 오늘 한 내용

  • 소스 코드 모듈화 (Refactoring)
    • 1,000줄 이상의 단일 파일(main.c)을 기능별 5개 소스 파일 및 헤더 파일로 분리.
  • 입력 예외 처리 강화 (Defensive Programming)
    • scanf 오입력(문자/특수기호) 시 발생하는 무한 루프 방지 로직 구현.
  • 데이터 파싱 구조 개선
    • 파일 입출력 시 띄어쓰기 포함 문자열 처리를 위한 구분자 정책 변경.

2. 직면했던 에러 및 해결 과정

(1) [컴파일] 헤더 파일 중복 참조 오류 (Redefinition Error)

  • 원인: 다수의 .c 파일이 하나의 헤더(inventory.h)를 동시에 참조하며 구조체 재정의 충돌 발생.
  • 해결: 전처리기 매크로 #ifndef ~ #endif (Include Guard) 를 적용하여 중복 포함 원천 차단.

(2) [런타임] 입력 버퍼 꼬임 (Infinite Loop)

  • 원인: 정수형 입력(%d)에 문자를 입력할 경우, 버퍼에 남은 문자가 계속 읽히며 루프 발생.
#수정 전

int choice;
while (1) {
    printf("메뉴를 선택하세요: ");
    scanf("%d", &choice); // ⚠️ 문자를 입력하면 여기서 무한 반복됨!
    
    if (choice == 0) break;
    // ... 기능 실행 로직 ...
}
  • 해결: 입력 실패 시 getchar()로 개행 문자(\n)가 나올 때까지 버퍼를 비우는 clearBuffer() 유틸리티 함수 제작 및 표준 적용.
#수정 후
//[유틸리티] 입력 버퍼 비우기 함수
void clearBuffer() {
    while (getchar() != '\n'); // 엔터키가 나올 때까지 버퍼를 비움
}

int choice;
while (1) {
    printf("메뉴를 선택하세요: ");
    
    // ✅ 반환값이 1이 아니면(입력 실패 시) 예외 처리 진입
    if (scanf("%d", &choice) != 1) { 
        printf(">> [경고] 숫자만 입력해주세요!\n");
        clearBuffer(); // 🛡️ 버퍼에 남은 문자 제거 (무한 루프 방지)
        continue;      // 루프 처음으로 돌아가 재입력 유도
    }

    if (choice == 0) break;
    // ... 기능 실행 로직 ...
}

 

 

(3) [데이터] 공백 포함 제품명 로드 실패

  • 원인: fscanf가 공백(Space)을 구분자로 인식하여 데이터 밀림 현상 발생.
#수정 전
// [저장] 공백(Space)으로 구분
fprintf(fp, "%d %s %d %d %d\n", p->id, p->name, p->qty, p->cost, p->price);

// [로드] 띄어쓰기 때문에 이름이 잘림!
// 예: "101 Intel Core i5 10 ..." -> 이름에 "Intel"만 들어가고 나머지는 에러
while (fscanf(fp, "%d %s %d %d %d", &id, name, &qty, &cost, &price) != EOF) {
    addProduct(head, id, name, qty, cost, price);
}
  • 해결: 저장 구분자를 공백에서 **파이프(|)**로 변경하고 파싱 로직 수정.
#수정 후
// [저장] 파이프(|) 기호로 명확히 구분
fprintf(fp, "%d|%s|%d|%d|%d\n", p->id, p->name, p->qty, p->cost, p->price);

// [로드] 정규식 포맷 사용: %[^|] -> '|' 문자가 나오기 전까지 문자열로 인식
while (fscanf(fp, "%d|%[^|]|%d|%d|%d", &id, name, &qty, &cost, &price) != EOF) {
    addProduct(head, id, name, qty, cost, price);
}

3. 오늘 배운 핵심 개념

  • 관심사의 분리 (SoC): 코드의 역할(UI, 로직, 데이터)에 따라 파일을 분리하여 유지보수성을 높이는 설계 원칙.
  • 헤더 가드 (Include Guard): 헤더 파일이 여러 번 포함되더라도 컴파일 에러가 나지 않도록 막는 전처리기 기법.
  • 입력 스트림 제어 (Input Stream Handling): 표준 입력 버퍼(stdin)의 동작 원리와 잔여 데이터 처리 방법.

4. 현재 프로그램 진행도

  • 구조 개선 (Refactoring): 100% 완료 (모듈 분리 및 의존성 정리).
  • 안정성 (Stability): 100% 완료 (예외 처리 및 방어 코드 적용).

5. 다음 목표

  • 최종 발표 자료(PPT) 제작 및 발표
  • 취업용 포트폴리오(One-Page) 최종 점검 및 제출.