Skip to main content
Summary

자바스크립트는 브라우저와 함께 일한다

지금까지 우리는 변수, 조건문, 반복문, 함수, 배열, 객체, DOM, 이벤트를 배웠습니다. 이제부터 자바스크립트가 더 실용적으로 느껴지는 구간으로 들어갑니다.

자바스크립트 혼자서도 계산하고 판단하는 일을 잘합니다. 하지만 웹페이지에서 실제로 쓸 만한 기능을 만들려면 브라우저가 제공하는 기능과 만나야 합니다.

예를 들어 이런 일들입니다.

  • 현재 시간을 화면에 보여 주기

  • 3초 뒤 안내 문구 띄우기

  • 1초마다 남은 시간 줄이기

  • 오늘의 점심 메뉴를 무작위로 고르기

  • 새로고침해도 사용자 이름 남겨 두기

이 장에서 다룰 기능은 대부분 따로 설치하지 않아도 됩니다. 브라우저가 이미 가지고 있는 도구를 자바스크립트로 꺼내 쓰는 방식입니다.

브라우저가 제공하는 편리한 기능 쓰기AI 생성 이미지

Date로 현재 시간 다루기

Date는 날짜와 시간을 다루는 자바스크립트의 기본 도구입니다. new Date()를 실행하면 지금 이 순간의 날짜와 시간을 담은 값이 만들어집니다. 자바스크립트는 날짜와 시간을 내부적으로 아주 긴 숫자, 즉 1970년 1월 1일 0시 0분 0초를 기준으로 한 밀리초 값으로 다룹니다.1

먼저 콘솔에서 실행해 보겠습니다.

const now = new Date();
console.log(now);

현재 날짜와 시간이 출력됩니다. 그대로 보면 조금 복잡해 보일 수 있습니다. 그래서 필요한 부분만 꺼내 씁니다.

const now = new Date();

console.log(now.getFullYear()); // 연도
console.log(now.getMonth());    // 월, 0부터 시작
console.log(now.getDate());     // 날짜
console.log(now.getDay());      // 요일, 일요일이 0
console.log(now.getHours());    // 시
console.log(now.getMinutes());  // 분
console.log(now.getSeconds());  // 초

여기서 초보자가 자주 헷갈리는 부분은 getMonth()입니다. 1월이 1이 아니라 0입니다. 그래서 사람이 읽는 월로 보여 주려면 보통 1을 더합니다.

const now = new Date();
const month = now.getMonth() + 1;

console.log(month + "월");

요일도 숫자로 나옵니다. 일요일은 0, 월요일은 1, 토요일은 6입니다. 숫자만 보여 주면 의미가 약하므로 배열과 함께 쓰면 좋습니다.

const now = new Date();
const days = ["일", "월", "화", "수", "목", "금", "토"];
const dayName = days[now.getDay()];

console.log("오늘은 " + dayName + "요일입니다.");

배열의 인덱스가 0부터 시작한다는 점이 여기서 자연스럽게 쓰입니다.

작은 시계 만들기

이번에는 화면에 현재 시간을 표시해 보겠습니다. 아래 코드를 time.html 같은 파일로 저장한 뒤 브라우저에서 열어 보세요.

<p id="clock">시간을 불러오는 중...</p>

<script>
  const clock = document.querySelector("#clock");

  function showTime() {
    const now = new Date();
    const hour = now.getHours();
    const minute = now.getMinutes();
    const second = now.getSeconds();

    clock.textContent = hour + ":" + minute + ":" + second;
  }

  showTime();
</script>

이 코드는 현재 시간을 한 번 보여 줍니다. 하지만 시계라면 시간이 계속 바뀌어야 합니다. 이때 필요한 기능이 setInterval()입니다.

<p id="clock">시간을 불러오는 중...</p>

<script>
  const clock = document.querySelector("#clock");

  function showTime() {
    const now = new Date();
    const hour = now.getHours();
    const minute = now.getMinutes();
    const second = now.getSeconds();

    clock.textContent = hour + ":" + minute + ":" + second;
  }

  showTime();
  setInterval(showTime, 1000);
</script>

setInterval(showTime, 1000)은 "showTime 함수를 1000밀리초마다 실행해 주세요"라는 뜻입니다. 1000밀리초는 1초입니다.

여기서 중요한 점이 있습니다.

setInterval(showTime(), 1000); // 좋지 않음

