몇 번의 시도 끝에 'Hello React!'를 웹에 표시해냈다

 

 

 

중간에 막혔던 부분들 기록...

 

1. 설치 경로 문제

윈도우 바탕화면에 리액트 개발환경 폴더를 만들었더니 리액트 설치가 되지 않았음. 아마 'OneDrive'나 '바탕 화면'이라는 파일명 때문에 그러지 않았을까 싶음. 서브 SSD에 폴더를 이동해서 설치했더니 다음 단계로 넘어감.

 

2. 설치 중 오류 발생 : 리액트 버전 문제

npm error code ERESOLVE
npm error ERESOLVE unable to resolve dependency tree
npm error
npm error While resolving: react-app@0.1.0
npm error Found: react@19.0.0
npm error node_modules/react
npm error   react@"^19.0.0" from the root project
npm error
npm error Could not resolve dependency:
npm error peer react@"^18.0.0" from @testing-library/react@13.4.0
npm error node_modules/@testing-library/react
npm error   @testing-library/react@"^13.0.0" from the root project
npm error
npm error Fix the upstream dependency conflict, or retry
npm error this command with --force or --legacy-peer-deps
npm error to accept an incorrect (and potentially broken) dependency resolution.
npm error
npm error

 

ChatGPT 사용하여 원인 찾아보니 리액트 버전 문제일 수 있다고 하여 아래 명령어 사용하여 다운그레이드.

npm install react@18 react-dom@18

 

3. 설치 후 'npm start' 후 에러 발생 : Node.js 호환성 문제

Error: error:0308010C:digital envelope routines::unsupported
    at new Hash (node:internal/crypto/hash:79:19)
    at Object.createHash (node:crypto:139:10)
    at module.exports

 

위 에러 메시지 원인을 GPT로 찾아보니 Node.js의 최신 버전(22.12.0)에서 OpenSSL 3과 Webpack의 호환성 문제 때문에 발생했다고 했다. NODE_OPTIONS 환경 변수를 설정하여 OpenSSL 3의 새로운 요구사항을 우회하라고 해서 아래 명령어 적용.

$env:NODE_OPTIONS="--openssl-legacy-provider"
npm start

 

 

4. 패키지가 설치되지 않아 오류 발생

ERROR in ./src/reportWebVitals.js 5:4-24
Module not found: Error: Can't resolve 'web-vitals' in...

 

'web-vitals' 재설치하여 해결

npm install web-vitals

마우스 호버링 시 파스텔 톤의 녹색으로 강조되는 효과 추가

<!DOCTYPE html>
<html lang="ko">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>표 생성기</title>
  <style>
    body {
      font-family: Arial, sans-serif;
      text-align: center;
      margin: 20px;
    }

    .input-container {
      margin-bottom: 20px;
    }

    input[type="number"] {
      padding: 10px;
      font-size: 1rem;
      width: 80px;
      margin: 5px;
      border: 1px solid #ccc;
      border-radius: 5px;
    }

    button {
      padding: 10px 20px;
      font-size: 1rem;
      background-color: #007aff;
      color: white;
      border: none;
      border-radius: 5px;
      cursor: pointer;
    }

    button:hover {
      background-color: #005ecb;
    }

    table {
      margin: 20px auto;
      border-collapse: collapse;
      width: auto;
    }

    td {
      border: 1px solid #ddd;
      padding: 10px;
      text-align: center;
      transition: background-color 0.3s ease; /* 부드러운 강조 효과 */
    }

    td:hover {
      background-color: #b2f2bb; /* 파스텔 톤의 녹색 */
    }
  </style>
