1. 자유로운 웹사이트 코드펜 작업

스크린샷 2025-11-09 오후 2.18.42.png

이런 프롬포트를 적었더니

<!doctype html>
<html lang="ko">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width,initial-scale=1" />
  <title>랜덤 명언 생성기</title>
  <style>
    :root{
      --bg:#0f1724;
      --card:#0b1220;
      --accent:#60a5fa;
      --muted:#94a3b8;
      --glass: rgba(255,255,255,0.03);
    }
    *{box-sizing:border-box}
    html,body{height:100%}
    body{
      margin:0;
      font-family: Inter, "Noto Sans KR", system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial;
      background: linear-gradient(180deg, #071026 0%, #081124 60%, #04101a 100%);
      color: #e6eef8;
      display:flex;
      align-items:center;
      justify-content:center;
      padding:24px;
    }

    .card{
      width:100%;
      max-width:720px;
      background: linear-gradient(180deg, rgba(255,255,255,0.02), rgba(255,255,255,0.01));
      border-radius:16px;
      padding:28px;
      box-shadow: 0 10px 30px rgba(2,6,23,0.6);
      border:1px solid rgba(255,255,255,0.04);
      backdrop-filter: blur(6px);
    }

    header{
      display:flex;
      align-items:center;
      justify-content:space-between;
      gap:12px;
      margin-bottom:18px;
    }
    .title{
      display:flex;
      gap:12px;
      align-items:center;
    }
    .logo{
      width:48px;
      height:48px;
      display:grid;
      place-items:center;
      border-radius:10px;
      background:linear-gradient(135deg, rgba(96,165,250,0.15), rgba(96,165,250,0.06));
      border:1px solid rgba(96,165,250,0.12);
      font-weight:700;
      color:var(--accent);
      font-size:18px;
    }
    h1{
      font-size:18px;
      margin:0;
      letter-spacing: -0.2px;
    }
    p.lead{
      margin:0;
      color:var(--muted);
      font-size:13px;
    }

    .quote-wrap{
      padding:28px;
      border-radius:12px;
      background: linear-gradient(180deg, rgba(255,255,255,0.01), rgba(255,255,255,0.02));
      border:1px solid rgba(255,255,255,0.03);
      min-height:160px;
      display:flex;
      flex-direction:column;
      justify-content:center;
      gap:14px;
      transition: transform .18s ease, opacity .18s ease;
    }

    blockquote{
      margin:0;
      font-size:20px;
      line-height:1.45;
      font-weight:500;
      quotes: "“" "”" "‘" "’";
    }
    blockquote::before{content: open-quote; margin-right:6px; color:var(--accent); font-size:28px}
    .author{
      text-align:right;
      color:var(--muted);
      font-size:14px;
      margin-top:6px;
    }

    .controls{
      display:flex;
      gap:12px;
      margin-top:18px;
      align-items:center;
      justify-content:space-between;
    }

    .left-controls{
      display:flex;
      gap:8px;
      align-items:center;
    }

    button{
      background:var(--glass);
      color:inherit;
      border:1px solid rgba(255,255,255,0.04);
      padding:10px 14px;
      border-radius:10px;
      cursor:pointer;
      font-size:14px;
      display:inline-flex;
      gap:8px;
      align-items:center;
      transition: transform .12s ease, background .12s ease;
    }
    button:hover{ transform: translateY(-3px) }
    .primary{
      background: linear-gradient(90deg, rgba(96,165,250,0.12), rgba(96,165,250,0.06));
      border:1px solid rgba(96,165,250,0.18);
      box-shadow: 0 6px 18px rgba(2,6,23,0.45);
      color:var(--accent);
      font-weight:600;
    }
    .icon{
      width:18px;height:18px;display:inline-grid;place-items:center;
    }

    .muted-small{ color:var(--muted); font-size:13px }

    /* fade animation classes */
    .fade-out{ opacity:0; transform: translateY(6px); }
    .fade-in{ opacity:1; transform: translateY(0); transition: opacity .28s ease, transform .28s ease; }

    @media (max-width:520px){
      blockquote{ font-size:18px }
      .card{ padding:18px }
      .controls{flex-direction:column;align-items:stretch}
      .left-controls{width:100%;justify-content:space-between}
    }
  </style>
</head>
<body>
  <main class="card" aria-live="polite">
    <header>
      <div class="title">
        <div class="logo" aria-hidden="true">QT</div>
        <div>
          <h1>랜덤 명언 생성기</h1>
          <p class="lead">버튼을 누르면 새로운 명언이 나타납니다. (API: type.fit)</p>
        </div>
      </div>

      <div class="muted-small" id="status">로딩 전</div>
    </header>

    <section class="quote-wrap fade-in" id="quoteWrap">
      <blockquote id="quote">로딩 중...</blockquote>
      <div class="author" id="author">—</div>
    </section>

    <div class="controls">
      <div class="left-controls">
        <button id="newQuoteBtn" class="primary" title="새 명언">
          <span class="icon">🔁</span>새 명언
        </button>

        <button id="copyBtn" title="명언 복사">
          <span class="icon">📋</span>복사
        </button>

        <button id="tweetBtn" title="트윗으로 공유">
          <span class="icon">🐦</span>트윗
        </button>
      </div>

      <div class="muted-small" style="text-align:right">
        <div>Tip: 스페이스바로도 새 명언을 볼 수 있어요</div>
      </div>
    </div>
  </main>

  <script>
    (function(){
      const API = "<https://type.fit/api/quotes>";
      const quoteEl = document.getElementById("quote");
      const authorEl = document.getElementById("author");
      const newBtn = document.getElementById("newQuoteBtn");
      const copyBtn = document.getElementById("copyBtn");
      const tweetBtn = document.getElementById("tweetBtn");
      const statusEl = document.getElementById("status");
      const wrap = document.getElementById("quoteWrap");

      let quotes = [];
      let lastIndex = -1;

      const fallback = [
        { text: "성공은 최종 목표가 아니라 과정이다. 계속 움직여라.", author: "익명" },
        { text: "작은 습관들이 큰 변화를 만든다.", author: "익명" },
        { text: "배움은 멈추지 않는 자의 특권이다.", author: "익명" }
      ];

      function setStatus(text){
        statusEl.textContent = text;
      }

      function fadeSwitch(newText, newAuthor){
        wrap.classList.remove("fade-in");
        wrap.classList.add("fade-out");
        // 짧게 기다렸다가 텍스트 바꾸고 fade-in
        setTimeout(() => {
          quoteEl.textContent = newText;
          authorEl.textContent = newAuthor ? `— ${newAuthor}` : "— 익명";
          wrap.classList.remove("fade-out");
          wrap.classList.add("fade-in");
        }, 180);
      }

      function pickRandom(){
        if (!quotes || quotes.length === 0) return fallback[Math.floor(Math.random()*fallback.length)];
        if (quotes.length === 1) return quotes[0];
        let idx;
        do {
          idx = Math.floor(Math.random()*quotes.length);
        } while (idx === lastIndex);
        lastIndex = idx;
        return quotes[idx];
      }

      async function fetchQuotes(){
        setStatus("API에서 명언 불러오는 중...");
        try {
          const res = await fetch(API, {cache: "force-cache"});
          if (!res.ok) throw new Error("네트워크 에러");
          const data = await res.json();
          // 정상적 구조인지 확인해서 필터
          quotes = Array.isArray(data)
            ? data.filter(q => q && q.text).map(q => ({text: q.text.trim(), author: (q.author || "").trim()}))
            : [];
          if (quotes.length === 0) throw new Error("빈 데이터");
          setStatus(`명언 ${quotes.length}개 로드됨`);
        } catch (e) {
          console.warn("Quotes fetch failed:", e);
          quotes = fallback;
          setStatus("API 불가 — 기본 문구 사용");
        }
      }

      function showRandom(){
        const q = pickRandom();
        fadeSwitch(q.text, q.author);
      }

      // 이벤트 바인딩
      newBtn.addEventListener("click", showRandom);
      copyBtn.addEventListener("click", async () => {
        const text = `${quoteEl.textContent}\\n${authorEl.textContent}`;
        try {
          await navigator.clipboard.writeText(text);
          setStatus("명언을 클립보드에 복사했어요");
          setTimeout(()=> setStatus(quotes && quotes.length ? `명언 ${quotes.length}개 로드됨` : "기본 문구 사용"), 1400);
        } catch {
          setStatus("복사 실패 — 수동으로 선택해 복사하세요");
        }
      });

      tweetBtn.addEventListener("click", () => {
        const tweetText = `${quoteEl.textContent} ${authorEl.textContent}`;
        const url = `https://twitter.com/intent/tweet?text=${encodeURIComponent(tweetText)}`;
        window.open(url, "_blank", "noopener");
      });

      // 스페이스바로도 새 명언
      window.addEventListener("keydown", (e) => {
        if (e.code === "Space" && document.activeElement.tagName !== "INPUT" && document.activeElement.tagName !== "TEXTAREA") {
          e.preventDefault();
          showRandom();
        }
      });

      // 초기 로드: fetch 후 첫 명언 표시
      (async function init(){
        setStatus("로딩 중...");
        await fetchQuotes();
        showRandom();
      })();

      // accessibility: ARIA live already on main; focus management optional
    })();
  </script>
</body>
</html>

화면 기록 2025-11-09 오후 2.22.51.mov

작동을 시켜보니 익명으로 뜨는 것이 아쉬워서 고쳐보기로 했다

스크린샷 2025-11-09 오후 2.28.58.png

익명인 자료들을 다 지워서 해결하였다

화면 기록 2025-11-09 오후 2.27.56.mov

2. ai를 활용한 인식관련된 웹사이트 제작