이렇게 쓰면 showTime 함수를 나중에 실행하는 것이 아니라 지금 바로 실행한 결과를 넘기게 됩니다. 이벤트에서 배운 것과 비슷합니다. 나중에 실행할 함수는 괄호 없이 이름만 전달합니다.

setInterval(showTime, 1000); // 좋음

마감일까지 남은 시간 계산하기

날짜는 서로 뺄 수 있습니다. 정확히 말하면 날짜를 밀리초 숫자로 바꾼 뒤 차이를 계산합니다. 이 방식으로 마감일까지 며칠 남았는지 구할 수 있습니다.

const today = new Date();
const deadline = new Date(2026, 11, 31);

const diff = deadline.getTime() - today.getTime();
const daysLeft = Math.ceil(diff / (1000 * 60 * 60 * 24));

console.log("마감일까지 " + daysLeft + "일 남았습니다.");

여기서 new Date(2026, 11, 31)은 2026년 12월 31일을 뜻합니다. 조금 이상해 보이지만, 날짜를 만들 때도 월은 0부터 시작합니다. 그래서 1월은 0, 12월은 11입니다.

1000 * 60 * 60 * 24는 하루를 밀리초로 바꾼 값입니다.

  • 1000밀리초 = 1초

  • 60초 = 1분

  • 60분 = 1시간

  • 24시간 = 하루

Math.ceil()은 소수점이 있으면 올림합니다. 3.2일이 남았다면 실제 안내에서는 "4일 남음"이라고 보여 주는 편이 자연스러울 때가 많습니다.

Math.random()으로 무작위 선택하기

이번에는 랜덤 기능을 보겠습니다. Math.random()은 0 이상 1 미만의 무작위 숫자를 만듭니다. 0은 나올 수 있지만 1은 나오지 않습니다.2

console.log(Math.random());

실행할 때마다 이런 숫자가 나옵니다.

0.3849281...
0.9021437...
0.0571234...

그런데 우리는 보통 이런 소수보다 "배열에서 하나 고르기"가 필요합니다. 배열 인덱스는 정수여야 하므로 Math.floor()를 함께 씁니다.

const messages = ["천천히 해도 괜찮아요", "오늘도 한 줄이면 충분합니다", "막히면 쉬었다가 다시 보세요"];

const randomIndex = Math.floor(Math.random() * messages.length);
console.log(messages[randomIndex]);

흐름을 나누면 이렇습니다.

Math.random() * messages.length

배열 길이가 3이라면 0 이상 3 미만의 숫자가 만들어집니다. 예를 들어 2.71이 나올 수 있습니다.

Math.floor(2.71)

Math.floor()는 소수점을 버려 2로 만듭니다. 그래서 가능한 인덱스는 0, 1, 2가 됩니다. 배열 길이가 3일 때 마지막 인덱스가 2였다는 점과 맞아떨어집니다.

주사위도 만들 수 있습니다.

const dice = Math.floor(Math.random() * 6) + 1;
console.log("주사위 결과: " + dice);

Math.random() * 6은 0 이상 6 미만입니다. Math.floor()를 거치면 0부터 5까지가 됩니다. 주사위는 1부터 6까지 필요하므로 마지막에 1을 더합니다.

오늘의 점심 메뉴 선택기도 같은 원리입니다.

const menus = ["김밥", "비빔밥", "쌀국수", "샐러드", "돈가스"];
const index = Math.floor(Math.random() * menus.length);

console.log("오늘의 점심 추천: " + menus[index]);

단, Math.random()은 재미있는 추천이나 간단한 게임에는 충분하지만 보안이 필요한 추첨, 비밀번호, 인증번호 생성에는 적합하지 않습니다. 그런 목적에는 더 안전한 별도 기능을 사용해야 합니다.2

setTimeout()과 setInterval()로 시간을 두고 실행하기

브라우저에는 "나중에 실행해 주세요"라고 부탁하는 기능이 있습니다. 대표적으로 setTimeout()과 setInterval()입니다.

setTimeout()은 일정 시간이 지난 뒤 한 번만 실행합니다.3

setTimeout(function () {
  console.log("3초가 지났습니다.");
}, 3000);

3000밀리초는 3초입니다. 이 코드는 "3초 뒤에 콘솔에 문장을 출력해 주세요"라는 뜻입니다.

화면 문구도 바꿀 수 있습니다.