</head>
<body>
  <h1>표 생성기</h1>

  <div class="input-container">
    <label for="rows">행:</label>
    <input type="number" id="rows" min="1" placeholder="행 수 입력">
    <label for="columns">열:</label>
    <input type="number" id="columns" min="1" placeholder="열 수 입력">
    <button onclick="generateTable()">표 생성</button>
  </div>

  <div id="table-container"></div>

  <script>
    function generateTable() {
      // 입력 값 가져오기
      const rows = parseInt(document.getElementById("rows").value);
      const columns = parseInt(document.getElementById("columns").value);

      // 유효성 검사
      if (isNaN(rows) || isNaN(columns) || rows <= 0 || columns <= 0) {
        alert("유효한 숫자를 입력하세요.");
        return;
      }

      // 기존 표 제거
      const tableContainer = document.getElementById("table-container");
      tableContainer.innerHTML = "";

      // 새 표 생성
      const table = document.createElement("table");
      for (let i = 0; i < rows; i++) {
        const tr = document.createElement("tr");
        for (let j = 0; j < columns; j++) {
          const cell = document.createElement("td");
          cell.textContent = `셀 ${i + 1}-${j + 1}`;
          tr.appendChild(cell);
        }
        table.appendChild(tr);
      }

      // 표 추가
      tableContainer.appendChild(table);
    }
  </script>
</body>
</html>
<!DOCTYPE html>
<html lang="ko">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>할 일 목록</title>
  <style>
    body {
      font-family: Arial, sans-serif;
      margin: 20px;
      padding: 0;
      line-height: 1.6;
    }

    h1 {
      text-align: center;
      margin-bottom: 20px;
    }

    .input-container {
      display: flex;
      justify-content: center;
      margin-bottom: 20px;
    }

    input[type="text"] {
      padding: 10px;
      font-size: 1rem;
      border: 1px solid #ccc;
      border-radius: 5px;
      width: 300px;
    }

    button {
      padding: 10px 20px;
      font-size: 1rem;
      background-color: #007aff;
      color: white;
      border: none;
      border-radius: 5px;
      cursor: pointer;
      margin-left: 10px;
    }

    button:hover {
      background-color: #005ecb;
    }

    ul {
      list-style-type: none;
      padding: 0;
      margin: 0;
    }

    li {
      display: flex;
      align-items: center;
      background-color: #f5f5f5;
      margin: 5px 0;
      padding: 10px;
      border: 1px solid #ddd;
      border-radius: 5px;
      justify-content: space-between;
    }

    .task-text {
      flex-grow: 1;
      margin-left: 10px;
    }

    .completed {
      text-decoration: line-through;
      color: #ccc;
    }

    .check-btn {
      background-color: #4caf50;
      color: white;
      border: none;
      border-radius: 50%;
      cursor: pointer;
      width: 30px;
      height: 30px;
      display: flex;
      align-items: center;
      justify-content: center;
      font-size: 1.2rem;
      line-height: 1;
    }

    .check-btn:hover {
      background-color: #45a049;
    }

    .particle {
      position: absolute;
      border-radius: 50%; /* 원형 */
      opacity: 1;
      animation: explode 1s ease-out forwards, fade-out 1.5s ease-out forwards;
    }

    @keyframes explode {
      0% {
        transform: translate(0, 0) scale(1);
      }
      50% {
        transform: scale(1.5); /* 크기 확장 */
      }
      100% {
        transform: translate(var(--x), var(--y)) scale(0.5); /* 최종 위치 */
      }
    }

    @keyframes fade-out {
      0% {
        opacity: 1;
      }
      100% {
        opacity: 0;
      }
    }
  </style>
