6주차 실습 - isuho378/2026-1-AI- GitHub Wiki

실습 1. CLaude 시작하기와 첫 대화

첫 프롬프트 입력

원칙 점검

실습 2: 긴 문서 완벽하게 요약하기

6주차-1 교재4장 관계 대수와 SQL1(1~3절)-20260413.pdf


실습 2 심화: 문서 기반 심층 질의응답

질문 패턴 A: 특정 정보 추출

질문 패턴 B: 비판적 사고 훈련

실습 3: 조건이 부여된 복잡한 코드 생성

"""
============================================================
  할 일 관리 프로그램 (To-Do List)
  - Python으로 만든 초보자용 할 일 관리 앱
  - JSON 파일로 데이터를 저장하고 불러옵니다
============================================================
"""

import json       # JSON 파일 읽기/쓰기를 위한 모듈
import os         # 파일 존재 여부 확인을 위한 모듈

# ─────────────────────────────────────────
# 설정값: 저장 파일 이름
# ─────────────────────────────────────────
FILE_NAME = "todos.json"


# ══════════════════════════════════════════
# 1. 파일 불러오기
# ══════════════════════════════════════════
def load_todos():
    """
    JSON 파일에서 할 일 목록을 불러옵니다.
    파일이 없으면 빈 리스트를 반환합니다.

    반환값(return):
        list: 할 일 딕셔너리들의 리스트
              예) [{"id": 1, "task": "공부하기", "done": False}, ...]
    """
    # 파일이 존재하는지 먼저 확인
    if not os.path.exists(FILE_NAME):
        return []  # 파일 없으면 빈 목록 반환

    try:
        # 파일 열기 (읽기 모드, UTF-8 한글 지원)
        with open(FILE_NAME, "r", encoding="utf-8") as f:
            return json.load(f)  # JSON → 파이썬 리스트로 변환
    except json.JSONDecodeError:
        # 파일 내용이 깨졌을 때 처리
        print("⚠️  저장 파일이 손상되었습니다. 새로 시작합니다.")
        return []
    except Exception as e:
        # 그 외 예상치 못한 오류 처리
        print(f"⚠️  파일 불러오기 오류: {e}")
        return []


# ══════════════════════════════════════════
# 2. 파일 저장하기
# ══════════════════════════════════════════
def save_todos(todos):
    """
    할 일 목록을 JSON 파일에 저장합니다.

    매개변수(parameter):
        todos (list): 저장할 할 일 목록
    """
    try:
        with open(FILE_NAME, "w", encoding="utf-8") as f:
            # indent=2: 보기 좋게 들여쓰기
            # ensure_ascii=False: 한글이 깨지지 않도록 설정
            json.dump(todos, f, indent=2, ensure_ascii=False)
    except Exception as e:
        print(f"⚠️  파일 저장 오류: {e}")


# ══════════════════════════════════════════
# 3. 할 일 추가
# ══════════════════════════════════════════
def add_todo(todos):
    """
    새로운 할 일을 목록에 추가합니다.

    매개변수(parameter):
        todos (list): 현재 할 일 목록 (이 함수 안에서 직접 수정됨)
    """
    print("\n[ 할 일 추가 ]")

    # 사용자 입력 받기 (빈 입력 방지)
    task = input("추가할 할 일을 입력하세요: ").strip()

    if not task:
        # 아무것도 입력하지 않은 경우
        print("❌ 할 일 내용을 입력해야 합니다.")
        return

    # 새 항목 딕셔너리 만들기
    # id: 기존 목록 마지막 번호 + 1 (목록이 비어있으면 1부터 시작)
    new_id = todos[-1]["id"] + 1 if todos else 1
    new_todo = {
        "id": new_id,
        "task": task,
        "done": False   # 처음엔 미완료 상태
    }

    todos.append(new_todo)  # 목록에 추가
    save_todos(todos)       # 파일에 저장
    print(f"✅ '{task}' 이(가) 추가되었습니다!")