<p id="message">잠시만 기다려 주세요.</p>

<script>
  const message = document.querySelector("#message");

  setTimeout(function () {
    message.textContent = "준비가 끝났습니다.";
  }, 2000);
</script>

반면 setInterval()은 일정 시간마다 반복 실행합니다. 시계, 카운트다운, 자동 저장 안내처럼 주기적으로 갱신해야 하는 일에 어울립니다.

setInterval(function () {
  console.log("1초마다 실행됩니다.");
}, 1000);

반복을 멈추고 싶다면 타이머 번호를 저장해 두었다가 clearInterval()을 사용합니다.

let count = 5;

const timerId = setInterval(function () {
  console.log(count);
  count = count - 1;

  if (count === 0) {
    clearInterval(timerId);
    console.log("끝!");
  }
}, 1000);

여기서 timerId는 브라우저가 타이머를 구분하기 위해 돌려주는 값입니다. "방금 만든 반복 타이머를 멈춰 주세요"라고 말할 때 필요합니다.

또 하나 기억할 점이 있습니다. 타이머 시간은 정확한 약속이라기보다 요청에 가깝습니다. 브라우저가 바쁘거나 탭이 뒤에 있으면 실행이 조금 늦어질 수 있습니다.3

localStorage로 새로고침 후에도 값 남기기

웹페이지는 보통 새로고침하면 화면 상태가 초기화됩니다. 입력했던 이름이나 할 일 목록도 사라질 수 있습니다. 이때 간단한 값을 브라우저에 저장하고 싶다면 localStorage를 사용할 수 있습니다.

localStorage는 같은 사이트에서 다시 열었을 때도 남아 있는 작은 저장 공간입니다. 브라우저를 껐다 켜도 보통 유지됩니다.4

가장 기본 사용법은 세 가지입니다.

localStorage.setItem("userName", "민지");

const savedName = localStorage.getItem("userName");
console.log(savedName);

localStorage.removeItem("userName");
  • setItem()은 저장합니다.

  • getItem()은 꺼냅니다.

  • removeItem()은 삭제합니다.

간단한 이름 저장 예제를 만들어 보겠습니다.

<input id="nameInput" placeholder="이름을 입력하세요">
<button id="saveButton">저장</button>
<p id="greeting"></p>

<script>
  const nameInput = document.querySelector("#nameInput");
  const saveButton = document.querySelector("#saveButton");
  const greeting = document.querySelector("#greeting");

  const savedName = localStorage.getItem("userName");

  if (savedName !== null) {
    greeting.textContent = savedName + "님, 다시 오셨군요.";
  }

  saveButton.addEventListener("click", function () {
    const userName = nameInput.value;

    localStorage.setItem("userName", userName);
    greeting.textContent = userName + "님, 저장했습니다.";
  });
</script>

이제 이름을 입력하고 저장한 뒤 새로고침해 보세요. 문구가 남아 있다면 성공입니다.

주의할 점은 localStorage가 모든 값을 문자열로 저장한다는 것입니다.4 숫자 3을 저장해도 꺼내면 문자열 "3"입니다.

localStorage.setItem("count", 3);

const count = localStorage.getItem("count");
console.log(count); // "3"

할 일 목록처럼 배열을 저장하려면 JSON.stringify()와 JSON.parse()를 함께 씁니다. JSON은 배열이나 객체를 저장 가능한 문자열 모양으로 바꾸는 형식이라고 생각하면 됩니다.

const todos = ["책 읽기", "물 마시기", "운동하기"];

localStorage.setItem("todos", JSON.stringify(todos));

const savedTodos = JSON.parse(localStorage.getItem("todos"));
console.log(savedTodos[0]);

처음에는 이름 하나를 저장하는 것만으로 충분합니다. 배열 저장은 할 일 목록 프로젝트에서 다시 만나면 더 자연스럽게 이해됩니다.

편리하지만 한계도 있다

브라우저 기능은 매우 편리합니다. 하지만 아무 값이나 마음대로 저장하고, 아무 기능이나 조용히 실행할 수 있는 것은 아닙니다.

첫째, 개인정보를 조심해야 합니다. localStorage에는 비밀번호, 주민등록번호, 결제 정보처럼 민감한 값을 저장하지 않는 편이 안전합니다. 같은 브라우저를 쓰는 사람이 볼 수도 있고, 웹사이트 코드가 접근할 수도 있습니다.

