C# 함수에 대해서 쉽게 설명하는 페이지 만들기

소개

21기 교육앱만들기 수업 후 강의 교안을 웹으로 만들어 줬더니 반응이 좋아서 수업 때마다 만들어서 보여주고 있습니다.

어려운 코딩 수업이 조금은 친근해지길 기대해 봅니다.

진행 방법

어떤 도구를 사용했고, 어떻게 활용하셨나요?

cluade로 만들었습니다.

Tip: 사용한 프롬프트 전문을 꼭 포함하고, 내용을 짧게 소개해 주세요.

한국어로 된 문자 메시지의 스크린샷

Tip: 활용 이미지나 캡처 화면을 꼭 남겨주세요.

한국어로 된 문자 메시지의 스크린샷

설명을 해주더니 이제는 제 패턴을 인식했는지 이러네요.

"이제 HTML 웹 페이지로도 만들어드릴까요? 😊"

한국어 웹사이트 스크린샷

Tip: 코드 전문은 코드블록에 감싸서 작성해주세요. ( / 을 눌러 '코드 블록'을 선택)


<!DOCTYPE html>
<html lang="ko">
<head>
  <meta charset="UTF-8"/>
  <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
  <title>C# 함수 & 오버라이딩</title>
  <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@300;400;500;700;900&family=JetBrains+Mono:wght@400;500;700&display=swap" rel="stylesheet"/>
  <style>
    :root {
      --bg: #f6f4ef;
      --surface: #ffffff;
      --surface2: #eeeae1;
      --border: #e0dbd0;
      --text: #1c1a14;
      --muted: #9a9285;
      --fn-c:   #0369a1;
      --fn-bg:  rgba(3,105,161,0.07);
      --fn-bd:  rgba(3,105,161,0.25);
      --ov-c:   #7c3aed;
      --ov-bg:  rgba(124,58,237,0.07);
      --ov-bd:  rgba(124,58,237,0.25);
      --vt-c:   #d97706;
      --vt-bg:  rgba(217,119,6,0.07);
      --vt-bd:  rgba(217,119,6,0.25);
      --gr-c:   #16a34a;
      --gr-bg:  rgba(22,163,74,0.07);
      --gr-bd:  rgba(22,163,74,0.25);
      --code-bg:#1a1d2e;
      --shadow: 0 2px 14px rgba(0,0,0,0.07);
    }

    * { box-sizing: border-box; margin: 0; padding: 0; }
    html { scroll-behavior: smooth; }
    body {
      background: var(--bg);
      color: var(--text);
      font-family: 'Noto Sans KR', sans-serif;
      line-height: 1.7;
    }

    /* ── 히어로 ── */
    .hero {
      background: var(--code-bg);
      padding: 72px 24px 60px;
      text-align: center;
      position: relative;
      overflow: hidden;
      border-bottom: 1px solid #252840;
    }

    .hero::after {
      content: 'override';
      position: absolute; bottom: -24px; right: -10px;
      font-family: 'JetBrains Mono', monospace;
      font-size: 8rem; font-weight: 700;
      color: rgba(255,255,255,0.025);
      pointer-events: none;
    }

    .hero-tag {
      font-family: 'JetBrains Mono', monospace;
      font-size: 11px; letter-spacing: .22em;
      text-transform: uppercase; color: #585b7a;
      margin-bottom: 18px;
    }

    .hero h1 {
      font-size: clamp(2rem,5vw,3.4rem);
      font-weight: 900; letter-spacing: -.03em;
      line-height: 1.1; color: #cdd6f4;
      margin-bottom: 16px;
    }

    .hero h1 .hl-fn { color: #89b4fa; }
    .hero h1 .hl-ov { color: #cba6f7; }

    .hero-sub {
      font-size: 15px; color: #585b7a;
      max-width: 460px; margin: 0 auto 30px;
      line-height: 1.85;
    }

    .hero-chips {
      display: flex; justify-content: center;
      gap: 8px; flex-wrap: wrap;
    }

    .hero-chip {
      font-family: 'JetBrains Mono', monospace;
      font-size: 12px; padding: 6px 16px;
      border-radius: 20px; border: 1px solid;
      text-decoration: none; transition: all .2s;
    }

    .chip-fn { border-color: rgba(137,180,250,0.4); color: #89b4fa; }
    .chip-ov { border-color: rgba(203,166,247,0.4); color: #cba6f7; }
    .chip-vt { border-color: rgba(249,226,175,0.4); color: #f9e2af; }
    .hero-chip:hover { filter: brightness(1.4); transform: translateY(-2px); }

    /* ── 래퍼 ── */
    .wrapper {
      max-width: 880px; margin: 0 auto;
      padding: 0 24px 100px;
    }

    /* ── 섹션 ── */
    .section { margin-top: 68px; animation: fadeUp .5s ease both; }
    .section:nth-child(1) { animation-delay: .05s; }
    .section:nth-child(2) { animation-delay: .12s; }
    .section:nth-child(3) { animation-delay: .19s; }
    .section:nth-child(4) { animation-delay: .26s; }
    .section:nth-child(5) { animation-delay: .33s; }

    .sec-header {
      display: flex; align-items: center;
      gap: 14px; margin-bottom: 22px;
      padding-bottom: 18px;
      border-bottom: 1px solid var(--border);
    }

    .badge {
      font-family: 'JetBrains Mono', monospace;
      font-size: 12px; font-weight: 700;
      padding: 5px 16px; border-radius: 8px;
      border: 1.5px solid; white-space: nowrap;
    }

    .badge-fn { background: var(--fn-bg); border-color: var(--fn-bd); color: var(--fn-c); }
    .badge-ov { background: var(--ov-bg); border-color: var(--ov-bd); color: var(--ov-c); }
    .badge-vt { background: var(--vt-bg); border-color: var(--vt-bd); color: var(--vt-c); }
    .badge-gr { background: var(--gr-bg); border-color: var(--gr-bd); color: var(--gr-c); }

    .sh-title h2 { font-size: 1.4rem; font-weight: 800; letter-spacing: -.02em; margin-bottom: 2px; }
    .sh-title p  { font-size: 13px; color: var(--muted); }

    /* ── 설명 카드 ── */
    .desc-card {
      background: var(--surface);
      border: 1px solid var(--border);
      border-radius: 14px;
      padding: 22px 28px;
      margin-bottom: 16px;
      font-size: 15px; line-height: 2;
      color: #3a3930;
      box-shadow: var(--shadow);
    }
    .desc-card strong { color: var(--text); }

    .key-point {
      display: inline-flex; align-items: center;
      gap: 8px; margin-top: 14px;
      padding: 10px 16px; border-radius: 8px;
      font-size: 13.5px; font-weight: 600;
    }
    .kp-fn { background: var(--fn-bg); border: 1px solid var(--fn-bd); color: var(--fn-c); }
    .kp-ov { background: var(--ov-bg); border: 1px solid var(--ov-bd); color: var(--ov-c); }
    .kp-vt { background: var(--vt-bg); border: 1px solid var(--vt-bd); color: var(--vt-c); }
    .kp-gr { background: var(--gr-bg); border: 1px solid var(--gr-bd); color: var(--gr-c); }

    /* ── 비유 박스 ── */
    .analogy-box {
      background: #fffbeb;
      border: 1px solid #fde68a;
      border-radius: 12px;
      padding: 18px 22px;
      margin-bottom: 16px;
      font-size: 14px; line-height: 1.85;
      color: #78350f;
    }
    .analogy-box .ab-title {
      font-weight: 700; font-size: 13px;
      letter-spacing: .06em; margin-bottom: 8px;
      color: #92400e;
    }

    /* ── 코드 블록 ── */
    .code-block {
      background: var(--code-bg);
      border: 1px solid #252840;
      border-radius: 12px; overflow: hidden;
      margin-bottom: 16px;
    }

    .cb-bar {
      display: flex; align-items: center; gap: 7px;
      padding: 10px 16px;
      background: rgba(255,255,255,0.03);
      border-bottom: 1px solid #252840;
    }

    .dot { width: 10px; height: 10px; border-radius: 50%; }
    .dr { background: #f38ba8; }
    .dy { background: #f9e2af; }
    .dg { background: #a6e3a1; }
    .cb-fname { font-family: 'JetBrains Mono', monospace; font-size: 11px; color: #44475a; margin-left: 4px; }
    .cb-lang  { font-family: 'JetBrains Mono', monospace; font-size: 11px; color: #44475a; margin-left: auto; }

    pre {
      padding: 20px 22px;
      font-family: 'JetBrains Mono', monospace;
      font-size: 13.5px; line-height: 2.1;
      overflow-x: auto; color: #cdd6f4;
    }

    .kw  { color: #cba6f7; }
    .cl  { color: #89b4fa; }
    .fn  { color: #89dceb; }
    .str { color: #a6e3a1; }
    .num { color: #fab387; }
    .cm  { color: #44475a; font-style: italic; }
    .ret { color: #f38ba8; }
    .virt{ color: #f9e2af; font-weight: 700; }
    .over{ color: #cba6f7; font-weight: 700; }
    .out { color: #a6e3a1; }

    /* ── 함수 구조 시각화 ── */
    .fn-structure {
      background: var(--surface);
      border: 1px solid var(--border);
      border-radius: 14px; padding: 24px 28px;
      margin-bottom: 16px; box-shadow: var(--shadow);
    }

    .fn-diagram {
      display: flex; align-items: stretch;
      gap: 0; font-family: 'JetBrains Mono', monospace;
      font-size: 14px; flex-wrap: wrap;
      margin-bottom: 20px;
    }

    .fn-part {
      display: flex; flex-direction: column;
      align-items: center; gap: 8px;
    }

    .fn-token {
      padding: 10px 14px; border-radius: 8px;
      border: 2px solid; font-weight: 700;
      font-size: 15px; white-space: nowrap;
    }

    .ft-ret  { background: rgba(243,139,168,0.1); border-color: rgba(243,139,168,0.3); color: #f38ba8; }
    .ft-name { background: var(--fn-bg); border-color: var(--fn-bd); color: var(--fn-c); }
    .ft-paren{ background: rgba(255,255,255,0.05); border-color: #30344a; color: #6c7086; padding: 10px 8px; }
    .ft-param{ background: var(--vt-bg); border-color: var(--vt-bd); color: var(--vt-c); }
    .ft-body { background: var(--gr-bg); border-color: var(--gr-bd); color: var(--gr-c); }

    .fn-label {
      font-size: 9px; letter-spacing: .1em;
      text-transform: uppercase; padding: 2px 8px;
      border-radius: 10px; white-space: nowrap;
    }

    .lbl-ret  { background: rgba(243,139,168,0.1); color: #f38ba8; }
    .lbl-name { background: var(--fn-bg); color: var(--fn-c); }
    .lbl-param{ background: var(--vt-bg); color: var(--vt-c); }
    .lbl-body { background: var(--gr-bg); color: var(--gr-c); }

    .fn-rules {
      display: grid; grid-template-columns: repeat(auto-fit, minmax(170px,1fr));
      gap: 10px;
    }

    .fn-rule {
      background: var(--surface2);
      border: 1px solid var(--border);
      border-radius: 10px; padding: 14px 16px;
    }

    .fn-rule .fr-num {
      font-family: 'JetBrains Mono', monospace;
      font-size: 1.2rem; font-weight: 700;
      color: var(--fn-c); margin-bottom: 4px;
    }

    .fn-rule .fr-title { font-size: 13px; font-weight: 700; margin-bottom: 3px; }
    .fn-rule .fr-desc  { font-size: 12px; color: var(--muted); line-height: 1.6; }

    /* ── 오버라이딩 흐름도 ── */
    .inherit-flow {
      display: flex; flex-direction: column;
      gap: 0; margin-bottom: 16px;
    }

    .flow-parent {
      background: var(--surface);
      border: 2px solid var(--fn-bd);
      border-radius: 14px 14px 0 0;
      padding: 20px 24px;
      box-shadow: var(--shadow);
    }

    .flow-arrow {
      display: flex; justify-content: center;
      align-items: center; height: 40px;
      background: linear-gradient(to bottom, var(--fn-bg), var(--ov-bg));
      position: relative;
    }

    .flow-arrow::after {
      content: '▼ 상속 (inheritance)';
      font-family: 'JetBrains Mono', monospace;
      font-size: 11px; color: var(--muted);
      letter-spacing: .08em;
    }

    .flow-children {
      display: grid; grid-template-columns: 1fr 1fr; gap: 0;
    }

    @media (max-width: 540px) { .flow-children { grid-template-columns: 1fr; } }

    .flow-child {
      border: 2px solid var(--ov-bd);
      padding: 20px 24px;
      background: var(--surface);
    }

    .flow-child:first-child { border-radius: 0 0 0 14px; border-right-width: 1px; }
    .flow-child:last-child  { border-radius: 0 0 14px 0; border-left-width: 1px; }

    .flow-label {
      font-family: 'JetBrains Mono', monospace;
      font-size: 10px; letter-spacing: .12em;
      text-transform: uppercase; margin-bottom: 8px;
    }

    .fl-parent { color: var(--fn-c); }
    .fl-child  { color: var(--ov-c); }

    .flow-class-name {
      font-family: 'JetBrains Mono', monospace;
      font-size: 1.1rem; font-weight: 700;
      margin-bottom: 10px;
    }

    .fcn-parent { color: var(--fn-c); }
    .fcn-child  { color: var(--ov-c); }

    .flow-method {
      font-family: 'JetBrains Mono', monospace;
      font-size: 12.5px; padding: 8px 12px;
      border-radius: 8px;
    }

    .fm-parent { background: var(--fn-bg); border: 1px solid var(--fn-bd); color: var(--fn-c); }
    .fm-child  { background: var(--ov-bg); border: 1px solid var(--ov-bd); color: var(--ov-c); }

    /* ── virtual / override 비교 ── */
    .vo-grid {
      display: grid; grid-template-columns: 1fr 1fr;
      gap: 14px; margin-bottom: 16px;
    }

    @media (max-width: 520px) { .vo-grid { grid-template-columns: 1fr; } }

    .vo-card {
      border-radius: 12px; overflow: hidden;
      border: 1.5px solid; box-shadow: var(--shadow);
    }

    .vo-card.vt { border-color: var(--vt-bd); }
    .vo-card.ov { border-color: var(--ov-bd); }

    .vo-head {
      padding: 14px 18px;
      display: flex; align-items: center; gap: 10px;
    }

    .vo-card.vt .vo-head { background: var(--vt-bg); }
    .vo-card.ov .vo-head { background: var(--ov-bg); }

    .vo-kw {
      font-family: 'JetBrains Mono', monospace;
      font-size: 1.4rem; font-weight: 700;
    }

    .vo-card.vt .vo-kw { color: var(--vt-c); }
    .vo-card.ov .vo-kw { color: var(--ov-c); }

    .vo-head-text .vht-title { font-size: 14px; font-weight: 700; margin-bottom: 2px; }
    .vo-head-text .vht-sub   { font-size: 12px; color: var(--muted); }

    .vo-body {
      padding: 16px 18px;
      background: var(--surface);
    }

    .vo-body ul {
      list-style: none;
      display: flex; flex-direction: column; gap: 8px;
    }

    .vo-body ul li {
      font-size: 13px; color: #555;
      padding-left: 18px; position: relative;
      line-height: 1.65;
    }

    .vo-body ul li::before { content: '·'; position: absolute; left: 4px; font-size: 18px; line-height: 1.1; }
    .vo-card.vt .vo-body ul li::before { color: var(--vt-c); }
    .vo-card.ov .vo-body ul li::before { color: var(--ov-c); }

    /* ── 인터랙티브 데모 ── */
    .demo-wrap {
      background: var(--surface);
      border: 1px solid var(--border);
      border-radius: 14px; overflow: hidden;
      box-shadow: var(--shadow);
    }

    .demo-top {
      padding: 13px 20px;
      background: var(--surface2);
      border-bottom: 1px solid var(--border);
      display: flex; align-items: center;
      gap: 12px; flex-wrap: wrap;
    }

    .demo-top span {
      font-family: 'JetBrains Mono', monospace;
      font-size: 11px; color: var(--muted);
      letter-spacing: .12em; text-transform: uppercase;
    }

    .animal-btns { display: flex; gap: 8px; flex-wrap: wrap; }

    .animal-btn {
      padding: 7px 16px; border-radius: 8px;
      border: 1.5px solid var(--border);
      background: transparent; cursor: pointer;
      font-family: 'Noto Sans KR', sans-serif;
      font-size: 13px; color: var(--muted);
      transition: all .2s;
    }

    .animal-btn:hover { border-color: #aaa; color: var(--text); }
    .animal-btn.active {
      background: var(--ov-bg);
      border-color: var(--ov-bd);
      color: var(--ov-c); font-weight: 700;
    }

    .demo-body { padding: 24px; }

    .demo-console {
      background: #0e1018;
      border: 1px solid #252840;
      border-radius: 10px; overflow: hidden;
      margin-bottom: 14px;
    }

    .dc-bar {
      display: flex; align-items: center; gap: 6px;
      padding: 9px 14px;
      background: #13161f;
      border-bottom: 1px solid #252840;
    }

    .dc-dot { width: 10px; height: 10px; border-radius: 50%; }
    .dd-r{background:#f38ba8;}.dd-y{background:#f9e2af;}.dd-g{background:#a6e3a1;}

    .dc-body {
      padding: 16px 20px;
      font-family: 'JetBrains Mono', monospace;
      font-size: 14px; line-height: 2.2;
      min-height: 60px;
    }

    #demo-output {
      transition: all .3s;
    }

    .demo-code-box {
      background: var(--code-bg);
      border: 1px solid #252840;
      border-radius: 8px;
      padding: 14px 18px;
      font-family: 'JetBrains Mono', monospace;
      font-size: 12.5px; line-height: 1.9;
      color: #6c7086;
    }

    /* ── 비교표 ── */
    .cmp-table {
      width: 100%; border-collapse: collapse;
      font-size: 13.5px;
      background: var(--surface);
      border: 1px solid var(--border);
      border-radius: 14px; overflow: hidden;
      box-shadow: var(--shadow);
    }

    .cmp-table th {
      padding: 13px 18px; text-align: left;
      font-family: 'JetBrains Mono', monospace;
      font-size: 10px; letter-spacing: .12em;
      text-transform: uppercase; color: var(--muted);
      background: var(--surface2);
      border-bottom: 1px solid var(--border);
    }

    .cmp-table td {
      padding: 14px 18px;
      border-bottom: 1px solid rgba(0,0,0,0.04);
      vertical-align: middle; color: #555;
    }

    .cmp-table tr:last-child td { border-bottom: none; }
    .cmp-table tr:hover td { background: var(--surface2); }
    .cmp-table td:first-child { font-family: 'JetBrains Mono', monospace; font-size: 13px; font-weight: 700; }
    .cmp-table .row-vt td:first-child { color: var(--vt-c); }
    .cmp-table .row-ov td:first-child { color: var(--ov-c); }

    /* ── 핵심 정리 ── */
    .summary-grid {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(190px,1fr));
      gap: 14px; margin-top: 60px;
    }

    .sum-card {
      background: var(--surface);
      border: 1px solid var(--border);
      border-radius: 14px; padding: 22px;
      box-shadow: var(--shadow); transition: transform .2s;
    }

    .sum-card:hover { transform: translateY(-4px); }

    .sum-dot { width: 10px; height: 10px; border-radius: 50%; margin-bottom: 12px; }
    .sum-name { font-family: 'JetBrains Mono', monospace; font-size: 14px; font-weight: 700; margin-bottom: 8px; }
    .sum-desc { font-size: 13px; color: var(--muted); line-height: 1.7; }
    .sum-when { margin-top: 10px; font-size: 12px; color: var(--muted); border-top: 1px solid var(--border); padding-top: 10px; }

    @keyframes fadeUp { from{opacity:0;transform:translateY(20px);}to{opacity:1;transform:translateY(0);} }
  </style>
</head>
<body>

<!-- 히어로 -->
<div class="hero">
  <div class="hero-tag">C# · OOP · Method</div>
  <h1>
    <span class="hl-fn">함수</span> &
    <span class="hl-ov">오버라이딩</span>
  </h1>
  <p class="hero-sub">
    코드를 묶는 함수부터 부모 기능을 자식이 바꾸는 오버라이딩까지<br/>
    아주 쉽게 이해해봐요!
  </p>
  <div class="hero-chips">
    <a href="#sec-fn"  class="hero-chip chip-fn">함수(Method)</a>
    <a href="#sec-ov"  class="hero-chip chip-ov">오버라이딩</a>
    <a href="#sec-vt"  class="hero-chip chip-vt">virtual / override</a>
  </div>
</div>

<div class="wrapper">

  <!-- ── 01 함수 ── -->
  <div class="section" id="sec-fn">
    <div class="sec-header">
      <div class="badge badge-fn">01 · 함수 (Method)</div>
      <div class="sh-title">
        <h2>함수란 무엇인가요?</h2>
        <p>이름 붙은 코드 묶음 — 한 번 만들고 여러 번 사용!</p>
      </div>
    </div>

    <div class="analogy-box">
      <div class="ab-title">🍕 쉬운 비유</div>
      함수는 <strong>요리 레시피</strong>와 같아요!<br/>
      레시피(함수)를 한 번 만들어두면, 피자가 먹고 싶을 때마다 꺼내서 쓸 수 있어요.<br/>
      매번 처음부터 요리법을 생각할 필요가 없죠. → <strong>코드 재사용!</strong>
    </div>

    <div class="desc-card">
      <strong>함수(Method)</strong>는 특정 동작을 하는 코드를 <strong>묶어서 이름을 붙인 것</strong>이에요.<br/>
      필요할 때마다 이름을 불러서 <strong>반복 사용</strong>할 수 있어요.<br/>
      값을 받아서(<strong>매개변수</strong>) 처리하고, 결과를 돌려줄(<strong>반환</strong>) 수 있어요.
      <br/>
      <div class="key-point kp-fn">📌 한 번 만들고 → 여러 번 재사용!</div>
    </div>

    <!-- 함수 구조 시각화 -->
    <div class="fn-structure">
      <p style="font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--muted);letter-spacing:.12em;text-transform:uppercase;margin-bottom:20px;">함수 구조 분해</p>
      <div class="fn-diagram" style="gap:6px;margin-bottom:32px;flex-wrap:wrap;align-items:flex-end;justify-content:center;">
        <div class="fn-part">
          <div class="fn-token ft-ret">int</div>
          <div class="fn-label lbl-ret">반환 타입</div>
        </div>
        <div style="padding-bottom:18px;color:#6c7086;font-family:'JetBrains Mono',monospace;font-size:18px;"> </div>
        <div class="fn-part">
          <div class="fn-token ft-name">Add</div>
          <div class="fn-label lbl-name">함수 이름</div>
        </div>
        <div style="padding-bottom:18px;color:#6c7086;font-family:'JetBrains Mono',monospace;font-size:18px;">(</div>
        <div class="fn-part">
          <div class="fn-token ft-param">int a, int b</div>
          <div class="fn-label lbl-param">매개변수</div>
        </div>
        <div style="padding-bottom:18px;color:#6c7086;font-family:'JetBrains Mono',monospace;font-size:18px;">)</div>
        <div style="padding-bottom:18px;color:#6c7086;font-family:'JetBrains Mono',monospace;"> </div>
        <div class="fn-part">
          <div class="fn-token ft-body">{ return a+b; }</div>
          <div class="fn-label lbl-body">본문</div>
        </div>
      </div>

      <div class="fn-rules">
        <div class="fn-rule">
          <div class="fr-num">01</div>
          <div class="fr-title">반환 타입</div>
          <div class="fr-desc">돌려줄 값의 타입. 없으면 void</div>
        </div>
        <div class="fn-rule">
          <div class="fr-num">02</div>
          <div class="fr-title">함수 이름</div>
          <div class="fr-desc">호출할 때 쓰는 이름. 동사로!</div>
        </div>
        <div class="fn-rule">
          <div class="fr-num">03</div>
          <div class="fr-title">매개변수</div>
          <div class="fr-desc">외부에서 받아올 값. 없어도 OK</div>
        </div>
        <div class="fn-rule">
          <div class="fr-num">04</div>
          <div class="fr-title">본문 & return</div>
          <div class="fr-desc">실제 동작 코드 + 결과 반환</div>
        </div>
      </div>
    </div>

    <div class="code-block">
      <div class="cb-bar">
        <div class="dot dr"></div><div class="dot dy"></div><div class="dot dg"></div>
        <div class="cb-lang">C#</div>
      </div>
      <pre><span class="cm">// ① 함수 만들기 (정의)</span>
<span class="kw">int</span> <span class="fn">Add</span>(<span class="kw">int</span> a, <span class="kw">int</span> b)
{
    <span class="ret">return</span> a + b;
}

<span class="cm">// ② 반환값 없는 함수 (void)</span>
<span class="kw">void</span> <span class="fn">SayHello</span>(<span class="kw">string</span> name)
{
    Console.<span class="fn">WriteLine</span>(<span class="str">$"안녕하세요, {name}님!"</span>);
}

<span class="cm">// ③ 함수 사용하기 (호출)</span>
<span class="kw">int</span> result = <span class="fn">Add</span>(<span class="num">3</span>, <span class="num">5</span>);          <span class="cm">// result = 8</span>
Console.<span class="fn">WriteLine</span>(result);         <span class="out">// 8</span>

<span class="fn">SayHello</span>(<span class="str">"홍길동"</span>);               <span class="out">// 안녕하세요, 홍길동님!</span>
<span class="fn">SayHello</span>(<span class="str">"김철수"</span>);               <span class="out">// 안녕하세요, 김철수님!</span></pre>
    </div>
  </div>

  <!-- ── 02 오버라이딩 ── -->
  <div class="section" id="sec-ov">
    <div class="sec-header">
      <div class="badge badge-ov">02 · 오버라이딩 (Overriding)</div>
      <div class="sh-title">
        <h2>부모 함수를 자식이 덮어쓰기</h2>
        <p>상속받은 메서드를 자식 클래스에서 새로 정의</p>
      </div>
    </div>

    <div class="analogy-box">
      <div class="ab-title">🍕 쉬운 비유</div>
      <strong>피자 본점(부모)</strong>에 "피자 굽기" 레시피가 있어요.<br/>
      <strong>분점(자식)</strong>이 그 레시피를 그대로 쓰지 않고 <strong>자기만의 방식으로 바꾸는 것</strong>이 오버라이딩이에요!<br/><br/>
      🐶 강아지는 "소리내기"를 <strong>멍멍</strong>으로,<br/>
      🐱 고양이는 "소리내기"를 <strong>야옹</strong>으로 — 같은 함수를 다르게 구현!
    </div>

    <div class="desc-card">
      <strong>오버라이딩</strong>은 부모 클래스의 함수를 <strong>자식 클래스에서 새로 정의</strong>하는 것이에요.<br/>
      부모의 함수를 그대로 쓰지 않고, <strong>자식만의 방식으로 바꿀 수 있어요.</strong><br/>
      부모에서 <strong>virtual</strong>로 열어주고, 자식에서 <strong>override</strong>로 덮어써요.
      <br/>
      <div class="key-point kp-ov">📌 부모 virtual → 자식 override → 자식만의 동작!</div>
    </div>

    <!-- 상속 흐름도 -->
    <div class="inherit-flow">
      <div class="flow-parent">
        <div class="flow-label fl-parent">부모 클래스 (Parent)</div>
        <div class="flow-class-name fcn-parent">Animal</div>
        <div class="flow-method fm-parent">
          virtual void Speak() → "..." 출력
        </div>
      </div>
      <div class="flow-arrow"></div>
      <div class="flow-children">
        <div class="flow-child">
          <div class="flow-label fl-child">자식 클래스 (Child)</div>
          <div class="flow-class-name fcn-child">Dog 🐶</div>
          <div class="flow-method fm-child">
            override void Speak() → "멍멍!" 출력
          </div>
        </div>
        <div class="flow-child">
          <div class="flow-label fl-child">자식 클래스 (Child)</div>
          <div class="flow-class-name fcn-child">Cat 🐱</div>
          <div class="flow-method fm-child">
            override void Speak() → "야옹!" 출력
          </div>
        </div>
      </div>
    </div>

    <div class="code-block">
      <div class="cb-bar">
        <div class="dot dr"></div><div class="dot dy"></div><div class="dot dg"></div>
        <div class="cb-lang">C#</div>
      </div>
      <pre><span class="cm">// 부모 클래스</span>
<span class="kw">class</span> <span class="cl">Animal</span>
{
    <span class="kw">public</span> <span class="virt">virtual</span> <span class="kw">void</span> <span class="fn">Speak</span>()   <span class="cm">// virtual = "바꿔도 돼!"</span>
    {
        Console.<span class="fn">WriteLine</span>(<span class="str">"..."</span>);
    }
}

<span class="cm">// 자식 클래스 — Dog</span>
<span class="kw">class</span> <span class="cl">Dog</span> : <span class="cl">Animal</span>
{
    <span class="kw">public</span> <span class="over">override</span> <span class="kw">void</span> <span class="fn">Speak</span>()  <span class="cm">// override = "내가 새로 만들게!"</span>
    {
        Console.<span class="fn">WriteLine</span>(<span class="str">"멍멍! 🐶"</span>);
    }
}

<span class="cm">// 자식 클래스 — Cat</span>
<span class="kw">class</span> <span class="cl">Cat</span> : <span class="cl">Animal</span>
{
    <span class="kw">public</span> <span class="over">override</span> <span class="kw">void</span> <span class="fn">Speak</span>()
    {
        Console.<span class="fn">WriteLine</span>(<span class="str">"야옹! 🐱"</span>);
    }
}

<span class="cm">// 사용</span>
<span class="cl">Animal</span> dog = <span class="kw">new</span> <span class="cl">Dog</span>();
<span class="cl">Animal</span> cat = <span class="kw">new</span> <span class="cl">Cat</span>();

dog.<span class="fn">Speak</span>();   <span class="out">// 멍멍! 🐶</span>
cat.<span class="fn">Speak</span>();   <span class="out">// 야옹! 🐱</span></pre>
    </div>

    <!-- 인터랙티브 데모 -->
    <div class="demo-wrap">
      <div class="demo-top">
        <span>동물을 선택해보세요</span>
        <div class="animal-btns">
          <button class="animal-btn" onclick="callSpeak('Animal')">Animal (부모)</button>
          <button class="animal-btn" onclick="callSpeak('Dog')">Dog 🐶</button>
          <button class="animal-btn" onclick="callSpeak('Cat')">Cat 🐱</button>
          <button class="animal-btn" onclick="callSpeak('Bird')">Bird 🐦</button>
        </div>
      </div>
      <div class="demo-body">
        <div class="demo-console">
          <div class="dc-bar">
            <div class="dc-dot dd-r"></div>
            <div class="dc-dot dd-y"></div>
            <div class="dc-dot dd-g"></div>
          </div>
          <div class="dc-body">
            <span id="demo-output" style="color:#6c7086;">← 동물을 선택하면 Speak()가 실행돼요!</span>
          </div>
        </div>
        <div class="demo-code-box" id="demo-code">
          // 버튼을 눌러보세요!
        </div>
      </div>
    </div>
  </div>

  <!-- ── 03 virtual / override ── -->
  <div class="section" id="sec-vt">
    <div class="sec-header">
      <div class="badge badge-vt">03 · virtual & override</div>
      <div class="sh-title">
        <h2>두 키워드의 차이</h2>
        <p>부모가 열어주고 → 자식이 들어가서 바꾼다!</p>
      </div>
    </div>

    <div class="vo-grid">
      <div class="vo-card vt">
        <div class="vo-head">
          <div class="vo-kw">virtual</div>
          <div class="vo-head-text">
            <div class="vht-title">부모가 씁니다</div>
            <div class="vht-sub">"자식아, 바꿔도 돼!"</div>
          </div>
        </div>
        <div class="vo-body">
          <ul>
            <li>부모 클래스의 함수에 붙여요</li>
            <li>"이 함수는 자식이 바꿀 수 있어" 라는 신호</li>
            <li>virtual 없으면 override 불가!</li>
            <li>🚪 열려있는 문 — 들어올 수 있어!</li>
          </ul>
        </div>
      </div>
      <div class="vo-card ov">
        <div class="vo-head">
          <div class="vo-kw">override</div>
          <div class="vo-head-text">
            <div class="vht-title">자식이 씁니다</div>
            <div class="vht-sub">"내가 새로 만들게!"</div>
          </div>
        </div>
        <div class="vo-body">
          <ul>
            <li>자식 클래스의 함수에 붙여요</li>
            <li>부모의 virtual 함수를 새로 정의</li>
            <li>반드시 부모에 virtual이 있어야!</li>
            <li>🎨 문 열고 들어가서 새로 꾸미기!</li>
          </ul>
        </div>
      </div>
    </div>

    <div class="code-block">
      <div class="cb-bar">
        <div class="dot dr"></div><div class="dot dy"></div><div class="dot dg"></div>
        <div class="cb-lang">C# — virtual & override 흐름</div>
      </div>
      <pre><span class="kw">class</span> <span class="cl">Parent</span>
{
    <span class="cm">// virtual → "자식이 바꿔도 OK!"</span>
    <span class="kw">public</span> <span class="virt">virtual</span> <span class="kw">void</span> <span class="fn">Hello</span>()
    {
        Console.<span class="fn">WriteLine</span>(<span class="str">"부모의 Hello"</span>);
    }
}

<span class="kw">class</span> <span class="cl">Child</span> : <span class="cl">Parent</span>
{
    <span class="cm">// override → "내가 새로 정의할게!"</span>
    <span class="kw">public</span> <span class="over">override</span> <span class="kw">void</span> <span class="fn">Hello</span>()
    {
        Console.<span class="fn">WriteLine</span>(<span class="str">"자식의 Hello"</span>);
    }
}

<span class="cl">Parent</span> p = <span class="kw">new</span> <span class="cl">Parent</span>();
<span class="cl">Parent</span> c = <span class="kw">new</span> <span class="cl">Child</span>();

p.<span class="fn">Hello</span>();   <span class="out">// 부모의 Hello</span>
c.<span class="fn">Hello</span>();   <span class="out">// 자식의 Hello  ← override 적용!</span></pre>
    </div>

    <!-- 비교표 -->
    <div style="overflow-x:auto;">
      <table class="cmp-table">
        <thead>
          <tr>
            <th>키워드</th>
            <th>누가 쓰나</th>
            <th>의미</th>
            <th>없으면?</th>
          </tr>
        </thead>
        <tbody>
          <tr class="row-vt">
            <td>virtual</td>
            <td>부모 클래스</td>
            <td>"자식아, 이 함수 바꿔도 돼!"</td>
            <td>자식이 override 불가</td>
          </tr>
          <tr class="row-ov">
            <td>override</td>
            <td>자식 클래스</td>
            <td>"부모 함수를 내가 새로 만들게!"</td>
            <td>부모 함수 그대로 사용</td>
          </tr>
        </tbody>
      </table>
    </div>
  </div>

  <!-- ── 핵심 정리 ── -->
  <div class="summary-grid">
    <div class="sum-card">
      <div class="sum-dot" style="background:var(--fn-c);"></div>
      <div class="sum-name" style="color:var(--fn-c);">함수 (Method)</div>
      <div class="sum-desc">코드를 묶어 이름 붙이고 재사용. 반환타입 + 이름 + 매개변수 + 본문.</div>
      <div class="sum-when">✦ 반복되는 코드는 함수로!</div>
    </div>
    <div class="sum-card">
      <div class="sum-dot" style="background:var(--vt-c);"></div>
      <div class="sum-name" style="color:var(--vt-c);">virtual</div>
      <div class="sum-desc">부모가 사용. "자식이 이 함수를 바꿔도 돼!"라는 신호.</div>
      <div class="sum-when">✦ 🚪 열려있는 문</div>
    </div>
    <div class="sum-card">
      <div class="sum-dot" style="background:var(--ov-c);"></div>
      <div class="sum-name" style="color:var(--ov-c);">override</div>
      <div class="sum-desc">자식이 사용. 부모의 virtual 함수를 자식 방식으로 새로 정의.</div>
      <div class="sum-when">✦ 🎨 문 열고 새로 꾸미기</div>
    </div>
    <div class="sum-card">
      <div class="sum-dot" style="background:var(--gr-c);"></div>
      <div class="sum-name" style="color:var(--gr-c);">핵심 순서</div>
      <div class="sum-desc">① 부모에 virtual 추가 → ② 자식에 override 추가 → ③ 자식만의 동작!</div>
      <div class="sum-when">✦ virtual 없으면 override 불가!</div>
    </div>
  </div>

</div>

<script>
  const animals = {
    Animal: {
      color: '#89b4fa',
      text: '... (부모 기본 동작)',
      code: `Animal a = new Animal();\na.Speak();\n// → "..." (virtual 기본값)`
    },
    Dog: {
      color: '#fab387',
      text: '멍멍! 🐶 (Dog override)',
      code: `Animal dog = new Dog();\ndog.Speak();\n// → "멍멍! 🐶" (override 적용!)`
    },
    Cat: {
      color: '#f9a8d4',
      text: '야옹! 🐱 (Cat override)',
      code: `Animal cat = new Cat();\ncat.Speak();\n// → "야옹! 🐱" (override 적용!)`
    },
    Bird: {
      color: '#86efac',
      text: '짹짹! 🐦 (Bird override)',
      code: `Animal bird = new Bird();\nbird.Speak();\n// → "짹짹! 🐦" (override 적용!)`
    }
  };

  function callSpeak(name) {
    document.querySelectorAll('.animal-btn').forEach(b => b.classList.remove('active'));
    event.target.classList.add('active');

    const a = animals[name];
    const out = document.getElementById('demo-output');
    out.style.color = a.color;
    out.textContent = a.text;

    document.getElementById('demo-code').innerHTML =
      `<span style="color:#44475a;font-style:italic;">// ${name}.Speak() 호출 결과</span>\n` + a.code;
  }
</script>
</body>
</html>

결과와 배운 점

같은 채팅에 계속 요청을 동일하게 했더니 정리를 더 잘 해주는 것 같아요.

패턴도 이제 다 파악해서 알아서 만들어 줄까? 라고 물어보니 편하기도 합니다.

열심히 활용해 볼게요.

밀어주고 끌어주는

온·오프라인 AI 스터디

AI로 어디까지 할 수 있는지
직접 확인하실 분만 신청하세요.