</head>
<body>
  <h1>할 일 목록</h1>

  <div class="input-container">
    <input type="text" id="todoInput" placeholder="할 일을 입력하세요">
    <button onclick="addTask()">할 일 추가</button>
  </div>

  <ul id="todoList"></ul>

  <script>
    function addTask() {
      const input = document.getElementById("todoInput");
      const task = input.value.trim();

      if (task === "") {
        alert("할 일을 입력하세요!");
        return;
      }

      // 새로운 할 일 생성
      const listItem = document.createElement("li");

      // 체크 버튼
      const checkButton = document.createElement("button");
      checkButton.textContent = "✔";
      checkButton.className = "check-btn";
      checkButton.onclick = function () {
        completeTask(listItem, taskSpan);
      };

      // 할 일 텍스트
      const taskSpan = document.createElement("span");
      taskSpan.textContent = task;
      taskSpan.className = "task-text";

      // 구성
      listItem.appendChild(checkButton);
      listItem.appendChild(taskSpan);
      document.getElementById("todoList").appendChild(listItem);

      // 입력 필드 초기화
      input.value = "";
    }

    function completeTask(listItem, taskSpan) {
      taskSpan.classList.add("completed");

      // 파티클 애니메이션 생성
      const particleCount = 50; // 파티클 수
      const rect = listItem.getBoundingClientRect();
      const centerX = rect.left + rect.width / 2;
      const centerY = rect.top + rect.height / 2;

      for (let i = 0; i < particleCount; i++) {
        const particle = document.createElement("div");
        particle.className = "particle";

        // 초기 위치 설정
        particle.style.left = `${centerX}px`;
        particle.style.top = `${centerY}px`;

        // 무작위 크기, 색상 설정
        const size = Math.random() * 8 + 4; // 크기 (4~12px)
        particle.style.width = `${size}px`;
        particle.style.height = `${size}px`;
        particle.style.backgroundColor = getRandomColor();

        // 애니메이션 속성 설정
        const angle = Math.random() * 2 * Math.PI; // 방향 (라디안)
        const distance = Math.random() * 120 + 50; // 거리
        particle.style.setProperty("--x", `${distance * Math.cos(angle)}px`);
        particle.style.setProperty("--y", `${distance * Math.sin(angle)}px`);

        // 파티클 제거
        setTimeout(() => {
          particle.remove();
        }, 1500);

        document.body.appendChild(particle);
      }
    }

    function getRandomColor() {
      const colors = ["#FF5722", "#FF9800", "#FFC107", "#4CAF50", "#03A9F4", "#9C27B0", "#E91E63"];
      return colors[Math.floor(Math.random() * colors.length)];
    }

    document.getElementById("todoInput").addEventListener("keypress", function (e) {
      if (e.key === "Enter") {
        addTask();
      }
    });
  </script>
</body>
</html>
<!DOCTYPE html>
<html lang="ko">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>노드 추가</title>
  <style>
    body {
      font-family: Arial, sans-serif;
      margin: 20px;
      padding: 0;
    }

    .input-container {
      margin-bottom: 20px;
    }

    input[type="text"] {
      padding: 10px;
      font-size: 1rem;
      border: 1px solid #ccc;
      border-radius: 5px;
      width: 300px;
    }

    button {
      padding: 10px 20px;
      font-size: 1rem;
      background-color: #007aff;
      color: white;
      border: none;
      border-radius: 5px;
      cursor: pointer;
      margin-left: 10px;
    }

    button:hover {
      background-color: #005ecb;
    }

    ul {
      list-style-type: none;
      padding: 0;
    }

    li {
      background-color: #f5f5f5;
      margin: 5px 0;
      padding: 10px;
      border: 1px solid #ddd;
      border-radius: 5px;
      display: flex;
      justify-content: space-between;
      align-items: center;
    }

    .content {
      flex-grow: 1; /* 텍스트 영역 확장 */
      margin-right: 10px; /* 버튼과 간격 조정 */
    }

    .timestamp {
      font-size: 0.8rem;
      color: #555;
      margin-right: 10px;
    }

    .delete-btn {
      background-color: #ff4d4f;
      color: white;
      border: none;
      border-radius: 5px;
      cursor: pointer;
      padding: 5px 10px;
      font-size: 0.9rem;
    }

    .delete-btn:hover {
      background-color: #cc0000;
    }
  </style>