# ══════════════════════════════════════════
# 4. 목록 보기
# ══════════════════════════════════════════
def view_todos(todos):
    """
    현재 할 일 목록을 화면에 출력합니다.

    매개변수(parameter):
        todos (list): 현재 할 일 목록
    """
    print("\n[ 할 일 목록 ]")
    print("─" * 40)

    # 목록이 비어있는 경우
    if not todos:
        print("  📭 할 일이 없습니다. 새로 추가해보세요!")
        print("─" * 40)
        return

    # 목록 출력
    for todo in todos:
        # 완료 여부에 따라 체크 표시 변경
        status = "✔" if todo["done"] else "○"
        task_text = todo["task"]

        # 완료된 항목은 취소선 느낌으로 표시
        if todo["done"]:
            task_text = f"[완료] {task_text}"

        print(f"  {todo['id']:2}. [{status}] {task_text}")

    print("─" * 40)
    # 완료/전체 통계 출력
    done_count = sum(1 for t in todos if t["done"])
    print(f"  총 {len(todos)}개 중 {done_count}개 완료")


# ══════════════════════════════════════════
# 5. 완료 표시
# ══════════════════════════════════════════
def complete_todo(todos):
    """
    특정 할 일을 완료 상태로 변경합니다.

    매개변수(parameter):
        todos (list): 현재 할 일 목록
    """
    print("\n[ 완료 표시 ]")

    if not todos:
        print("❌ 완료할 항목이 없습니다.")
        return

    view_todos(todos)  # 목록 먼저 보여주기

    try:
        # 번호 입력 받기
        todo_id = int(input("완료할 항목 번호를 입력하세요: "))

        # 입력한 번호와 일치하는 항목 찾기
        for todo in todos:
            if todo["id"] == todo_id:
                if todo["done"]:
                    # 이미 완료된 항목인 경우
                    print(f"ℹ️  '{todo['task']}' 은(는) 이미 완료된 항목입니다.")
                else:
                    todo["done"] = True  # 완료 상태로 변경
                    save_todos(todos)    # 파일 저장
                    print(f"✅ '{todo['task']}' 완료 처리되었습니다!")
                return

        # 해당 번호가 없는 경우
        print(f"❌ {todo_id}번 항목을 찾을 수 없습니다.")

    except ValueError:
        # 숫자가 아닌 값을 입력한 경우
        print("❌ 숫자를 입력해주세요.")


# ══════════════════════════════════════════
# 6. 할 일 삭제
# ══════════════════════════════════════════
def delete_todo(todos):
    """
    특정 할 일을 목록에서 삭제합니다.

    매개변수(parameter):
        todos (list): 현재 할 일 목록
    """
    print("\n[ 할 일 삭제 ]")

    if not todos:
        print("❌ 삭제할 항목이 없습니다.")
        return

    view_todos(todos)  # 목록 먼저 보여주기

    try:
        todo_id = int(input("삭제할 항목 번호를 입력하세요: "))

        # 해당 번호의 항목 찾기
        for todo in todos:
            if todo["id"] == todo_id:
                # 실수로 삭제하는 것을 방지하기 위해 확인
                confirm = input(f"  '{todo['task']}' 을(를) 삭제할까요? (y/n): ").strip().lower()
                if confirm == "y":
                    todos.remove(todo)   # 목록에서 제거
                    save_todos(todos)    # 파일 저장
                    print("🗑️  삭제되었습니다.")
                else:
                    print("↩️  삭제를 취소했습니다.")
                return

        print(f"❌ {todo_id}번 항목을 찾을 수 없습니다.")

    except ValueError:
        print("❌ 숫자를 입력해주세요.")


# ══════════════════════════════════════════
# 7. 메뉴 출력
# ══════════════════════════════════════════
def print_menu():
    """
    사용자에게 선택 메뉴를 출력합니다.
    """
    print("\n" + "═" * 40)
    print("       📝  할 일 관리 프로그램")
    print("═" * 40)
    print("  1. 할 일 추가")
    print("  2. 목록 보기")
    print("  3. 완료 표시")
    print("  4. 할 일 삭제")
    print("  0. 종료")
    print("─" * 40)


