년월일의 날짜정보를 저장할 때 varchar(8)을 이용하여 표현하는 것을 종종 볼 수 있는데요. MySQL의 date 타입을 이용하면 더욱 효율적으로 정보를 저장하고 조회할 수 있어 이에 대해 공유 드리고자 합니다.

date타입은 'YYYY-MM-DD' 형식의 날짜 타입입니다. 시간을 저장하지 않습니다.

테이블에 저장된 date 타입

먼저 표를 통해 간략한 차이점을 알아보겠습니다.

varchar(8)date
size9byte3byte
validationX
타 언어와 호환XO
비교 및 연산O
가독성낮음높음

아래에서 하나씩 살펴보겠습니다.

1. size

varchar(8) 사용 시 언뜻 하이픈(-) 없이 데이터를 압축, 저장할 수 있을 것만 같지만 실제로는 date 타입에 비해 3배 큰 용량을 차지하게 됩니다.

MySQL에서 varchar는 String 데이타 타입 중 하나로 가변(variable) 문자(character) 타입을 의미합니다. 고정된 용량을 사용하는 char와 달리 varchar는 실제 용량을 표현하기 위한 prefix를 필요로 합니다. 따라서 varchar(255) 이하에서는 1 byte, 이상에서는 2 byte의 용량이 필요합니다. (1 byte = 8 bit, 즉 2^8=256, 0부터 255까지) UTF-8 인코딩방식에서는 하나의 문자 당 1바이트에서 최대 4바이트를 지원하지만 우리가 사용할 숫자로만 구성된 년월일의 경우 각 1바이트 * 8에 prefix인 1byte까지 총 9 byte를 필요로 합니다.

반면 date 타입은 '1000-01-01' 부터 '9999-12-31' 까지의 값을 지원하며 3 byte의 용량을 필요로 합니다. 년, 월, 일을 나누어 인식하므로 최대 값('9999-12-31')도 3 byte로 충분히 표현할 수 있습니다.

2. validation

값 입력 시 varchar(8) 문자열은 각 문자열을 년, 월, 일로 잘라 각각이 유효한 값인지 검사하여야 하지만 실제 저희 프로그램에서는 자리 수 체크 정도만 진행되고 있습니다. '88888888'도 유효한 날짜로 인식됩니다. date 타입은 날짜 타입인 만큼 월과 년,월에 따른 일에 대해 유효하지 않은 경우 예외가 발생합니다. 예를 들어 '1990-02-29' 또는 '2000-11-31' 같은 값은 입력할 수 없습니다. 그러나 모든 유효하지 않은 날짜를 막는 것은 아닙니다(00월이나 00일은 허용). 또 비즈니스마다 유효한 연도의 범위도 필요하므로 이 이상의 validation은 어플리케이션 단에서 로직을 통해 통제하는 것이 합리적으로 보입니다.

3. 타 언어와 호환

MySQL date 타입은 java.sql.Date로 리턴됩니다. 또 java.lang.String, java.sql.Date, java.sql.Timestamp와 같은 객체로 변환이 가능합니다.

Java, JDBC, and MySQL Types

즉 라이브러리에서 지원되는 연산이나 비교 등의 작업이 가능하다는 얘기입니다.

String 타입으로 받더라도 저희 프로그램에서 사용하는 java와 javascript에서 날짜를 표현하는 객체는 'YYYY-MM-DD' 포맷의 문자열로 객체 생성 및 초기화가 가능합니다.

java 예시

    LocalDate date = LocalDate.parse("2022-01-13");

javascript 예시

    Date = new Date("2022-01-13");

비즈니스 로직에서 validation, 날짜 연산 등을 위해 객체를 이용해야 할 경우가 많습니다. date 타입의 경우 DB에서 조회한 문자열 그대로 별도의 가공 없이 사용할 수 있습니다. 생산성과 코드 가독성이 향상됩니다.

java 로직 예시

    try{
        LocalDate date = LocalDate.parse("2022-00-00"); //DateTimeParseException 발생
    }catch(DateTimeParseException e){
        //...예외 처리 내용
    }

반면 varchar를 이용한다면 문자열을 자른 후 각각 별도의 로직 구현을 통해 연산 및 계산하거나, 문자열을 다시 객체로 만들 수 있도록 별도의 가공을 해야합니다.

4. 비교 및 연산

MySQL에서는 날짜 연산을 위해 자체적으로 다양한 함수들을 제공합니다 MYSQL 날짜 및 시간 함수. date타입은 datetime, timestamp 등의 날짜 타입과 호환되므로 위 링크의 모든 함수 사용이 가능합니다. varchar(8)의 경우 String 타입이므로 바로 함수를 사용할 수 없습니다. DATE() 함수나 STR_TO_DATE() 함수로 가공 후 사용해야 합니다. 단순 문자열 비교는 가능하지만 더 구체적인 월 비교, 일 비교나 더 나아가 연산은 지원되지 않습니다.

5. 가독성

YYYY-MM-DD는 일반적으로 년, 월, 일을 인식하는 포맷입니다. 현재 사용자가 보는 화면 또한 가독성을 위해 포맷팅 작업을 일일이 별도로 해주고 있는데 date를 사용하면 문자열 그대로 받아 사용하면 됩니다.

위처럼 별도의 포맷팅이 없어도 아래와 같이 표현됩니다.

사용자와 개발자 모두에게 가독성과 편의성을 향상시켜줍니다.

date 타입 칼럼에 입력 가능한 형식들

  • YYYYMMDD, YYMMDD, YYYY-MM-DD, YYYY#MM#DD 등 다양한 문자열 포맷으로 입력이 가능합니다. 사실상 년, 월, 일 사이 구분자가 어떤 것이어도 무관하며 연월일 6 자리도 인식 가능합니다.
입력값출력값
'20200101', '2020#01#01', '200101', '20200101'2020-01-01
  • 숫자, String 타입으로 입력이 가능합니다.
입력값출력값
'20200101', 20200101'2020-01-01'
  • 0도 입력 가능합니다.
입력값출력값
0'0000-00-00'
  • datetime타입도 입력할 수 있습니다.
입력값출력값
'2023-10-19 20:06:38''2023-10-19'
NOW()'2023-10-25' (오늘 날짜)

만약 드물지만 date를 'YYYYMMDD'의 plain한 문자열로 사용해야 한다면 date_format() 함수를 통해 문자열을 변환해 내려줄 수 있습니다.

select date_format('2022-11-11', '%Y%m%d'); -- 20221111 출력