</head>
<body>
  <h1>Web Programming</h1>
  <p>공부할 주제를 기록해 보세요</p>
  <div class="input-container">
    <input type="text" id="textInput" placeholder="텍스트를 입력하세요" onkeypress="handleKeyPress(event)">
    <button onclick="addNode()">추가</button>
  </div>
  <ul id="nodeList"></ul>

  <script>
    function addNode() {
      // 입력 필드에서 값 가져오기
      const textInput = document.getElementById("textInput");
      const text = textInput.value.trim();

      // 빈 문자열 처리
      if (text === "") {
        alert("텍스트를 입력하세요!");
        return;
      }

      // 현재 날짜와 시간 가져오기
      const now = new Date();
      const month = now.getMonth() + 1; // 월 (0부터 시작하므로 +1)
      const date = now.getDate(); // 일
      const dayNames = ["일", "월", "화", "수", "목", "금", "토"];
      const day = dayNames[now.getDay()]; // 요일
      const hours = now.getHours(); // 시
      const minutes = String(now.getMinutes()).padStart(2, "0"); // 분
      const period = hours >= 12 ? "오후" : "오전"; // 오전/오후
      const displayHours = hours % 12 === 0 ? 12 : hours % 12; // 12시간 형식
      const timestamp = `${month}월 ${date}일 ${day}요일 ${period} ${displayHours}시 ${minutes}분`;

      // 새로운 리스트 항목 생성
      const newNode = document.createElement("li");

      // 텍스트 노드 추가
      const textSpan = document.createElement("span");
      textSpan.textContent = text;
      textSpan.className = "content";

      // 시간 표시 노드 추가
      const timeSpan = document.createElement("span");
      timeSpan.textContent = timestamp;
      timeSpan.className = "timestamp";

      // 삭제 버튼 생성 및 추가
      const deleteButton = document.createElement("button");
      deleteButton.textContent = "삭제";
      deleteButton.className = "delete-btn";
      deleteButton.onclick = function () {
        newNode.remove(); // 노드 삭제
      };

      // 항목 구성
      newNode.appendChild(textSpan); // 텍스트
      newNode.appendChild(timeSpan); // 시간
      newNode.appendChild(deleteButton); // 삭제 버튼

      // 리스트에 추가 (최상단에 추가)
      const nodeList = document.getElementById("nodeList");
      nodeList.insertBefore(newNode, nodeList.childNodes[0]);

      // 입력 필드 초기화
      textInput.value = "";
    }

    function handleKeyPress(event) {
      // Enter 키인지 확인
      if (event.key === "Enter") {
        addNode();
        event.preventDefault(); // Enter 키의 기본 동작(폼 제출 방지)을 막음
      }
    }
  </script>
</body>
</html>
<!DOCTYPE html>
<html lang="ko">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Read More</title>
</head>
<body>

  <div id="container">
    <h1>DOM을 공부합시다</h1>
    <a href="#" onclick="addP(); this.onclick='';">더 보기</a>
    <div id="info"></div>
  </div>

  <script>
    function addP() {
      var newP = document.createElement("p");
      var txtNode = document.createTextNode("DOM은 document object model의 줄임말입니다.");
      newP.appendChild(txtNode);
      document.getElementById("info").appendChild(newP);
    }
  </script>
</body>
</html>
<!DOCTYPE html>
<html lang="ko">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>사진 갤러리</title>
  <style>
    /* 기본 스타일 */
    body {
      margin: 0;
      font-family: Arial, sans-serif;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      background-color: #f0f0f0;
    }

    h1 {
      margin: 20px;
    }

    /* 갤러리 스타일 */
    .gallery {
      display: grid;
      grid-template-columns: repeat(3, 1fr);
      gap: 10px;
      max-width: 900px;
    }

    .gallery img {
      width: 100%;
      aspect-ratio: 1 / 1; /* 정사각형 유지 */
      object-fit: cover;
      border-radius: 5px;
      cursor: pointer;
      transition: transform 0.2s ease;
    }

    .gallery img:hover {
      transform: scale(1.05);
    }

    /* 라이트박스 스타일 */
    .lightbox {
      display: none;
      position: fixed;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      background-color: rgba(0, 0, 0, 0.8);
      align-items: center;
      justify-content: center;
      z-index: 10;
    }

    .lightbox img {
      max-width: 90%;
      max-height: 90%;
      border-radius: 5px;
      box-shadow: 0 0 20px rgba(255, 255, 255, 0.8);
    }

    .lightbox:active {
      display: flex;
    }

    .lightbox .close {
      position: absolute;
      top: 20px;
      right: 20px;
      font-size: 30px;
      color: white;
      cursor: pointer;
      z-index: 20;
    }
  </style>