# ══════════════════════════════════════════
# 8. 메인 함수 (프로그램 진입점)
# ══════════════════════════════════════════
def main():
    """
    프로그램의 시작점입니다.
    메뉴를 반복 출력하고 사용자 선택에 따라 기능을 실행합니다.
    """
    print("\n🎉 할 일 관리 프로그램을 시작합니다!")

    # 프로그램 시작 시 저장된 파일 불러오기
    todos = load_todos()
    print(f"  → 저장된 항목 {len(todos)}개를 불러왔습니다.")

    # 메인 루프: 사용자가 0(종료)을 선택할 때까지 반복
    while True:
        print_menu()  # 메뉴 출력

        choice = input("메뉴를 선택하세요 (0~4): ").strip()

        # 선택에 따라 해당 함수 실행
        if choice == "1":
            add_todo(todos)
        elif choice == "2":
            view_todos(todos)
        elif choice == "3":
            complete_todo(todos)
        elif choice == "4":
            delete_todo(todos)
        elif choice == "0":
            print("\n👋 프로그램을 종료합니다. 수고하셨습니다!")
            break   # while 루프 종료
        else:
            # 0~4 이외의 입력 처리
            print("❌ 0~4 사이의 숫자를 입력해주세요.")


# ─────────────────────────────────────────
# 이 파일이 직접 실행될 때만 main() 호출
# (다른 파일에서 import 될 때는 실행 안 됨)
# ─────────────────────────────────────────
if __name__ == "__main__":
    main()

실습 3 심화: 시니어 개발자 수준의 코드 리뷰

Mission 1: 객체지향(OOP) 리팩토링 요청


"""
============================================================
  할 일 관리 프로그램 (To-Do List) - OOP 버전
  
  [클래스 구조]
  ┌─────────────────────────────────────┐
  │  TodoItem                           │  ← 할 일 1개를 표현하는 클래스
  │    - id, task, done                 │
  │    - complete(), to_dict(), __str__ │
  ├─────────────────────────────────────┤
  │  TodoManager                        │  ← 목록 전체를 관리하는 클래스
  │    - todos, file_name               │
  │    - add(), delete(), complete()    │
  │    - save(), load(), view()         │
  ├─────────────────────────────────────┤
  │  TodoApp                            │  ← UI/메뉴를 담당하는 클래스
  │    - manager                        │
  │    - run(), print_menu()            │
  └─────────────────────────────────────┘
============================================================
"""

import json
import os


# ══════════════════════════════════════════════════════════
# 클래스 1: TodoItem
# - "할 일 한 개"를 표현하는 클래스
# - 데이터(속성)와 그 데이터를 다루는 행동(메서드)을 함께 묶음
# ══════════════════════════════════════════════════════════
class TodoItem:
    """
    할 일 항목 하나를 표현하는 클래스.

    속성(Attributes):
        id   (int) : 고유 번호
        task (str) : 할 일 내용
        done (bool): 완료 여부 (기본값: False)
    """

    def __init__(self, id: int, task: str, done: bool = False):
        """
        TodoItem 객체를 생성합니다.

        매개변수:
            id   (int) : 고유 번호
            task (str) : 할 일 내용
            done (bool): 완료 여부 (기본값: False)
        """
        self.id   = id
        self.task = task
        self.done = done

    # ──────────────────────────────────
    # 메서드: 완료 처리
    # ──────────────────────────────────
    def complete(self):
        """
        이 할 일 항목을 완료 상태로 변경합니다.
        이미 완료된 경우 False를 반환해 호출자에게 알립니다.

        반환값:
            bool: 완료 처리에 성공하면 True, 이미 완료였으면 False
        """
        if self.done:
            return False   # 이미 완료 상태
        self.done = True
        return True        # 완료 처리 성공

    # ──────────────────────────────────
    # 메서드: 딕셔너리로 변환 (JSON 저장용)
    # ──────────────────────────────────
    def to_dict(self) -> dict:
        """
        이 객체를 딕셔너리 형태로 변환합니다.
        JSON 파일에 저장할 때 사용합니다.

        반환값:
            dict: {"id": ..., "task": ..., "done": ...}
        """
        return {
            "id":   self.id,
            "task": self.task,
            "done": self.done
        }

    # ──────────────────────────────────
    # 메서드: 딕셔너리 → 객체 변환 (JSON 불러오기용)
    # @classmethod: 객체 없이 클래스 이름으로 직접 호출 가능
    # ──────────────────────────────────
    @classmethod
    def from_dict(cls, data: dict) -> "TodoItem":
        """
        딕셔너리를 TodoItem 객체로 변환합니다.
        JSON 파일에서 불러올 때 사용합니다.

        사용 예:
            item = TodoItem.from_dict({"id": 1, "task": "공부", "done": False})

        반환값:
            TodoItem: 새 객체
        """
        return cls(
            id   = data["id"],
            task = data["task"],
            done = data.get("done", False)  # done 키가 없으면 기본값 False
        )

    # ──────────────────────────────────
    # 메서드: 출력 형식 정의
    # __str__: print(item) 할 때 자동으로 호출됨
    # ──────────────────────────────────
    def __str__(self) -> str:
        """
        할 일 항목을 사람이 읽기 좋은 문자열로 반환합니다.

        반환 예:
            "  1. [✔] [완료] 공부하기"
            "  2. [○] 운동하기"
        """
        status    = "✔" if self.done else "○"
        task_text = f"[완료] {self.task}" if self.done else self.task
        return f"  {self.id:2}. [{status}] {task_text}"


