{
  "version": 4,
  "settings": {
    "heroEyebrow": "Cloud Engineer · Developer",
    "heroLead": "서비스를 만들고,",
    "heroAccent": "안정적으로 운영되는 환경까지 설계합니다.",
    "heroDescription": "사용자의 문제를 코드로 해결해 온 개발 경험을 바탕으로, AWS에서 서비스가 배포되고 운영되는 전체 흐름까지 직접 구현하는 역량을 확장하고 있습니다.",
    "showAchievements": true,
    "heroBadge": "Cloud · Serverless · Automation"
  },
  "profile": {
    "name": "김동현",
    "about": "사용자에게 실질적인 가치를 주는 시스템을 만들고, 유지보수가 쉽고 안정적인 구조를 중요하게 생각합니다. 프론트엔드·백엔드·데이터 처리 경험을 쌓았고, 현재는 AWS를 활용해 서비스가 배포되고 운영되는 전체 흐름을 직접 구현하는 데 집중하고 있습니다.",
    "email": "kimdonghyeon1126@gmail.com",
    "github": "https://github.com/Altlog214608",
    "blog": "https://alt-log.tistory.com/",
    "photo": "images/profile.webp",
    "role": "Cloud Engineer · Developer",
    "resume": ""
  },
  "skillGroups": [
    {
      "title": "Core Development",
      "level": "CORE",
      "kind": "core",
      "description": "프로젝트에서 주로 쓰는 언어와 프레임워크",
      "items": [
        "Python",
        "JavaScript",
        "TypeScript",
        "React",
        "FastAPI",
        "MySQL",
        "Git"
      ]
    },
    {
      "title": "AWS Cloud",
      "level": "IN PRODUCTION",
      "kind": "cloud",
      "description": "KoiCut·PDF→HWPX를 운영하며 직접 설계하고 쓰고 있는 AWS 서비스",
      "items": [
        "Lambda",
        "API Gateway",
        "S3",
        "CloudFront",
        "Route 53",
        "ACM",
        "DynamoDB",
        "SQS",
        "Fargate",
        "ECR",
        "Athena",
        "Glue",
        "CloudWatch",
        "SNS",
        "Cognito",
        "IAM",
        "KMS",
        "Systems Manager",
        "Lightsail"
      ]
    },
    {
      "title": "DevOps & Quality",
      "level": "PRACTICE",
      "kind": "cloud",
      "description": "인프라 코드, 배포 자동화, 테스트와 측정",
      "items": [
        "Terraform",
        "GitHub Actions (OIDC)",
        "Docker",
        "Caddy",
        "systemd",
        "Linux",
        "pytest",
        "Vitest",
        "Playwright",
        "k6"
      ]
    },
    {
      "title": "Backend · Data Experience",
      "level": "EXPERIENCE",
      "kind": "experience",
      "description": "교육과 팀 프로젝트에서 사용해 본 기술",
      "items": [
        "Node.js",
        "Java",
        "Spring Boot",
        "Flask",
        "Spring Data JPA",
        "SQLAlchemy",
        "Pandas",
        "NumPy",
        "OpenCV",
        "PyTorch",
        "Mask R-CNN",
        "Chart.js"
      ]
    }
  ],
  "timeline": [
    {
      "id": "digitalscents",
      "period": "2025.07 ~ 2026.02",
      "title": "소프트웨어 개발 (계약직, 7개월)",
      "subtitle": "디지털센트",
      "description": "Python으로 작성된 기존 소프트웨어의 UI와 기능 리팩토링, 결과를 확인하는 모바일 화면 개발, 기존 소프트웨어를 기반으로 한 신규 향수 소프트웨어 개발"
    },
    {
      "id": "greentech",
      "period": "2024.11 ~ 2025.05",
      "title": "계룡건설 Green Tech SW 개발자 과정",
      "subtitle": "미래융합교육원",
      "description": "Python, Java, Spring Boot, HTML/CSS/JavaScript, MySQL 기반 실무형 개발 교육 및 공공데이터 활용 프로젝트 수행"
    },
    {
      "id": "naver-rush",
      "period": "2023.07 ~ 2023.08",
      "title": "NAVER RUSH 'CLOVA X AI' 팀 프로젝트",
      "subtitle": "팀 프로젝트",
      "description": "AI 기반 데이터 분석 및 시각화 결과를 웹에 구현하고, 명세 작성과 커뮤니케이션을 통해 프로젝트를 재정비한 경험"
    },
    {
      "id": "eagu",
      "period": "2020.03 ~ 2022.11",
      "title": "EAGU 개발 동아리",
      "subtitle": "대전대학교",
      "description": "주간 테스트, 방학 스터디, 자체 세미나와 프로젝트를 통한 협업 및 지식 공유 경험"
    },
    {
      "id": "university",
      "period": "2020.03 ~ 2024.02",
      "title": "정보통신학과",
      "subtitle": "대전대학교",
      "description": "학사 졸업"
    }
  ],
  "projects": [
    {
      "id": "koicut",
      "routeKey": "koicut",
      "title": "KoiCut",
      "category": "AWS · SERVERLESS · WEB",
      "level": "Lv.3",
      "date": "2026.10 ~ 운영 중",
      "order": 0,
      "published": true,
      "featured": true,
      "live": true,
      "description": "사진·영상·음성을 기기와 용도에 맞게 바꾸는 AWS 서버리스 웹 서비스. 쓰지 않을 때 비용이 0에 가까운 구조를 실제 측정값으로 증명했습니다.",
      "highlights": [
        {
          "value": "$0.15",
          "label": "월 AWS 사용 금액"
        },
        {
          "value": "8.7초",
          "label": "변환 처리 p95"
        },
        {
          "value": "0건",
          "label": "부하 테스트 5xx"
        }
      ],
      "role": "1인 개발 · 기획, 아키텍처·비용 설계, Terraform 인프라와 CI/CD, 측정과 기술 결정 기록(ADR) / 코드 구현은 AI 코딩 도구(Claude Code)와 협업",
      "tags": [
        "AWS Lambda",
        "API Gateway",
        "DynamoDB",
        "SQS",
        "CloudFront",
        "Terraform",
        "TypeScript",
        "React",
        "Fargate",
        "Athena",
        "GitHub Actions",
        "Playwright",
        "k6"
      ],
      "github": "https://github.com/Altlog214608/fitcut",
      "demo": "https://koicut.com",
      "image": "images/projects/koicut/card.webp",
      "overview": "폰 배경화면, 워치 페이스, 움짤, 벨소리, 방송 하이라이트를 한 곳에서 만드는 웹 서비스입니다. 기능만큼 중요한 목표는 'AWS 서버리스로 쓰지 않을 때 비용이 0에 가까운 구조를 만들고, 그 근거를 숫자로 남기는 것'이었습니다. 내 도메인(koicut.com, Route 53)에 붙여 실제로 운영하고 있습니다.\n\n주요 기능\n• 사진: 아이폰·갤럭시·폴드·아이패드·워치 등 기기 프리셋 리사이즈·크롭, 여러 기기 한 번에(ZIP), 목표 용량 맞추기, HEIC, AI 업스케일 (브라우저 처리)\n• 움짤·음성·세로 변환: 구간 선택 후 GIF·WebP·MP4, 벨소리(M4R·MP3) (Lambda + ffmpeg)\n• 하이라이트: 치지직 라이브 채팅을 분석해 하이라이트 후보를 찾고 녹화 파일에서 바로 클립으로 (방송 중에만 Fargate)\n• 관리자: 사용 분석, 비용, 감사 로그 (Cognito + MFA)",
      "problem": "미디어 변환 서비스는 보통 상시 켜진 서버나 GPU 인스턴스로 만들어 사용자가 없어도 비용이 나갑니다. 개인 프로젝트로 오래 운영하려면 '쓰지 않을 때는 거의 0원, 쓰는 만큼만 비용'인 구조가 필요했습니다.\n\n목표\n• 상시 과금 리소스 없이(EC2·NAT Gateway·상시 Fargate 0개) 서비스 전체를 구성\n• 작업마다 가장 싼 곳에서 처리: 브라우저 > Lambda > Fargate\n• 비용·처리 시간·부하 한계를 직접 측정하고, 결정 근거를 ADR로 남기기\n• 인프라 전체를 코드(Terraform)로, 배포는 PR·머지만으로",
      "contribution": "설계와 운영 결정\n• 처리 위치 결정: 사진은 브라우저(Web Worker)에서 끝내 서버 비용 0, 영상은 측정 결과 모든 작업이 Lambda 한도 안에 끝나 Fargate 없이 Lambda로\n• 비용 상한을 설계에 포함: IP 해시별 일일 할당량, API 속도 제한, 워커 동시 실행 상한, 입력 크기·길이 제한, S3 수명 주기, Athena 스캔 한도, 월 예산 알림\n• 기술 결정 기록(ADR) 52개 작성\n\n인프라·보안\n• Terraform 모듈 10개, S3 원격 상태, 서울 리전\n• GitHub Actions + AWS OIDC로 plan 역할과 배포 역할 분리, 권한 경계 적용 (장기 액세스 키 없음)\n• 비밀값은 SSM, 스트리머 OAuth 토큰은 KMS로 암호화, 관리자 API는 Cognito 관리자 그룹 + MFA\n• Route 53·ACM(DNS 검증)·CloudFront 별칭까지 코드로, www·cloudfront.net 주소는 CloudFront Function으로 301\n\n개발 방식 (AI 협업)\n• 요구사항과 설계 원칙을 정하고 Claude Code와 함께 구현했으며, 커밋 기록에 AI 공동 작성이 표시되어 있습니다.",
      "implementation": "업로드는 presigned POST로 브라우저에서 S3에 직접 올리고, API Lambda가 잡을 SQS에 넣으면 ffmpeg 컨테이너 이미지 기반 Lambda 워커(arm64)가 처리해 결과를 S3에 저장합니다.\n\n사용 이벤트는 SQS → 배치 Lambda → S3 데이터 레이크로 쌓고, Glue + Athena로 집계해 일별 집계 Lambda가 Cost Explorer 비용과 함께 DynamoDB에 저장합니다. 무료 플랜 제약 때문에 Firehose 대신 SQS + 배치 Lambda, WAF 대신 API 속도 제한을 택했습니다.\n\n하이라이트는 방송이 시작될 때만 Fargate 수집기가 떠서 채팅을 SQS로 보내고, 지연 SQS를 거친 분석 Lambda가 후보 구간 점수를 계산합니다. 수집 중인 방송이 없으면 태스크는 0개입니다.\n\n테스트: Vitest(단위), Playwright(E2E: 데스크톱·Pixel 7·iPhone), k6(부하). PR에서 lint·test·terraform plan, main 머지 시 apply와 배포가 자동으로 실행됩니다.",
      "architecture": "모든 구성 요소는 요청이 있을 때만 비용이 나는 서비스로 골랐습니다. 상시 비용은 Route 53 호스팅 영역 월 $0.50뿐입니다. 관측은 CloudWatch 대시보드 하나와 알람 8개(잡 실패율, 실패 대기열, Lambda 오류, API 5xx)를 무료 한도 안에서 SNS 이메일로 받습니다.",
      "architectureFlows": [
        {
          "label": "웹 · API",
          "nodes": [
            "브라우저",
            "Route 53",
            "CloudFront · ACM",
            "S3 웹 / HTTP API + Lambda",
            "DynamoDB"
          ]
        },
        {
          "label": "변환 잡",
          "nodes": [
            "S3 업로드 (presigned POST)",
            "API Lambda",
            "SQS 잡",
            "Lambda 워커 · ffmpeg",
            "S3 결과"
          ]
        },
        {
          "label": "사용 분석 · 비용",
          "nodes": [
            "SQS 이벤트",
            "배치 Lambda",
            "S3 데이터 레이크",
            "Glue + Athena",
            "일별 집계 Lambda + Cost Explorer"
          ]
        },
        {
          "label": "하이라이트",
          "nodes": [
            "Fargate 수집기 (방송 중에만)",
            "SQS 채팅",
            "Lambda",
            "지연 SQS",
            "분석 Lambda"
          ]
        },
        {
          "label": "관측",
          "nodes": [
            "CloudWatch 알람 8개",
            "SNS 이메일"
          ]
        }
      ],
      "troubleshooting": "부하 테스트에서 503이 25건 발생\n→ 새 계정의 Lambda 동시 실행 기본 한도가 10이었습니다. 한도 상향(1000)을 받은 뒤 다시 측정해 API 초당 30건 요청에서 상한 초과분은 429로 막히고 5xx는 0건, 통과한 요청 p95 39ms를 확인했습니다.\n\n브라우저(ffmpeg.wasm) 변환으로 서버 비용을 없앨 수 있을까\n→ 같은 작업(1080×1920 5초 → GIF)을 비교하니 브라우저는 약 6초 + wasm 30.7MB 다운로드, 멀티 스레드는 탭이 죽었고, 서버는 업로드 1.5초 + 7.5초였습니다. 측정 결과로 서버 처리를 유지했습니다.\n\nLambda 메모리 크기\n→ 1024MB는 2배 느리고 비용은 같았고, 3008MB는 10% 빠르지만 30~40% 비쌌습니다. 2048MB로 정했습니다.",
      "result": "2026-10-01~14 AWS 사용 금액 $0.15(크레딧 적용 전, 청구액 $0)로 운영 중입니다. 가장 큰 항목은 비용을 재는 Cost Explorer API 자체($0.09)였습니다.\n\n• 사진 작업당 서버 비용 $0 (브라우저 처리)\n• GIF 잡당 약 $0.0002, 실제 잡 10건 처리 시간 p50 1.7초 · p95 8.7초\n• 동시 잡 4개 → 워커 상한 2개로 차례로 처리, 최대 4.2초\n\n배운 점\n• '서버리스라서 싸다'가 아니라 처리 위치·메모리·한도를 측정해서 고르는 것이 비용을 결정한다는 것\n• 계정 기본 한도처럼 문서에 잘 보이지 않는 제약은 부하 테스트로만 드러난다는 것\n• 비용 상한과 권한 경계를 처음부터 설계에 넣어야 개인 프로젝트도 안심하고 공개할 수 있다는 것",
      "gallery": [
        {
          "src": "images/projects/koicut/cover.webp",
          "caption": "홈 화면"
        },
        {
          "src": "images/projects/koicut/01.webp",
          "caption": "사진: 기기에 맞춰 자르기"
        },
        {
          "src": "images/projects/koicut/02.webp",
          "caption": "하이라이트: 예시 방송 리플레이"
        },
        {
          "src": "images/projects/koicut/03.webp",
          "caption": "모바일 홈 화면"
        }
      ]
    },
    {
      "id": "pdf-to-hwpx",
      "routeKey": "pdf-to-hwpx",
      "title": "PDF → 한글(HWPX) 변환기",
      "category": "WEB · AWS · DOCUMENT",
      "level": "Lv.3",
      "date": "2026.09 ~ 운영 중",
      "order": 1,
      "published": true,
      "featured": true,
      "live": true,
      "description": "국어 문제집 PDF를 편집 가능한 한글(HWPX) 파일로 바꾸고, AWS Lightsail에서 초대 링크로 운영하는 변환 서비스",
      "highlights": [
        {
          "value": "3만→3,700줄",
          "label": "단계별 재설계"
        },
        {
          "value": "약 1초",
          "label": "문서 1개 변환"
        },
        {
          "value": "60개",
          "label": "자동 테스트"
        }
      ],
      "role": "1인 개발 · 요구사항 정의, 설계 방향, 실사용 피드백 수집과 한글 검증, AWS 배포·운영 / 코드 구현은 AI 코딩 도구(Claude Code)와 협업",
      "tags": [
        "Python",
        "FastAPI",
        "AWS Lightsail",
        "PyMuPDF",
        "HWPX(OWPML)",
        "JavaScript",
        "pytest",
        "Caddy",
        "systemd",
        "GitHub Actions"
      ],
      "github": "https://github.com/Altlog214608/pdf-to-hwpx",
      "demo": "",
      "image": "images/projects/pdf-to-hwpx/card.webp",
      "overview": "현직 국어 강사가 문제집 PDF를 학원 시험지 양식의 한글 파일로 일일이 다시 옮겨 치던 일을 줄이기 위해 만든 변환기와 전용 웹사이트입니다. PDF를 끌어다 놓으면 지문 박스, <보기> 박스, 시의 연 구분, 밑줄, 원문자 선택지, 그림, 표, 정답과 해설까지 구조를 살려 HWPX로 만들고, 학원 이름·로고·시험 제목·글꼴을 미리 보며 정할 수 있습니다.\n\n한글(Hancom) 프로그램 없이 순수 Python으로 HWPX(XML)를 생성하기 때문에 Linux 서버에서 동작하며, AWS Lightsail(서울)에 배포해 초대받은 사용자만 쓰도록 실제로 운영하고 있습니다.\n\n주요 기능\n• 구조 보존 변환: 박스·표(병합 칸, 배경색)·[A] 묶음 괄호·빈칸 네모\n• 정답·해설을 문서 끝에 모으거나 각 문제와 미주로 연결\n• 문제 번호를 한글 문단 번호로 넣어 문제를 추가하거나 붙여 넣으면 번호가 자동으로 이어짐\n• 여러 파일: 대기열로 하나씩 변환해 ZIP/개별 다운로드, 또는 번호를 이어 통합본 하나로(20문제 3개 → 1~60번)\n• 저작권 보호: 업로드 파일은 작업 폴더에만 두고 30분 TTL·페이지 이탈 시 삭제",
      "problem": "처음 버전(v0.1~v0.4)은 3만 줄짜리 단일 파일에서 Windows의 한글 COM 자동화로 문서를 만든 뒤, 버전마다 후처리 코드를 덧붙이는 구조였습니다. 박스 하나의 처리가 실패하면 문서 전체 테두리가 사라지는 연쇄 오류가 났고, 검증기는 'XML 속성이 있는지'만 확인해 띄어쓰기·연 구분 소실 같은 실제 결함을 놓쳤습니다. 서버에 올릴 수도 없었습니다.\n\n목표\n• 한글 프로그램 없이 Linux에서 동작하는 변환 파이프라인으로 다시 설계\n• 특정 PDF 하나에 맞춘 하드코딩이 아니라 좌표(기하) 규칙으로 일반화\n• 결과 품질을 수치로 검증하고, 회귀를 자동 테스트로 막기\n• 비개발자 사용자가 설치 없이 웹에서 쓰도록 배포·운영",
      "contribution": "개발 방식 (AI 협업)\n• 실제 사용자(현직 강사)의 요구와 피드백을 정리해 기능 단위로 요청하고, 결과를 한글에서 직접 열어 검증한 뒤 다시 고치는 주기를 운영했습니다.\n• 코드 구현은 Claude Code와 함께 진행했고, 단계 분리 설계·좌표 기반 일반화·합성 PDF 테스트 같은 원칙을 프로젝트 규칙(CLAUDE.md)으로 정해 결과물을 관리했습니다.\n• AWS 계정·IAM 권한·서울 리전 배포, 컨테이너 서비스 한도 문제 대응 등 운영 결정은 직접 했습니다. 커밋 기록에도 AI 공동 작성이 표시되어 있습니다.\n\n변환 엔진 (pdf2hwpx 패키지, 약 3,700줄)\n• extract: PyMuPDF 글자 좌표로 줄·2단·읽기 순서 재구성, 그림 명령의 선분을 모아 박스·표·괄호를 기하적으로 복원\n• ir: 문제 머리(기대 번호 + 큰 글씨) 판별, 줄 끝 위치로 산문/시 구분, 원문자 아이콘을 이미지 해시와 선택지 순서 투표로 판별\n• hwpx_writer: 한글에서 검증한 header.xml 스타일 id를 재사용하고 변형만 복제, 바탕쪽(머리 부분)·미주·문단 번호·표를 XML로 직접 생성\n• validate: 만든 HWPX를 다시 읽어 원문과 6-gram 반영률·박스 수·문제 순서·표 격자 무결성을 검사\n• merge: 여러 문서를 잇고 문제·정답·지문 안내 번호를 다시 매김\n\n웹 서비스\n• FastAPI 백엔드: 작업 수명 관리(TTL, 페이지 이탈 시 삭제), 시간 제한 다운로드 토큰, 변환 대기열, ZIP/통합본 묶음 API\n• 프런트엔드(바닐라 JS): 화면 전체 드래그 앤 드롭, 원본/HWPX 미리보기, 여러 파일 목록(순서 변경·상태 표시), 어두운 화면\n\n배포·운영\n• 초대 링크 접속 제한, Lightsail 인스턴스 배포 스크립트(PowerShell), 서버 설치 스크립트, GitHub Actions 테스트",
      "implementation": "표 복원: 칸을 이루는 가로/세로 선분을 union-find로 묶어 격자를 만들고, 내부 선이 없는 구간은 병합 칸으로 판단합니다. 칸 배경색은 그리기 순서대로 적용해 덮어쓴 색을 반영합니다.\n\nHWPX 생성: 후처리 패치 없이 IR에서 한 번에 생성합니다. 스타일은 검증된 템플릿의 id를 재사용하고 Styles.derive()로만 변형을 추가해, 한글에서 깨지는 속성값이 생기지 않게 했습니다. 정답 미주는 문제 첫 줄의 1pt 흰 글자 표시에 연결하고, 문제 번호는 한글 문단 번호(heading NUMBER)로 넣어 편집 시 번호가 자동으로 이어지게 했습니다.\n\n검증: 원문 줄마다 6-gram을 만들어 HWPX 글자와 비교하고, 반영률이 낮은 줄과 근본 원인을 앞에서부터 한 줄씩 보고합니다. 실제 문제집 PDF는 저작권 때문에 저장소에 넣지 않고, 같은 특징(박스·표·괄호·아이콘 선택지 등)을 가진 합성 PDF를 코드로 만들어 테스트합니다(합성 PDF·웹 API 테스트 54개와, 실제 문제집 샘플이 있을 때만 도는 회귀 테스트 6개. GitHub Actions에서 자동 실행).\n\n웹: 변환은 서버 전체에서 한 번에 하나씩 처리(Lock 기반 대기열)해 1GB 서버에서도 메모리가 넘치지 않게 했고, 접속 키는 상수 시간 비교와 HttpOnly·Secure 쿠키로 다룹니다.",
      "architecture": "변환 파이프라인: PDF → extract(페이지 모델) → ir(지문·문제·보기·선택지·정답) → hwpx_writer(순수 XML) → validate. 여러 파일은 ir 다음에 merge에서 번호를 다시 매깁니다.\n\n운영: 브라우저(초대 링크 쿠키) → Lightsail 방화벽(22/80/443만) → Caddy(Let's Encrypt 인증서 자동 발급, https://<고정 IP>.sslip.io) → FastAPI(systemd, 127.0.0.1:8000) → 변환 대기열.\n\n처음에는 Lightsail 컨테이너 서비스로 설계했지만 새 계정의 서비스 한도가 0이어서 인스턴스 + Caddy 구성으로 바꿨습니다. 배포 스크립트 한 줄이 서버·고정 IP·방화벽 생성, git archive 업로드, 서버 설치, HTTPS 확인, 사람별 초대 링크 출력까지 처리하고, -Delete로 서버와 고정 IP를 함께 지웁니다.",
      "architectureFlows": [
        {
          "label": "변환 파이프라인",
          "nodes": [
            "PDF",
            "extract",
            "IR",
            "HWPX writer",
            "validate"
          ]
        },
        {
          "label": "운영 · AWS Lightsail",
          "nodes": [
            "Browser · 초대 링크",
            "Lightsail 방화벽 443",
            "Caddy · Let's Encrypt",
            "FastAPI · systemd",
            "변환 엔진"
          ]
        }
      ],
      "troubleshooting": "박스 하나 실패가 문서 전체 테두리 소실로 번짐\n→ 단계별 후처리·롤백 구조를 버리고 IR에서 HWPX를 한 번에 생성하도록 다시 설계했습니다.\n\n표 칸 글자가 표 아래에 한 번 더 출력됨\n→ 표 칸 안의 줄을 본문 읽기 순서에서 빼고, 합성 PDF 테스트에 박스 밖 표를 추가해 회귀를 막았습니다.\n\n표 모양 선택지(머리 ㉠ ㉡ ㉢)의 열이 어긋나고 마지막 열이 줄바꿈됨\n→ 원본 열 위치에 맞춘 테두리 없는 표로 출력하고, 열 폭을 칸 글자 폭 이상으로 넓히되 모자라면 여유 있는 열에서 덜어 오게 했습니다.\n\n여러 파일을 합치면 20번 다음이 다시 1번(사용자 피드백)\n→ 문제 번호를 한글 문단 번호로 바꾸고, 통합본에서는 문제·정답·지문 안내의 글자 번호까지 이어서 다시 매기도록 했습니다.\n\n배포: Docker 빌드 실패, 컨테이너 서비스 한도 0\n→ 같은 이름의 requirements.txt 두 개가 덮어써지던 Dockerfile 버그를 고쳤고, 한도 문제는 인스턴스 + Caddy 자동 HTTPS 구성으로 우회했습니다.",
      "result": "한글 COM에 의존하던 3만 줄 단일 파일을 약 3,700줄의 단계별 패키지로 다시 설계해 Linux 서버에서 1개 문서를 1초 안팎에 변환합니다. 현직 강사가 실제 수업 자료를 만드는 데 쓰고 있고, 사용자의 피드백을 받아 기능을 고치고 배포하는 주기를 직접 운영하고 있습니다.\n\n배운 점\n• 단계 경계를 지키는 설계가 기능 추가와 버그 수정 속도를 얼마나 바꾸는지\n• '검사가 통과했다'가 아니라 원문 대비 수치로 품질을 재야 실제 결함이 보인다는 것\n• 클라우드 계정 한도처럼 설계 밖의 제약에 맞춰 구성을 바꾸고, 배포·삭제를 스크립트로 재현 가능하게 만드는 운영 경험",
      "gallery": [
        {
          "src": "images/projects/pdf-to-hwpx/01.webp",
          "caption": "디자인 설정과 HWPX 미리보기 (여러 파일 목록, 하나로 합치기)"
        },
        {
          "src": "images/projects/pdf-to-hwpx/02.webp",
          "caption": "PDF 올리기 화면 (한 번에 최대 10개)"
        },
        {
          "src": "images/projects/pdf-to-hwpx/03.webp",
          "caption": "파일마다 따로 변환: 대기열로 하나씩 변환 후 ZIP 또는 개별 다운로드"
        },
        {
          "src": "images/projects/pdf-to-hwpx/04.webp",
          "caption": "통합본: 3개 파일 15문제를 1~15번으로 이어 붙이고 구조 검사 통과"
        },
        {
          "src": "images/projects/pdf-to-hwpx/05.webp",
          "caption": "어두운 화면"
        }
      ]
    },
    {
      "id": "ecosolar",
      "routeKey": "ecosolar",
      "title": "EchoSolar",
      "category": "WEB · AI · DATA",
      "level": "Lv.3",
      "date": "2025.03 ~ 2025.05",
      "order": 2,
      "published": true,
      "featured": true,
      "live": false,
      "description": "지도에서 건물을 고르면 AI가 옥상 영역을 찾고, 그 위에 태양광 패널을 배치해 예상 발전량과 탄소 절감 효과를 확인하는 시뮬레이션 플랫폼",
      "highlights": [
        {
          "value": "10,000장",
          "label": "AI 학습 데이터"
        },
        {
          "value": "22→10시간",
          "label": "학습 시간 단축"
        },
        {
          "value": "0.8+",
          "label": "옥상 인식 Score"
        }
      ],
      "role": "3인 팀 · 팀장 · 데이터 수집·전처리(QGIS), 지도 API·AI 서버 연동, 패널 배치 시뮬레이터, 발전량 예측 알고리즘, 일조량 필터, 에너지 대시보드",
      "tags": [
        "React",
        "Spring Boot",
        "Java",
        "Flask",
        "PyTorch",
        "Mask R-CNN",
        "MySQL",
        "QGIS",
        "Chart.js",
        "Python"
      ],
      "github": "https://github.com/Altlog214608/EchoSolar",
      "demo": "",
      "image": "images/projects/ecosolar/card.webp",
      "overview": "교육과정 최종 팀 프로젝트(3인, 팀장)로 진행했습니다. 실제 지도를 기반으로 사용자가 원하는 위치를 선택하면 AI가 해당 이미지 영역을 분석해 옥상 영역을 추론하고, 사용자가 그 위에 태양광 패널을 자유롭게 배치할 수 있도록 설계했습니다. 배치 결과는 지역별 일조량과 표고 데이터를 반영해 예상 발전량을 계산하고, 같은 전기를 화석연료로 만들 때와 비교한 탄소 절감량까지 차트와 수치로 보여 줍니다.\n\n개발 환경: React 18(프론트), Spring Boot 3.4 · Java 21(서버), Flask · PyTorch(AI 서버), MySQL 8.0\n개발 도구: VS Code, IntelliJ, PyCharm, QGIS, Figma, Notion, GitHub",
      "problem": "AI 기술과 이미지 기반 시뮬레이션을 결합해 누구나 쉽고 직관적으로 태양광 패널의 설치 가능 영역과 배치 결과를 확인하고, 발전량을 예측할 수 있는 도구를 만드는 것이 목표였습니다.\n\n주요 목표\n• 사용자 중심 패널 배치·회전·시뮬레이션 인터페이스 제공\n• 실제 환경 기반 발전량 예측\n• 지도·AI·시각화를 통합한 웹 시뮬레이션 플랫폼 구축",
      "contribution": "팀장으로서 데이터 준비부터 지도 · AI 연동 · 시뮬레이션 · 시각화까지, 사용자가 직접 보고 조작하는 흐름 대부분을 맡았습니다.\n\n데이터 수집 · 전처리 (QGIS)\n• AI 학습용 위성 이미지와 행정경계 데이터를 좌표 기반으로 정리\n• 날씨 · 일사량 데이터와 결합해 좌표별 일사량 매핑\n• TIFF 표고 데이터와 행정경계 SHP를 GeoJSON으로 변환\n\n외부 API · AI 서버 연동\n• Naver Maps · VWorld · Kakao Local API를 지도 페이지에 통합\n• '패널 배치 시작' 시 현재 지도 화면을 이미지로 캡처해 Spring 서버를 거쳐 Flask AI 서버로 전송\n• 모델이 돌려준 마스크 · 박스를 Canvas로 지도 위에 시각화\n\n패널 배치 시뮬레이터 · 발전량 예측\n• 드래그, 회전, 크기 조절, 우클릭 삭제 인터랙션\n• 지도 zoom · 중심 좌표로 실제 면적을 계산하고 설치 가능 수 산출\n• 가장 가까운 관측소의 일사량과 표고를 반영한 일/월/년 발전량 예측 알고리즘\n• Chart.js로 결과와 탄소 절감량 시각화\n\n일조량 필터 · 에너지 대시보드\n• 전국 일조량을 시·도 경계 GeoJSON 위에 색 농도로 표시하는 필터\n• 공공데이터 전력 사용량(지역별 · 업종별 · 에너지원별) 시각화",
      "implementation": "AI 모델은 객체의 존재 여부뿐 아니라 픽셀 단위 설치 가능 영역이 필요해 Mask R-CNN(maskrcnn_resnet50_fpn, COCO 사전학습 → 배경/옥상 2클래스 파인튜닝)을 사용했습니다. AI Hub 위성 이미지와 라벨 10,000장으로 50 epoch, batch size 4, SGD(lr 0.005), AMP(Mixed Precision)로 학습해 Train Loss 약 0.21, 검증 이미지 Score 0.8 이상을 얻었습니다. 모델 학습은 팀원이 맡았고, 저는 학습용 데이터와 공간 데이터의 수집·전처리를 담당했습니다.\n\n학습 과정 개선\n• 1,000장 / 30 epoch: epoch 23 이후 Loss가 다시 올라 과적합 → 다음 학습은 25 epoch로 조정\n• 3,000장: batch size 2에서 GPU 메모리 한계 → AMP 적용으로 사용량을 절반으로 줄여 batch size 4로\n• 10,000장 / 50 epoch: 예상 약 22시간 → 최적화 후 약 10시간\n\n전체 서비스 흐름은 지도에서 위치 선택 → React가 지도 화면 캡처 → Spring Boot가 요청을 기록하고 Flask AI 서버로 전달 → Mask R-CNN이 마스크·박스·점수를 JSON으로 반환 → Spring이 처리 시간과 결과를 MySQL에 로그로 저장 → React가 마스크를 지도 위에 그림 → 사용자 패널 배치 → 지역 일조량·표고 보정 → 발전량 계산 및 차트 시각화 순입니다.",
      "architecture": "프론트엔드: React 18, Naver Maps · VWorld(항공·3D 지도) · Kakao Local(장소 검색), Chart.js · Recharts 시각화\n백엔드: Spring Boot 3.4 REST API 게이트웨이(/api/*). AI 요청 중계, 처리 시간 측정, 요청 로그를 Spring Data JPA로 MySQL에 저장\nAI 서버: Flask /predict → Mask R-CNN 추론 → 바운딩 박스 · 마스크 좌표 · 점수 JSON 반환, 추론 로그는 SQLAlchemy로 저장\n데이터: 공공데이터포털(전력 사용량 · 일사량), QGIS로 가공한 시·도 경계 GeoJSON과 표고점",
      "architectureFlows": [
        {
          "label": "AI 옥상 인식",
          "nodes": [
            "React · 지도 캡처",
            "Spring Boot /api/predict",
            "Flask /predict",
            "Mask R-CNN",
            "Spring · MySQL 로그",
            "React · 마스크 표시"
          ]
        },
        {
          "label": "발전량 시뮬레이션",
          "nodes": [
            "패널 배치 (드래그·회전)",
            "면적 계산",
            "관측소 일사량 · 표고 보정",
            "발전량 · 탄소 절감량",
            "Chart.js 결과"
          ]
        }
      ],
      "troubleshooting": "패널 UI 조작의 자연스러운 사용자 경험\n→ 이미지 요소에 이벤트 리스너를 직접 부여하고 좌표 중심 회전 로직과 크기 변경 시 Bounding Box 재계산을 적용해 드래그·회전·삭제·크기 조절을 안정화했습니다.\n\n회전 중심 좌표 문제\n→ 패널 회전 시 중심점이 어긋나는 현상을 getBoundingClientRect() 기준으로 중심 좌표를 다시 계산해 해결했습니다.\n\nAI mask와 실제 지도 면적 차이\n→ 패널 이미지와 mask에 폴리곤 면적 계산을 적용하고 지도 zoom 레벨과 디스플레이 배율에 따라 스케일을 보정해 실제 설치 가능 면적(m²)에 가깝게 추정했습니다.\n\n일사량 지역 범위 모호성\n→ 좌표가 행정구역 경계에 걸릴 경우 가장 가까운 기상 관측소의 평균 일사량을 선택적으로 적용했습니다.",
      "result": "지도 API, AI 분석, 공간 데이터 전처리, 동적 UI, 데이터 시각화를 하나의 서비스 흐름으로 연결하면서 전체 시스템 구조를 직접 이해할 수 있었습니다. 특히 React 프론트엔드, Spring Boot 백엔드, Flask AI 서버 간 데이터 흐름을 구현하면서 각 기술이 서비스 안에서 맡는 역할을 구체적으로 경험했습니다. 기획 → 개발 → 시각화 → 검증 과정을 거치며 실제 서비스 수준의 기능을 고민한 프로젝트입니다.",
      "gallery": [
        {
          "src": "images/projects/ecosolar/07.webp",
          "caption": "EchoSolar 시스템 구조도"
        },
        {
          "src": "images/projects/ecosolar/08.webp",
          "caption": "Mask R-CNN 옥상 인식 예측 결과"
        },
        {
          "src": "images/projects/ecosolar/01.webp",
          "caption": "EchoSolar 인트로 화면"
        },
        {
          "src": "images/projects/ecosolar/02.webp",
          "caption": "전국 전력 사용량 및 에너지 데이터를 시각화한 대시보드"
        },
        {
          "src": "images/projects/ecosolar/03.webp",
          "caption": "지역별 일조량 데이터를 반영한 지도 필터"
        },
        {
          "src": "images/projects/ecosolar/04.webp",
          "caption": "옥상 위 태양광 패널 배치 시뮬레이션 화면"
        },
        {
          "src": "images/projects/ecosolar/05.webp",
          "caption": "주변 건물·지형의 높낮이를 반영한 일조 분석 화면"
        },
        {
          "src": "images/projects/ecosolar/06.webp",
          "caption": "QGIS 기반 공간 데이터 전처리 과정"
        }
      ]
    },
    {
      "id": "erp-mini",
      "routeKey": "erp-mini",
      "title": "ERP mini Project",
      "category": "SYSTEM · BACKEND",
      "level": "Lv.2",
      "date": "2025.02 ~ 2025.03",
      "order": 3,
      "published": true,
      "featured": true,
      "live": false,
      "description": "기업 업무 흐름을 TCP 기반 클라이언트·서버 구조로 재구성한 ERP 미니 프로젝트",
      "highlights": [
        {
          "value": "11명",
          "label": "팀 프로젝트"
        },
        {
          "value": "4개 부서",
          "label": "업무 통합"
        },
        {
          "value": "36개",
          "label": "DB 테이블"
        }
      ],
      "role": "11명 · 입고(receiving.py), 출고(shipping.py), 알림(notification.py) 모듈 전담",
      "tags": [
        "Python",
        "Tkinter",
        "MySQL",
        "TCP Socket",
        "JSON",
        "HTML",
        "CSS",
        "JavaScript"
      ],
      "github": "https://github.com/Altlog214608/ERP_Project",
      "demo": "",
      "image": "images/projects/erp-mini/card.webp",
      "overview": "총 11명이 참여해 기업의 부서 간 업무 흐름을 프로그래밍으로 재구성한 ERP Mini Project입니다. 생산지시, BOM, 자재 입출고, 결재·알림, 회계로 이어지는 흐름을 데이터베이스와 TCP 기반 클라이언트·서버 구조로 연결했습니다.\n\n사용 기술: Python, Tkinter, MySQL, JSON 기반 TCP Socket, JavaScript, HTML/CSS",
      "problem": "부서별로 분리되어 있는 생산·자재·물류·결재 업무를 하나의 ERP 흐름으로 연결하고, 여러 사용자가 동시에 사용하는 환경에서 데이터와 알림을 실시간으로 연계하는 것이 프로젝트의 핵심 과제였습니다.",
      "contribution": "본인 구현 파트\n• 입고 모듈 receiving.py 전담\n• 출고 모듈 shipping.py 전담\n• 알림 UI 및 로직 notification.py 전담\n\n입고 모듈에서는 발주 코드·자재 코드 기준 조회, 구매 오더 자재를 입고 테이블로 이동하고 저장·수정하는 흐름을 구현했습니다. 출고 모듈에서는 생산지시서 기반 출고 대상 조회, 출고 코드·판매 코드 생성, VAT와 총금액 자동 계산을 구현했습니다. 알림 모듈에서는 결재 요청·완료·반려 알림을 실시간으로 표시하고 다단계 결재 흐름과 과거 알림 조회를 구현했습니다.",
      "implementation": "TCP 기반 클라이언트·서버 모델을 사용했습니다. 클라이언트가 code와 args를 포함한 JSON 메시지를 서버로 보내면 tcpHandler.py가 메시지를 받고, msgHandler.py가 code에 따라 기능을 분기합니다. 사용자 접속 상태·채팅방·알림 등 세션 정보는 userManager.py에서 관리하고, DB 작업은 DBManager 계층으로 연결했습니다.\n\n입출고 처리에서는 생산지시서·작업표준서·BOM·자재 테이블을 연동하고, 자재 소모와 완제품 입고 과정에서 트랜잭션을 사용해 데이터 무결성을 유지했습니다. 알림은 요청 코드를 기반으로 수신자의 세션에 실시간 전송하고 승인·반려에 따라 다음 사용자에게 흐름이 이어지도록 구성했습니다.",
      "architecture": "클라이언트 → TCP Server → tcpHandler → msgHandler → userManager / DBManager → MySQL\n\n통신 형식: JSON(code, args)\n데이터베이스 연결: pymysql, 트랜잭션 기반\n화면 구현: Python Tkinter, HTML/CSS",
      "architectureFlows": [
        {
          "label": "시스템 흐름",
          "nodes": [
            "Tkinter Client",
            "TCP / JSON",
            "tcpHandler",
            "msgHandler",
            "userManager",
            "DBManager",
            "MySQL"
          ]
        }
      ],
      "troubleshooting": "",
      "result": "ERP 시스템 내에서 각 부서 간 실시간 데이터 연동 구조를 구현하면서 기업 업무를 기능 단위로 해석하고 연결하는 경험을 했습니다. 입출고와 알림 시스템을 통해 단순 CRUD를 넘어 트랜잭션 제어, 사용자 세션 관리, 요청 코드 분기, 다단계 결재 흐름을 실습했습니다. 실시간 메시징을 위한 소켓 관리와 기능 간 데이터 연결을 경험한 프로젝트입니다.",
      "gallery": [
        {
          "src": "images/projects/erp-mini/01.webp",
          "caption": "메인 대시보드와 결재 알림"
        },
        {
          "src": "images/projects/erp-mini/02.webp",
          "caption": "입고: 생산지시서 기준 조회"
        },
        {
          "src": "images/projects/erp-mini/03.webp",
          "caption": "입고: 구매 오더 자재 조회"
        },
        {
          "src": "images/projects/erp-mini/04.webp",
          "caption": "메신저 패널 (사원 목록 · 채팅방)"
        },
        {
          "src": "images/projects/erp-mini/05.webp",
          "caption": "데이터베이스 테이블 관계 (사원 · 급여 · 채팅)"
        }
      ]
    },
    {
      "id": "medicine-box",
      "routeKey": "medicine-box",
      "title": "스마트 절제 물품 보관함",
      "category": "IOT · HARDWARE",
      "level": "Lv.1",
      "date": "2022 · 창업경진대회",
      "order": 4,
      "published": true,
      "featured": false,
      "live": false,
      "description": "치매 노인의 약물 복용 사고를 예방하기 위해 시간 제어와 알림 기능을 탑재한 스마트 약품 보관함 설계",
      "highlights": [],
      "role": "4인 팀 · 기여도 약 20% · 하드웨어 설계 및 발표자료 제작",
      "tags": [
        "Arduino",
        "IR Sensor",
        "Servo Motor",
        "LCD",
        "Hardware Design"
      ],
      "github": "",
      "demo": "",
      "image": "images/projects/medicine-box/cover.webp",
      "overview": "치매 노인 또는 약물 오남용 가능성이 있는 사용자의 안전한 복약을 돕기 위해, 약 복용 시간에만 보관함이 열리고 그 외 시간에는 잠기도록 설계한 스마트 약품 보관함 프로젝트입니다. 보호자 관점의 상태 확인과 향후 IoT 연동까지 고려해 제품 구조를 기획했습니다.\n\n팀 구성: 4인\n기여도: 약 20% · 하드웨어 설계 및 발표자료 제작 담당",
      "problem": "인지 기능 저하로 약을 중복 복용하거나 복용을 잊는 상황에서 단순 알림만으로는 복약 사고를 막기 어렵다는 문제에서 출발했습니다. 환자와 보호자를 함께 고려해 지정된 시간에만 물리적으로 보관함을 열 수 있고, 복용 여부 확인과 향후 원격 알림으로 확장할 수 있는 구조를 목표로 했습니다.",
      "contribution": "하드웨어 설계\n• 적외선 센서를 활용한 복용 감지와 시간 기반 잠금장치 회로 구성\n• 실제 구동 로직과 전력 흐름을 고려한 센서 배치 및 보관함 구조 설계\n• 오작동 가능성을 줄이고 단순하면서도 신뢰도 높은 복용 인식이 가능하도록 구성\n• 향후 외부 장치 연동을 고려한 구조 설계\n\n발표 자료\n• 프로젝트 배경 → 문제 인식 → 시스템 구성 흐름으로 발표 자료 구성\n• 핵심 정보 중심의 가독성 높은 시각화와 슬라이드 디자인 담당",
      "implementation": "주요 기능\n• 약 복용 시간에만 도어를 열고 그 외에는 자동 잠금\n• LCD로 현재 시간과 상태 표시\n• 설정용 버튼 및 수동 제어 인터페이스\n\n개발 흐름\n아이디어 회의 → 시간 기반 제어·서보모터 잠금·LCD 인터페이스 설계 → Arduino 회로와 모터 작동 테스트 → MDF·아크릴 기반 시제품 제작 → 기능 시연 및 최종 발표 준비",
      "architecture": "시간/설정 입력 → Arduino 제어 → IR 센서로 복용 여부 감지 → 서보모터 기반 잠금/해제 → LCD 상태 표시\n\n향후 블루투스·IoT 모듈을 연결해 보호자 앱에서 상태를 확인하고 실시간 알림을 제공하는 방향을 고려했습니다.",
      "architectureFlows": [
        {
          "label": "시스템 흐름",
          "nodes": [
            "Time / Buttons",
            "Arduino",
            "IR Sensor",
            "Servo Lock",
            "LCD",
            "Future IoT"
          ]
        }
      ],
      "troubleshooting": "",
      "result": "물리적 제어를 이용한 복약 솔루션이라는 방향으로 시제품을 설계했습니다. 추가 개선 방향으로는 복수 알람 시간, 사용자별 구획 도어, 블루투스 앱 연동, 실시간 알림, 음성 안내 기능이 정리되어 있습니다.",
      "gallery": [
        {
          "src": "images/projects/medicine-box/01.webp",
          "caption": "문제 인식 및 기획 배경을 설명한 발표 자료"
        },
        {
          "src": "images/projects/medicine-box/02.webp",
          "caption": "스마트 약품 보관함 필요성을 설명한 발표 자료"
        },
        {
          "src": "images/projects/medicine-box/03.webp",
          "caption": "프로젝트 기대 효과"
        },
        {
          "src": "images/projects/medicine-box/04.webp",
          "caption": "추가 개선 방향"
        }
      ]
    },
    {
      "id": "smart-shoes",
      "routeKey": "smart-shoes",
      "title": "스마트 신발 관리기",
      "category": "IOT · EMBEDDED",
      "level": "Lv.1",
      "date": "2023 · 캡스톤디자인",
      "order": 5,
      "published": true,
      "featured": false,
      "live": false,
      "description": "자동 건조·살균·탈취 기능을 갖춘 Arduino 기반 스마트 신발 관리기",
      "highlights": [],
      "role": "팀장 · 기획, 회로 설계, Arduino 프로그래밍, 센서·모듈 통합, 케이스 구조 제작까지 제품 개발 전반 수행",
      "tags": [
        "Arduino",
        "C++",
        "DHT11",
        "IR Sensor",
        "Motor Driver",
        "UV",
        "Hardware"
      ],
      "github": "",
      "demo": "",
      "image": "images/projects/smart-shoes/cover.webp",
      "overview": "2023년 캡스톤디자인 졸업작품으로 진행한 스마트 신발 관리기입니다. 비 오는 날이나 장시간 착용 후 발생하는 신발의 악취와 위생 문제를 줄이기 위해 신발을 넣으면 건조·쿨링·살균 기능이 순차적으로 동작하는 제품을 설계했습니다. 향후 스마트폰과 연동하는 IoT 제품으로 확장하는 방향도 고려했습니다.\n\n팀명: 건조해조",
      "problem": "신발을 장시간 착용하거나 비에 젖었을 때 건조와 위생 관리가 번거롭다는 생활 문제에서 출발했습니다. 사용자가 복잡한 조작을 하지 않아도 신발 유무와 문 상태를 감지해 자동으로 관리 과정이 시작되고 종료되는 제품을 목표로 했습니다.",
      "contribution": "팀장으로 기획부터 회로 설계, Arduino 프로그래밍, 센서·모듈 통합, 외장 케이스 구조 제작까지 제품 개발 전반을 수행했습니다.\n\n주요 제어\n• IR 센서: 신발·문 상태 감지\n• DHT11: 온도·습도 측정\n• UV 램프: 살균\n• 히터 팬 / 쿨링 팬: 건조 및 내부 공기 순환\n• LCD: 온습도와 동작 상태 표시",
      "implementation": "개발 히스토리\n1~2주차: 아이디어 탐색 후 신발 관리기로 주제 전환\n3~4주차: 회로 설계, 모듈 목록화, 초기 동작 논리 구성\n5~6주차: 부품 테스트와 LCD·센서·모터 드라이버 문제 점검\n7~8주차: 장비 축소와 케이스 재설계, 전원 스위치 도입\n9~10주차: 히터 팬 전력 부족 문제 보조 전원으로 해결\n11~12주차: IR 센서를 이용해 문 감지 로직을 대체하고 코드 재작성\n13~14주차: 케이스 수작업 제작 및 공간 최적화\n15~16주차: 전체 기능 동기화와 문서화",
      "architecture": "센서 입력(DHT11 / IR / 문 상태) → Arduino 제어 로직 → 모터 드라이버 → 히터 팬·쿨링 팬·UV 램프 → LCD 상태 출력\n\n하드웨어 구성 문서에는 Arduino 기반 제어 보드, L293D 모터 드라이버, 히터 팬, 쿨링 팬, UV 램프와 각종 센서가 정리되어 있습니다.",
      "architectureFlows": [
        {
          "label": "시스템 흐름",
          "nodes": [
            "DHT11 / IR",
            "Arduino",
            "Motor Driver",
            "Heater / Cooling",
            "UV Lamp",
            "LCD"
          ]
        }
      ],
      "troubleshooting": "부품 테스트 과정에서 LCD, 마그네틱 센서, 모터 드라이버 문제가 발생해 구성 변경을 검토했습니다. 히터 팬의 전력 부족은 보조 전원을 추가해 해결했고, 문 상태 감지는 IR 센서 기반으로 대체하면서 전체 제어 코드를 다시 작성했습니다. 제한된 케이스 공간에 부품을 배치하기 위해 외장 구조도 여러 차례 축소·재설계했습니다.",
      "result": "3D 프린터를 사용하지 않는 환경에서 직접 외장 구조를 설계하고, 하드웨어와 소프트웨어를 하나의 동작하는 제품으로 연결했습니다. 아이디어 → 계획 → 설계 → 구현 → 수정·보완의 전체 개발 사이클을 경험했고, Arduino와 C++ 기반 제어 흐름에 대한 이해를 높였습니다. 향후 릴레이 모듈, 스마트폰 앱 연동, 예약 기능, 신발 종류별 관리 가이드 등을 개선 방향으로 정리했습니다.",
      "gallery": [
        {
          "src": "images/projects/smart-shoes/01.webp",
          "caption": "스마트 신발 관리기 시제품"
        },
        {
          "src": "images/projects/smart-shoes/02.webp",
          "caption": "초기 제품 디자인 설계"
        },
        {
          "src": "images/projects/smart-shoes/03.webp",
          "caption": "케이스 구조 및 내부 배치 설계"
        },
        {
          "src": "images/projects/smart-shoes/04.webp",
          "caption": "주요 하드웨어 부품 구성 1"
        },
        {
          "src": "images/projects/smart-shoes/05.webp",
          "caption": "주요 하드웨어 부품 구성 2"
        },
        {
          "src": "images/projects/smart-shoes/06.webp",
          "caption": "동작 흐름 설계"
        }
      ]
    }
  ],
  "certifications": [
    {
      "id": "aws-saa",
      "name": "AWS Certified Solutions Architect – Associate",
      "issuer": "Amazon Web Services",
      "date": "2026.09.23",
      "credential": "SAA-C03",
      "url": "https://www.credly.com/badges/b7aa4d39-2b84-469e-9aed-630fee45defd/public_url"
    },
    {
      "id": "engineer-info",
      "name": "정보처리기사",
      "issuer": "한국산업인력공단",
      "date": "2025.09.12",
      "credential": "국가기술자격",
      "url": ""
    }
  ],
  "awards": [
    {
      "id": "capstone-award",
      "name": "교내 캡스톤 경진대회",
      "result": "우수상",
      "organizer": "대전대학교",
      "date": "2024.02.12"
    },
    {
      "id": "startup-award",
      "name": "창업경진대회",
      "result": "우수상",
      "organizer": "대전대학교",
      "date": "2022.05.31"
    }
  ]
}