</head>
<body>
  <h1>사진 갤러리</h1>
  <div class="gallery">
    <img src="image/1.jpg" alt="사진 1">
    <img src="image/2.jpg" alt="사진 2">
    <img src="image/3.jpg" alt="사진 3">
    <img src="image/4.jpg" alt="사진 4">
    <img src="image/5.jpg" alt="사진 5">
    <img src="image/6.jpg" alt="사진 6">
    <img src="image/7.jpg" alt="사진 7">
    <img src="image/8.jpg" alt="사진 8">
    <img src="image/9.jpg" alt="사진 9">
  </div>

  <!-- 라이트박스 -->
  <div class="lightbox" id="lightbox">
    <span class="close" onclick="closeLightbox()">×</span>
    <img id="lightbox-img" src="" alt="클릭한 이미지">
  </div>

  <script>
    // 라이트박스 열기
    const galleryImages = document.querySelectorAll('.gallery img');
    const lightbox = document.getElementById('lightbox');
    const lightboxImg = document.getElementById('lightbox-img');

    galleryImages.forEach(image => {
      image.addEventListener('click', () => {
        lightbox.style.display = 'flex';
        lightboxImg.src = image.src;
      });
    });

    // 라이트박스 닫기
    function closeLightbox() {
      lightbox.style.display = 'none';
    }

    // 라이트박스 클릭 시 닫기
    lightbox.addEventListener('click', (e) => {
      if (e.target === lightbox || e.target.classList.contains('close')) {
        closeLightbox();
      }
    });
  </script>
</body>
</html>

 

이번에도 역시 chatGPT를 십분 활용하여 만들었다. 여기에 웹에서 직접 사진을 추가하는 기능을 넣어보고도 싶다.

<!DOCTYPE html>
<html lang="ko">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>원형 파티클</title>
  <style>
    body {
      font-family: Arial, sans-serif;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      height: 100vh;
      margin: 0;
      background-color: #f5f5f5;
      overflow: hidden;
    }

    .container-wrapper {
      position: relative;
      width: 300px;
      height: 300px;
    }

    /* 방사형 애니메이션 */
    .ripple-effect {
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      border-radius: 50%;
      background: conic-gradient(
        red, orange, yellow, green, cyan, blue, violet, red
      );
      animation: rotate 4s linear infinite;
      filter: blur(10px);
    }

    @keyframes rotate {
      from {
        transform: rotate(0deg);
      }
      to {
        transform: rotate(360deg);
      }
    }

    /* 컨테이너 */
    .container {
      position: relative;
      text-align: center;
      width: 100%;
      height: 100%;
      border-radius: 50%;
      background-color: #e0f7fa;
      border: 2px solid #333;
      display: flex;
      flex-direction: column;
      justify-content: center;
      align-items: center;
      box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2);
      z-index: 1;
    }

    .container h1 {
      font-size: 1.5rem;
      margin: 0;
    }

    .container .days {
      font-size: 2.5rem;
      font-weight: bold;
      color: #d32f2f;
      margin: 10px 0;
    }

    .container p {
      font-size: 1rem;
      margin: 5px 0;
    }

    @keyframes particleMove {
      0% {
        transform: translate(0, 0) scale(1);
        opacity: 1;
      }
      100% {
        transform: translate(var(--x), var(--y)) scale(0.5);
        opacity: 0;
      }
    }

    /* 날짜 입력창 */
    .input-wrapper {
      margin-bottom: 20px;
      text-align: center;
    }

    .input-wrapper input {
      padding: 8px;
      font-size: 1rem;
      border: 1px solid #ccc;
      border-radius: 4px;
    }

    .input-wrapper button {
      padding: 8px 16px;
      font-size: 1rem;
      margin-left: 10px;
      background-color: #007aff;
      color: white;
      border: none;
      border-radius: 4px;
      cursor: pointer;
    }

    .input-wrapper button:hover {
      background-color: #005ecb;
    }
  </style>