# ══════════════════════════════════════════════════════════
# 클래스 2: TodoManager
# - 할 일 목록 전체를 관리하는 클래스
# - 추가/삭제/완료/저장/불러오기 등 핵심 비즈니스 로직 담당
# ══════════════════════════════════════════════════════════
class TodoManager:
    """
    할 일 목록 전체를 관리하는 클래스.

    속성(Attributes):
        file_name (str)       : JSON 저장 파일 이름
        todos     (list)      : TodoItem 객체들의 리스트
    """

    def __init__(self, file_name: str = "todos_oop.json"):
        """
        TodoManager 객체를 생성하고 파일에서 데이터를 불러옵니다.

        매개변수:
            file_name (str): 저장할 JSON 파일 이름
        """
        self.file_name = file_name
        self.todos: list[TodoItem] = []  # 빈 목록으로 시작
        self.load()                      # 생성과 동시에 파일 불러오기

    # ──────────────────────────────────
    # 내부 헬퍼: 다음 ID 생성
    # (외부에서 직접 호출하지 않도록 _ 접두사 사용)
    # ──────────────────────────────────
    def _next_id(self) -> int:
        """
        새 항목에 부여할 다음 ID를 계산합니다.
        목록이 비어있으면 1, 아니면 마지막 ID + 1

        반환값:
            int: 다음 ID 번호
        """
        return self.todos[-1].id + 1 if self.todos else 1

    # ──────────────────────────────────
    # 내부 헬퍼: ID로 항목 찾기
    # ──────────────────────────────────
    def _find_by_id(self, todo_id: int) -> "TodoItem | None":
        """
        주어진 ID와 일치하는 TodoItem을 찾아 반환합니다.
        없으면 None을 반환합니다.

        매개변수:
            todo_id (int): 찾을 항목의 ID

        반환값:
            TodoItem | None
        """
        for todo in self.todos:
            if todo.id == todo_id:
                return todo
        return None

    # ──────────────────────────────────
    # 메서드: 할 일 추가
    # ──────────────────────────────────
    def add(self, task: str) -> TodoItem:
        """
        새로운 할 일을 목록에 추가하고 저장합니다.

        매개변수:
            task (str): 추가할 할 일 내용

        반환값:
            TodoItem: 새로 생성된 항목
        
        예외:
            ValueError: task가 빈 문자열인 경우
        """
        task = task.strip()
        if not task:
            raise ValueError("할 일 내용이 비어 있습니다.")

        new_item = TodoItem(id=self._next_id(), task=task)
        self.todos.append(new_item)
        self.save()
        return new_item

    # ──────────────────────────────────
    # 메서드: 완료 처리
    # ──────────────────────────────────
    def complete(self, todo_id: int) -> TodoItem:
        """
        특정 ID의 항목을 완료 상태로 변경하고 저장합니다.

        매개변수:
            todo_id (int): 완료 처리할 항목의 ID

        반환값:
            TodoItem: 완료 처리된 항목

        예외:
            KeyError  : 해당 ID가 없는 경우
            ValueError: 이미 완료된 경우
        """
        item = self._find_by_id(todo_id)

        if item is None:
            raise KeyError(f"{todo_id}번 항목을 찾을 수 없습니다.")

        if not item.complete():
            raise ValueError(f"'{item.task}' 은(는) 이미 완료된 항목입니다.")

        self.save()
        return item

    # ──────────────────────────────────
    # 메서드: 삭제
    # ──────────────────────────────────
    def delete(self, todo_id: int) -> TodoItem:
        """
        특정 ID의 항목을 목록에서 삭제하고 저장합니다.

        매개변수:
            todo_id (int): 삭제할 항목의 ID

        반환값:
            TodoItem: 삭제된 항목

        예외:
            KeyError: 해당 ID가 없는 경우
        """
        item = self._find_by_id(todo_id)

        if item is None:
            raise KeyError(f"{todo_id}번 항목을 찾을 수 없습니다.")

        self.todos.remove(item)
        self.save()
        return item

    # ──────────────────────────────────
    # 메서드: JSON 파일에 저장
    # ──────────────────────────────────
    def save(self):
        """
        현재 todos 목록을 JSON 파일에 저장합니다.
        각 TodoItem의 to_dict() 메서드를 활용합니다.
        """
        try:
            data = [item.to_dict() for item in self.todos]
            with open(self.file_name, "w", encoding="utf-8") as f:
                json.dump(data, f, indent=2, ensure_ascii=False)
        except Exception as e:
            print(f"⚠️  저장 오류: {e}")

    # ──────────────────────────────────
    # 메서드: JSON 파일에서 불러오기
    # ──────────────────────────────────
    def load(self):
        """
        JSON 파일에서 데이터를 불러와 TodoItem 객체 리스트로 변환합니다.
        파일이 없으면 조용히 넘어갑니다.
        """
        if not os.path.exists(self.file_name):
            return  # 파일 없으면 그냥 빈 목록 유지

        try:
            with open(self.file_name, "r", encoding="utf-8") as f:
                data = json.load(f)
            # 딕셔너리 → TodoItem 객체로 변환 (from_dict 활용)
            self.todos = [TodoItem.from_dict(d) for d in data]
        except json.JSONDecodeError:
            print("⚠️  저장 파일이 손상되었습니다. 새로 시작합니다.")
            self.todos = []
        except Exception as e:
            print(f"⚠️  불러오기 오류: {e}")
            self.todos = []

    # ──────────────────────────────────
    # 프로퍼티: 통계 정보
    # @property: 메서드를 속성처럼 접근 가능 (괄호 없이 호출)
    # ──────────────────────────────────
    @property
    def total_count(self) -> int:
        """전체 할 일 개수"""
        return len(self.todos)

    @property
    def done_count(self) -> int:
        """완료된 할 일 개수"""
        return sum(1 for item in self.todos if item.done)


