JavaScript의 Date.getMonth()는 왜 0부터 시작하는가

date
Nov 23, 2024
slug
why-javascript-date-getmonth-starts-from-zero
author
status
Public
tags
Javascript
summary
type
Post
thumbnail
3D Renders (3).jpg
category
updatedAt
Nov 24, 2024 01:26 PM
 

JavaScript로 Date객체 만지다 한 번쯤은 겪는 상황


 
notion image
> "아니, 12월인데 왜 11이 나오는 거죠? 🤔" > "앗! 1월인데 왜 0이... 😱"
const date = new Date(); console.log(date.getMonth()); // 12월인데 11이 출력됩니다 // 흔히 저지르는 실수 const christmas = new Date(2024, 12, 25); // 의도: 2024년 12월 25일 console.log(christmas); // 실제: 2025년 1월 25일 😅
JavaScript의 Date객체는 우리가 알던 달력과는 조금 다른 방식을 보여줍니다.
1월은 0이 되고, 12월은 11이 되는 이 독특한 방식의 비밀은 무엇일까요?
 

시간을 거슬러 올라가는 여정 🕰️


1. C언어의 time 구조체 (1970년대)

// tm 구조체 구현 struct tm { int tm_mon; // 월 (0-11) }; // 1월은 0, 12월은 11 if (time_info->tm_mon == 0) { printf("1월입니다\n"); }
 
tm구조체는 왜 zero-based(0-based) 방식을 사용했을까요? 무슨 장단점이 있었을까요?
 
장점
  1. 메모리 효율성
    1. 1970년대 초기 컴퓨터의 제한된 메모리 환경
    2. 0부터 시작하는 인덱싱으로 메모리 주소 계산이 더 효율적
    3. 바이너리 연산에서의 이점
  1. 배열 처리의 일관성
// C언어에서의 월 이름 배열 처리 char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; printf("%s", months[time_info->tm_mon]); // 직접 인덱싱 가능
단점
  1. 인간의 직관적인 달력 개념과 불일치
  1. 데이터 표현 시 항상 변환 작업 필요
  1. 개발자의 실수 가능성 증가

2. Java의 Date 클래스 (1995년)

// 혼란스러운 월 표현 Date date = new Date(); int month = date.getMonth(); // 12월이면 11이 반환됨 // 실제 사용시 항상 +1을 해야 함 System.out.println("현재 월: " + (month + 1));
Java는 C언어의 time 구조체의 0-based month표현을 가져와 Date 클래스를 설계했습니다.
이 직관적이지 않은 방식은 많은 개발자들을 혼란스럽게 만들었습니다.
 
Java의 개선 노력
Java 진영에서는 이 한계를 인식하고 개선하기위한 시도를 합니다. 2년 뒤인 1997년 JDK 1.1에서 Calendar 클래스를 도입하게되죠.
1. Calendar 클래스 도입 (1997년)
Calendar calendar = Calendar.getInstance(); int month = calendar.get(Calendar.MONTH); // 여전히 0-11 사용 -> 한계점
2. Joda-Time 라이브러리로 대안 제시 3. java.time 패키지로 최종 해결 (2014년)
// Java 8 LocalDate today = LocalDate.now(); int month = today.getMonthValue(); // 1-12 사용
 

3. JavaScript의 탄생 (1995년)

*Java와 JavaScript는 둘 다 1995년에 출시되었습니다.
  • Java: 1995년 5월 23일 (Sun Microsystems)
  • JavaScript: 1995년 12월 4일 (Netscape)
 

웹 브라우저를 위한 새로운 언어

1995년, 넷스케이프는 웹 브라우저에서 동작하는 가벼운 프로그래밍 언어가 필요했습니다. 당시 썬 마이크로시스템즈에서 개발한 Java가 큰 인기를 얻고 있었고, 넷스케이프는 이에 대응할 새로운 언어를 원했죠.
 

10일 만에 탄생한 JavaScript

- Brendan Eich가 단 10일 만에 첫 버전 개발 - Mocha(코드명) → LiveScript(베타) → JavaScript(정식)로 이름 변경 - 빠른 개발을 위해 Java의 많은 API를 그대로 차용
 

Date객체의 운명적인 선택

2014년, JavaScript의 Date 객체 설계에 대한 한 개발자의 문제 제기에 Brendan Eich는 이렇게 답했습니다.
"Java 1.0 beta에서 가져온 것입니다. 시간이 없어서 그대로 사용했죠."
https://x.com/BrendanEich/status/481939099138654209
 
JavaScript의 Date.getMonth()가 0부터 시작하는 것은 C언어에서 시작된 역사적인 결정이 Java를 거쳐 JavaScript까지 이어진 결과입니다. 비록 직관적이지 않지만, 이 방식은 당시의 기술적 제약과 개발 일정 속에서 내려진 선택이었습니다.
*C언어의 time 구조체 → Java의 Date 클래스 → JavaScript의 Date 객체로 이어지는 영향
notion image
 
 

현재와 미래: 각자의 해결책


Java와 JavaScript의 다른 길

Java가 18년에 걸쳐 날짜/시간 API를 개선해온 것과 달리, JavaScript의 Date 객체는 거의 변화가 없었습니다. 다만 JavaScript 생태계는 다른 방식으로 이 문제를 해결해왔습니다.
 
Java: 점진적 개선의 길
  1. 1995년: Date 클래스 (0-based month)
  1. 1997년: Calendar 클래스 (여전히 0-based)
  1. 2014년: java.time 패키지 (드디어 1-based month)
 
JavaScript: 커뮤니티 중심의 해결의 길
  1. 커뮤니티 중심의 해결책 - moment.js (레거시지만 안정적) - day.js (가볍고 사용하기 쉬움) - date-fns (현대적이고 함수형)
  1. 표준화를 향한 움직임 - TC39의 Temporal API 제안 - 1-based month 등 직관적인 날짜 처리 방식 도입 예정
 
JavaScript 개발자를 위한 현재의 선택지
  1. 내장 Date 객체 사용 시 - 항상 0-based month 주의 - 유틸리티 함수로 감싸서 사용
  1. 대안 라이브러리 활용 (day.js, date-fns 등) - 프로젝트 상황에 맞는 라이브러리 선택 - 일관된 날짜 처리 방식 유지
 

맺음말


JavaScript의 Date 객체가 0부터 시작하는 월 표현을 사용하게 된 것은 단순한 우연이 아닙니다. C언어의 메모리 효율성을 위한 선택이 Java를 거쳐, 급박했던 JavaScript 개발 일정 속에서 그대로 이어진 결과였죠. Java가 18년에 걸쳐 점진적으로 개선해 온 것과 달리, JavaScript는 커뮤니티 중심의 다양한 해결책을 제시해왔습니다. moment.js, day.js, date-fns와 같은 라이브러리들이 그 증거이죠. 이제 JavaScript도 TC39의 Temporal API를 통해 새로운 변화를 준비하고 있습니다. 과거의 제약에서 벗어나 더 직관적인 날짜 처리를 향해 나아가고 있는 것이죠. 그때까지는 우리가 선택할 수 있는 다양한 대안들을 활용하면서, JavaScript의 발전을 함께 지켜보면 좋겠습니다.