</head>
<body>
  <div class="input-wrapper">
    <input type="date" id="startDateInput" />
    <button onclick="applyStartDate()">날짜 적용</button>
  </div>
  <div class="container-wrapper">
    <div class="ripple-effect"></div>
    <div class="container">
      <h1>책 읽기</h1>
      <div class="days" id="days">0</div>
      <p id="message">일 연속으로 책 읽기를 달성했군요.</p>
      <p>축하합니다!</p>
    </div>
  </div>

  <script>
    let startDate = new Date(); // 기본 시작 날짜를 오늘로 설정
    let particleAngle = 0; // 초기 파티클 각도

    // 날짜 계산 및 표시
    function updateDays() {
      const currentDate = new Date();
      const diffTime = currentDate - startDate;
      const diffDays = Math.max(Math.floor(diffTime / (1000 * 60 * 60 * 24)), 0); // 최소 0일
      document.getElementById("days").textContent = diffDays;
      document.getElementById("message").textContent = `${diffDays}일 연속으로 책 읽기를 달성했군요.`;
    }

    // 날짜 입력 적용
    function applyStartDate() {
      const inputDate = document.getElementById("startDateInput").value;
      if (inputDate) {
        startDate = new Date(inputDate);
        updateDays();
      }
    }
    updateDays(); // 초기 날짜 표시
  </script>
</body>
</html>

자바스크립트의 Date 객체를 활용하여 기본 틀을 만들고 ChatGPT로 디지털 시계와 아날로그 시계를 구현해보았다. 

초침의 경우 딱딱 끊어지지 않고 부드럽게 움직이도록 했다. 

<!DOCTYPE html>
<html lang="ko">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>디지털 및 아날로그 시계</title>
  <style>
    body {
      font-family: Arial, sans-serif;
      text-align: center;
      margin-top: 50px;
    }
    .clock {
      font-size: 2rem;
      font-weight: bold;
      color: #007aff;
    }
    canvas {
      display: block;
      margin: 20px auto;
      background: #f5f5f5;
      border: 2px solid #333;
      border-radius: 50%;
    }
  </style>
</head>
<body>
  <h1>디지털 및 아날로그 시계</h1>
  <p class="clock" id="clock"></p>
  <canvas id="analogClock" width="300" height="300"></canvas>

  <script>
    // 디지털 시계 업데이트
    function updateClock() {
      const now = new Date();
      const hours = String(now.getHours()).padStart(2, '0');
      const minutes = String(now.getMinutes()).padStart(2, '0');
      const seconds = String(now.getSeconds()).padStart(2, '0');

      document.getElementById("clock").textContent =
        `현재 시각은 ${hours}:${minutes}:${seconds}`;
    }

    // 아날로그 시계 그리기
    function drawAnalogClock() {
      const now = new Date();
      const canvas = document.getElementById("analogClock");
      const ctx = canvas.getContext("2d");
      const centerX = canvas.width / 2;
      const centerY = canvas.height / 2;
      const radius = canvas.width / 2 - 10;

      // 캔버스 초기화
      ctx.clearRect(0, 0, canvas.width, canvas.height);

      // 시계 테두리
      ctx.beginPath();
      ctx.arc(centerX, centerY, radius, 0, Math.PI * 2);
      ctx.fillStyle = "#fff";
      ctx.fill();
      ctx.strokeStyle = "#333";
      ctx.lineWidth = 4;
      ctx.stroke();

      // 숫자 표시
      ctx.font = "16px Arial";
      ctx.textAlign = "center";
      ctx.textBaseline = "middle";
      for (let num = 1; num <= 12; num++) {
        const angle = (Math.PI / 6) * (num - 3);
        const x = centerX + Math.cos(angle) * (radius - 30);
        const y = centerY + Math.sin(angle) * (radius - 30);
        ctx.fillStyle = "#333";
        ctx.fillText(num, x, y);
      }

      // 시간 계산
      const ms = now.getMilliseconds();
      const seconds = now.getSeconds() + ms / 1000;
      const minutes = now.getMinutes() + seconds / 60;
      const hours = now.getHours() % 12 + minutes / 60;

      // 시침
      const hourAngle = (Math.PI / 6) * hours - Math.PI / 2;
      drawHand(ctx, centerX, centerY, hourAngle, radius * 0.5, 6);

      // 분침
      const minuteAngle = (Math.PI / 30) * minutes - Math.PI / 2;
      drawHand(ctx, centerX, centerY, minuteAngle, radius * 0.75, 4);

      // 초침 (부드럽게 움직임)
      const secondAngle = (Math.PI / 30) * seconds - Math.PI / 2;
      drawHand(ctx, centerX, centerY, secondAngle, radius * 0.85, 2, "#f00");
    }

    // 시계 바늘 그리기 함수
    function drawHand(ctx, x, y, angle, length, width, color = "#333") {
      ctx.beginPath();
      ctx.lineWidth = width;
      ctx.lineCap = "round";
      ctx.strokeStyle = color;
      ctx.moveTo(x, y);
      ctx.lineTo(
        x + Math.cos(angle) * length,
        y + Math.sin(angle) * length
      );
      ctx.stroke();
    }

    // 애니메이션 루프
    function animate() {
      updateClock();
      drawAnalogClock();
      requestAnimationFrame(animate);
    }

    // 애니메이션 시작
    animate();
  </script>