# ══════════════════════════════════════════════════════════
# 클래스 3: TodoApp
# - 사용자 인터페이스(UI)와 메뉴를 담당하는 클래스
# - TodoManager를 "사용"하여 실제 작업을 위임
# - 화면 출력·입력 처리만 이 클래스가 담당
# ══════════════════════════════════════════════════════════
class TodoApp:
    """
    사용자 인터페이스를 담당하는 클래스.
    TodoManager를 내부에 보유하여 실제 로직은 위임합니다.

    속성(Attributes):
        manager (TodoManager): 할 일 목록 관리 객체
    """

    def __init__(self):
        """
        TodoApp 객체를 생성합니다.
        내부적으로 TodoManager를 생성하여 데이터를 불러옵니다.
        """
        # TodoManager 객체를 생성 — 파일 불러오기도 자동 실행됨
        self.manager = TodoManager()

    # ──────────────────────────────────
    # 메서드: 메뉴 출력
    # ──────────────────────────────────
    def _print_menu(self):
        """메인 메뉴를 화면에 출력합니다."""
        print("\n" + "═" * 40)
        print("       📝  할 일 관리 프로그램  (OOP)")
        print("═" * 40)
        print("  1. 할 일 추가")
        print("  2. 목록 보기")
        print("  3. 완료 표시")
        print("  4. 할 일 삭제")
        print("  0. 종료")
        print("─" * 40)

    # ──────────────────────────────────
    # 메서드: 목록 출력
    # ──────────────────────────────────
    def _print_todos(self):
        """현재 할 일 목록을 화면에 출력합니다."""
        print("\n[ 할 일 목록 ]")
        print("─" * 40)

        if self.manager.total_count == 0:
            print("  📭 할 일이 없습니다. 새로 추가해보세요!")
        else:
            # TodoItem의 __str__ 메서드가 자동으로 호출됨
            for item in self.manager.todos:
                print(item)

        print("─" * 40)
        print(f"  총 {self.manager.total_count}개 중 "
              f"{self.manager.done_count}개 완료")

    # ──────────────────────────────────
    # 메서드: 할 일 추가 화면
    # ──────────────────────────────────
    def _handle_add(self):
        """할 일 추가 화면을 처리합니다."""
        print("\n[ 할 일 추가 ]")
        task = input("추가할 할 일을 입력하세요: ")

        try:
            new_item = self.manager.add(task)
            print(f"✅ '{new_item.task}' 이(가) 추가되었습니다!")
        except ValueError as e:
            # manager.add()에서 발생한 ValueError 처리
            print(f"❌ {e}")

    # ──────────────────────────────────
    # 메서드: 완료 처리 화면
    # ──────────────────────────────────
    def _handle_complete(self):
        """완료 처리 화면을 처리합니다."""
        print("\n[ 완료 표시 ]")

        if self.manager.total_count == 0:
            print("❌ 완료할 항목이 없습니다.")
            return

        self._print_todos()

        try:
            todo_id = int(input("완료할 항목 번호를 입력하세요: "))
            item = self.manager.complete(todo_id)
            print(f"✅ '{item.task}' 완료 처리되었습니다!")

        except ValueError as e:
            # int() 변환 실패 또는 이미 완료된 경우
            print(f"❌ {e}")
        except KeyError as e:
            # 해당 ID가 없는 경우
            print(f"❌ {e}")

    # ──────────────────────────────────
    # 메서드: 삭제 화면
    # ──────────────────────────────────
    def _handle_delete(self):
        """할 일 삭제 화면을 처리합니다."""
        print("\n[ 할 일 삭제 ]")

        if self.manager.total_count == 0:
            print("❌ 삭제할 항목이 없습니다.")
            return

        self._print_todos()

        try:
            todo_id = int(input("삭제할 항목 번호를 입력하세요: "))
            item = self.manager.delete.__func__  # 먼저 존재 확인
            # 삭제 전 확인
            found = self.manager._find_by_id(todo_id)
            if found is None:
                print(f"❌ {todo_id}번 항목을 찾을 수 없습니다.")
                return

            confirm = input(f"  '{found.task}' 을(를) 삭제할까요? (y/n): ").strip().lower()
            if confirm == "y":
                deleted = self.manager.delete(todo_id)
                print(f"🗑️  '{deleted.task}' 이(가) 삭제되었습니다.")
            else:
                print("↩️  삭제를 취소했습니다.")

        except ValueError:
            print("❌ 숫자를 입력해주세요.")
        except KeyError as e:
            print(f"❌ {e}")

    # ──────────────────────────────────
    # 메서드: 메인 루프 실행
    # ──────────────────────────────────
    def run(self):
        """
        프로그램의 메인 루프를 실행합니다.
        사용자가 0을 입력할 때까지 메뉴를 반복 출력합니다.
        """
        print("\n🎉 할 일 관리 프로그램을 시작합니다! (OOP 버전)")
        print(f"  → 저장된 항목 {self.manager.total_count}개를 불러왔습니다.")

        # 메뉴 선택지와 실행할 메서드를 딕셔너리로 매핑
        # → if/elif 없이 깔끔하게 처리 가능
        menu_actions = {
            "1": self._handle_add,
            "2": self._print_todos,
            "3": self._handle_complete,
            "4": self._handle_delete,
        }

        while True:
            self._print_menu()
            choice = input("메뉴를 선택하세요 (0~4): ").strip()

            if choice == "0":
                print("\n👋 프로그램을 종료합니다. 수고하셨습니다!")
                break

            action = menu_actions.get(choice)  # 딕셔너리에서 함수 가져오기
            if action:
                action()  # 해당 메서드 실행
            else:
                print("❌ 0~4 사이의 숫자를 입력해주세요.")