둘째, 브라우저 설정의 영향을 받습니다. 사용자가 쿠키나 사이트 데이터 저장을 막아 두었거나, 시크릿 모드를 사용 중이라면 저장이 유지되지 않을 수 있습니다.4

셋째, 저장 공간은 무한하지 않습니다. localStorage는 간단한 설정, 이름, 작은 목록 정도를 저장하는 용도에 어울립니다. 사진, 큰 파일, 많은 데이터를 넣는 공간이 아닙니다.

넷째, 일부 기능은 권한이 필요합니다. 예를 들어 위치 정보, 카메라, 마이크 같은 기능은 브라우저가 사용자에게 허락을 요청합니다. 사용자가 거절하면 사용할 수 없습니다. 이것은 불편함이 아니라 사용자를 보호하기 위한 장치입니다.

작은 실습: 오늘의 응원 문구 저장하기

마지막으로 랜덤과 저장 기능을 함께 써 보겠습니다. 버튼을 누르면 응원 문구를 하나 고르고, 새로고침 후에도 마지막 문구가 남게 만듭니다.

<button id="pickButton">응원 문구 뽑기</button>
<p id="message">버튼을 눌러 보세요.</p>

<script>
  const pickButton = document.querySelector("#pickButton");
  const message = document.querySelector("#message");

  const messages = [
    "오늘은 한 줄만 이해해도 충분합니다.",
    "오류는 실패가 아니라 힌트입니다.",
    "천천히 반복하면 코드가 익숙해집니다."
  ];

  const savedMessage = localStorage.getItem("lastMessage");

  if (savedMessage !== null) {
    message.textContent = savedMessage;
  }

  pickButton.addEventListener("click", function () {
    const index = Math.floor(Math.random() * messages.length);
    const pickedMessage = messages[index];

    message.textContent = pickedMessage;
    localStorage.setItem("lastMessage", pickedMessage);
  });
</script>

이 실습에는 지금까지 배운 내용이 여러 개 들어 있습니다.

  • 버튼을 찾기 위해 querySelector()를 사용했습니다.

  • 클릭에 반응하기 위해 addEventListener()를 사용했습니다.

  • 배열에서 문구를 고르기 위해 Math.random()과 Math.floor()를 사용했습니다.

  • 새로고침 후에도 남기기 위해 localStorage를 사용했습니다.

자바스크립트 실력은 문법을 많이 외울 때보다, 이런 작은 기능들을 연결해 볼 때 더 빠르게 자랍니다.

이번 장에서 기억할 것

Date는 현재 시간, 요일, 마감일 계산에 사용합니다. Math.random()은 무작위 선택에 사용하고, 배열 인덱스로 쓰려면 Math.floor()와 함께 사용합니다. setTimeout()은 나중에 한 번 실행할 때, setInterval()은 일정 시간마다 반복 실행할 때 사용합니다. localStorage는 새로고침 후에도 간단한 값을 남겨 둘 때 유용합니다.

브라우저는 자바스크립트에게 많은 도구를 빌려줍니다. 하지만 저장 공간, 개인정보, 권한 같은 한계도 함께 생각해야 합니다. 좋은 웹 기능은 작동만 하는 기능이 아니라, 사용자의 정보를 조심스럽게 다루는 기능입니다.

다음 장에서는 브라우저 안에 머무르지 않고, 인터넷에서 데이터를 가져오는 방법을 배웁니다. 실제 서비스의 상품 목록, 날씨 정보, 게시글처럼 바깥의 데이터를 자바스크립트로 받아 오는 첫걸음입니다.

참고

1Date - JavaScript | MDN

2Math.random() - JavaScript | MDN

3Window: setTimeout() method - Web APIs | MDN

4Window: localStorage property - Web APIs | MDN

책 목록

비개발자를 위한 JavaScript: 설치 없이 시작해 작은 프로젝트까지

전체 목차 보기

이 노트는 보도·비평·교육·연구 목적으로 작성되었습니다. 저작권 문의가 있으시면 에서 알려주세요.

틸노트는 사용자가 AI를 활용해 노트를 쉽게 작성하거나 편집할 수 있는 서비스입니다.

AI 스퀘어 단톡방에 함께해요

AI 활용과 틸노트 사용 팁을 나누는 오픈채팅방입니다. 입장 비밀번호는 tilnote입니다.

참여하기