</body>
</html>
<!DOCTYPE html>
<html lang="ko">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>숫자 비교</title>
</head>
<body>
  <h1>숫자 비교</h1>
  <p>두 숫자를 비교하여 더 큰 숫자를 알림창에 표시합니다.</p>
  <button onclick="compareNumbers()">숫자 비교하기</button>
  <script>
    function findLargerNumber(num1, num2) {
      if (num1 === num2) {
        alert("두 수는 같습니다.");
      } else if (num1 > num2) {
        alert(`더 큰 숫자는 ${num1}입니다.`);
      } else {
        alert(`더 큰 숫자는 ${num2}입니다.`);
      }
    }

    function compareNumbers() {
      const num1 = Number(prompt("첫 번째 숫자를 입력하세요:"));
      const num2 = Number(prompt("두 번째 숫자를 입력하세요:"));

      findLargerNumber(num1, num2);
    }
  </script>
</body>
</html>

입력받은 두 수가 같으면 곱하기, 다르면 덧셈을 수행하는 코드를 작성해 보는 실습

<!DOCTYPE html>
<html lang="ko">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>sumMulti() 함수 작성하기</title>
</head>
<body>
  <h1>sumMulti 함수</h1>
  <p>두 수를 입력받아 결과에 따른 연산</p>

  <label for="num1">첫 번째 숫자:</label>
  <input type="number" id="num1">
  <br><br>

  <label for="num2">두 번째 숫자:</label>
  <input type="number" id="num2">
  <br><br>

  <button onclick="runSumMulti()">결과 확인</button>
  <p id="result" style="margin-top: 20px; font-weight: bold; color: blue;"></p>

  <script>
    function sumMulti(x, y) {
      let resultText = "";
      if (x === y) {
        resultText = `두 수가 같습니다. 결과는 곱하기입니다: ${x * y}`;
        console.log(resultText);
      } else {
        resultText = `두 수가 다릅니다. 결과는 더하기입니다: ${x + y}`;
        console.log(resultText);
      }
      return resultText;
    }

    function runSumMulti() {
      const num1 = Number(document.getElementById("num1").value);
      const num2 = Number(document.getElementById("num2").value);

      const resultMessage = sumMulti(num1, num2);
 
      document.getElementById("result").textContent = resultMessage;
    }
  </script>
</body>
</html>

 

백틱(`)을 작은 따옴표(')로 해서 헤맸음.

+ Recent posts