# ──────────────────────────────────────────
# 프로그램 진입점
# ──────────────────────────────────────────
if __name__ == "__main__":
    # TodoApp 객체 하나 생성 후 실행
    # → 모든 상태(데이터)가 객체 안에 캡슐화됨
    app = TodoApp()
    app.run()

Mission 2: 내 코드 분석 받기

실습 4: ChatGPT vs Claude 블라인드 테스트

테스트 1: 논리적 분석력'

Chat GPT


Claude

테스트 2: 창의적 글쓰기

Chat GPT


Claude

평가

체계성

Chat GPT가 Claude에 비해 배경 설명이나 인과관계가 충분히 드러나지 않아 체계성은 Claude가 더 우세하다

흥미도

Claude의 글은 문장이 항상 ~다. 로 끝나 비교적 단조롭게 느껴진다. Chat GPT는 짧지만 단조롭지않은 문장 구성으로 이미지가 잘 떠오르는 편이다. 흥므도는 Chat GPT가 더 우세하다.

응답스타일

Chat GPT는 간결하고 과한 설명 없이 메시지를 전달하는 방식, Claude는 대화처럼 자연스럽게 짧은 질문엔 짧게 답하고, 복잡한 주제엔 필요한 만큼 답한다.


중간고사 대비 AI활용 과제 및 문의

AI 기술의 진화와 역사 (Week 1~2)

디지털 전환(DX) 3단계:

[Digitization]: 아날로그 정보를 디지털 형태로 변환.

[Digitalization]: 개별 업무 프로세스를 디지털화.

[Digital Transformation]: AI를 통해 비즈니스 모델 자체를 혁신하는 최종 단계.

AI의 역사적 흐름: 1956년 다트머스 회의(AI 용어 탄생) → 두 번의 AI 겨울 → 2012년 AlexNet(딥러닝 시대 개막) → 2022년 ChatGPT(AI 대중화).

기술의 4단계 진화: [규칙 기반] (If-Then) → [머신러닝] (데이터 학습) → [딥러닝] (인공신경망) → [LLM] (거대 언어 모델).


머신러닝과 딥러닝의 이해 (Week 3)

머신러닝의 3가지 학습 방법 지도학습 (Supervised Learning): 정답(Label)이 있는 데이터로 학습합니다. (예: 이미지 분류, 스팸 필터)

비지도학습 (Unsupervised Learning): 정답 없이 데이터의 패턴이나 규칙을 스스로 발견합니다. (예: 고객 군집화, 이상 탐지)

강화학습 (Reinforcement Learning): 행동에 따른 보상과 벌칙을 통해 최적의 방법을 찾아갑니다. (예: 알파고, 자율주행)

딥러닝과 신경망 딥러닝: 인간의 뇌 구조를 모방한 인공신경망을 여러 층(Layer)으로 쌓아 복잡한 패턴을 학습하는 기술입니다.

주요 신경망 구조:

CNN (합성곱 신경망): 이미지 처리에 특화되어 있으며, 사물의 위치가 바뀌어도 인식 가능한 특징이 있습니다.

Transformer: 문장 내 단어 간의 관계를 파악하는 데 강점이 있어 언어 모델의 핵심 기술로 쓰입니다.


LLM(대규모 언어 모델)의 원리 (Week 4)

LLM의 정의 및 특징 수십억 개 이상의 매개변수를 가진 모델로, 방대한 텍스트를 학습하여 다음 단어를 예측하는 방식으로 문장을 생성합니다.

Transformer 아키텍처: 문장 전체를 한 번에 처리하며 '어텐션(Attention)' 메커니즘을 통해 중요한 단어에 집중합니다.

핵심 개념 토큰화(Tokenization): 텍스트를 최소 단위인 토큰으로 나누는 과정입니다. 한국어는 영어보다 토큰을 더 많이 사용하는 경향이 있어 비용과 처리 시간에 영향을 줍니다.

환각(Hallucination): AI가 사실이 아닌 정보를 마치 사실인 것처럼 자신 있게 말하는 현상입니다.

RAG (검색 증강 생성): 외부 데이터베이스에서 정보를 검색하여 응답에 활용함으로써 환각 현상을 줄이는 기술입니다.


ChatGPT 활용 및 프롬프트 엔지니어링 (Week 5)

프롬프트 엔지니어링 5대 원칙 원하는 결과를 얻기 위해 프롬프트를 설계하는 기술입니다.

명확하게: 모호한 표현을 피하고 정확한 지시를 내립니다.

구체적으로: 분량, 형식, 대상 등을 상세히 지정합니다.

맥락 제공: 배경 정보와 현재 상황을 설명합니다.

역할 부여: AI에게 전문가의 페르소나를 부여합니다. (예: "당신은 10년 차 마케터입니다.")

예시 제공 (Few-shot): 원하는 출력 형식의 예시를 1~3개 제공하여 패턴을 파악하게 합니다.

고급 기법 단계별 사고 (Chain-of-Thought): "단계별로 생각해봐"라고 요청하여 복잡한 문제의 정확도를 높입니다.


Claude 활용 및 도구별 비교 (Week 6)

Claude의 특징 Anthropic 사에서 개발하였으며, AI의 안전성과 윤리성을 강조하는 Constitutional AI 기술이 적용되었습니다.

Claude Opus 4.5: 200K 토큰(약 500페이지)의 방대한 컨텍스트 창을 지원하여 긴 문서 분석에 매우 유리하며, 코딩 능력(SWE-bench 1위)이 뛰어납니다.

도구별 선택 가이드 ChatGPT: 창의적 글쓰기, 이미지 생성(DALL-E 3), 풍부한 플러그인 생태계와 한국어 성능이 강점입니다.

Claude: 논리적 분석, 복잡한 코딩, 긴 문서 요약 및 분석, 정직한 답변(모르는 것은 모른다고 인정)이 강점입니다.

Gemini: Google 서비스와의 연동, 실시간 웹 검색 및 멀티모달 기능이 뛰어납니다.


중간고사 대비 예상 문제

Q1. 다음 중 비지도학습의 사례로 가장 적절한 것은? ① 개와 고양이 사진을 구분하는 AI 생성 ② 스팸 메일을 자동으로 분류하는 필터 제작 ③ 쇼핑몰 고객들의 구매 패턴을 분석하여 비슷한 그룹으로 묶기 ④ 체스 게임에서 승리하기 위한 전략 학습

Q2. 프롬프트 엔지니어링에서 'Few-shot Learning'이란 무엇을 의미하나요? (정답: AI에게 원하는 결과의 예시를 몇 가지 제공하여 출력의 품질과 형식을 일관되게 유지하는 기법)

Q3. Claude가 ChatGPT와 비교했을 때 가지는 독보적인 강점 두 가지는? (정답: 긴 문서 분석 능력(대용량 컨텍스트 윈도우)과 높은 수준의 코딩 및 논리적 추론 능력)

Q4. LLM이 거짓 정보를 생성하는 '환각' 현상을 방지하기 위한 기술적 대안은? (정답: RAG - Retrieval-Augmented Generation / 검색 증강 생성)