인터넷 상에 누군가가 진담반 농담반으로 그랬습니다. 개발자가 가장 필요한 덕목중에 하나는 복붙, 구글링이라구요..
그러면서 위 사진을 덧붙였죠.
이번에 다룰 내용은 무지성으로 복붙, 구글링을 하다 생겨난 일이 였습니다.
개발을 하다보면 마감에 쫓기게 되는걸 여러번 느끼실 때가 있을겁니다.
저 역시 한참 압박에 시달릴 때 였습니다. 물론 회사에서 푸쉬를 하지는 않습니다만, 제가 생각한 일정에 맞는 결과가 나오지 않으면
저 혼자서 생각한 일정에 맞게 개발이 되야 한다는 엄청난 압박에 시달리더라구요..
그러다보니 당장 눈앞에 보이는 결과에만 목이 매이게 되고, 그 결과물을 만들기 위해 하게되는 구글링과 복붙이 더 좋지 않은 상황에 몰고 가게 되었습니다.
제가 요번에 이 일이 있게 된 일 중에 하나가 '시간'과 관련된 기능을 개발하는 과정에서 겪게 되었습니다.
서비스 중인 화면에서 다른 나라 시간으로 설정할 때 그 시간에 맞게 시간을 변경하여 보여주는 기능이였는데 거기에 그 포맷에 맞도록 변경도 해주어야 했었습니다.
기존에 Moment.js라는 걸 사용하여 세계 날짜들을 가져오고, 포맷도 맞추도록 하였지만 기획이 바뀌어 서버에서 세계시간 데이터가 들어있는 JSON파일로 받아와 그것으로 작업하는 것으로 바뀌었죠.
그러면서 기존에 Momnet.js로 사용중이였었던 부분들을 다 갈아 엎어야 했었고, 갈아 엎는 중에 '시간 포맷'부분을 작업하면서 발생한 일입니다.
제가 사용한 코드의 형태는 아래와 같습니다.
구글에 javascript date prototype format라고 치면 나오는 코드를 가져왔습니다.
Date.prototype.format = function(f) {
if (!this.valueOf()) return " ";
var weekName = ["일요일", "월요일", "화요일", "수요일", "목요일", "금요일", "토요일"];
var d = this;
return f.replace(/(yyyy|yy|MM|dd|E|hh|mm|ss|a\/p)/gi, function($1) {
switch ($1) {
case "yyyy": return d.getFullYear();
case "yy": return (d.getFullYear() % 1000).zf(2);
case "MM": return (d.getMonth() + 1).zf(2);
case "dd": return d.getDate().zf(2);
case "E": return weekName[d.getDay()];
case "HH": return (d.getUTCHours() + 100).toString().slice(-2);
case "hh": return ((h = d.getHours() % 12) ? h : 12).zf(2);
case "mm": return d.getMinutes().zf(2);
case "ss": return d.getSeconds().zf(2);
case "a/p": return d.getHours() < 12 ? "오전" : "오후";
default: return $1;
}
});
};
그 후 저 부분을 매핑 시켜주기 위해 맨 처음 동작하는데 딱 한 번만 동작하는 곳을 찾아 넣어 주었고, 다른 함수에서 저 포맷에 맞도록 맞추어 코드를 작성 한 후, 테스트 하는데 나라를 변경하더라도 시간이 변화가 없는거에요.
그래서 처음에는
function(타임스탬프 값) {
let date = new Date(타임스탬프 값);
return date.formatUTC("HH:mm");
}
타임스탬프 값이 현재 선택된 나라의 offset값과 UTCtimestamp값이 계산되어 받은 값이기 때문에 계산된 시간의 값을 파라미터로 받는다고 생각을 하고 있었기 때문에
case "dd": return d.getDate().zf(2);
d.getDate().zf(2)부분에서 데이터가 갈어 엎어진다는 걸로 착각을 했습니다. 그냥 저 부분은 출력해주는 곳인데 말이죠..
그래서 어떻게 했냐구요?
네 이렇게 출력식에 계산을 해버리는 만행을 저질렀습니다.
dateformat(offset) {
Date.prototype.format = function(f) {
if (!this.valueOf()) return " ";
var weekName = ["일요일", "월요일", "화요일", "수요일", "목요일", "금요일", "토요일"];
var d = this;
var calcoffset = offset / 60;
return f.replace(/(yyyy|yy|MM|dd|E|hh|mm|ss|a\/p)/gi, function($1) {
switch ($1) {
case "yyyy": return d.getFullYear();
case "yy": return (d.getFullYear() % 1000).zf(2);
case "MM": return (d.getMonth() + 1).zf(2);
case "dd": return d.getDate().zf(2);
case "E": return weekName[d.getDay()];
case "HH": return (d.getUTCHours() + 100 + calcoffset).toString().slice(-2);
case "hh": return ((h = d.getHours() % 12) ? h : 12).zf(2);
case "mm": return d.getMinutes().zf(2);
case "ss": return d.getSeconds().zf(2);
case "a/p": return d.getHours() < 12 ? "오전" : "오후";
default: return $1;
}
});
};
}
이런식으로여...
그 후 어떤 일이 벌어졌을까요?
제가 원하던 대로 선택한 나라의 offset값에 맞게 적용이 되었지만 문제는 시간이 00:00 상태에서 offset값이 현재 상태보다
-1시간 값을 가진 나라를 선택했을 때 99:00가 출력이 되었고, 100을 빼니 -1:00이 출력이 되더라구요.
(100을 넣은 이유는 0시 ~ 9시일 때 00시, 01시 등으로 표시해주기 위해 사용했습니다.)
여기서 뭔가 단단히 잘못되었다는 걸 알았습니다. 23:00이 아닌 -1:00나 99:00이 출력되었으니까요.
그러다 알게 된건 위에 말씀드렸던 단순한 출력식에 계산을 하려 했다는 실수였고,
function(타임스탬프 값) {
let date = new Date(타임스탬프 값);
return date.formatUTC("HH:mm");
}
요 값에서 타임스탬프 값을 계산하여 넣어주니 제가 원하는 대로 바뀌었더라구요.
그 전에 '타임스탬프 값이 현재 선택된 나라의 offset값과 UTCtimestamp값이 계산되어 받은 값이기 때문에 계산된 시간의 값을 파라미터로 받는다고 생각을 하고 있었다'고 했었던 이유가 이를 설명하기 위함 때문이였습니다.
다시 값을 확인해보니 계산된 값이 아닌 그냥 현재 UTC시간을 나타내는 타임스탬프 값이였죠. 그래서 제 눈에는 저 출력식으로 뒤엎어진 걸로 보였던 겁니다.
이번 이 일로 인해서 내가 사용하는 코드를 이해한 상태에서 사용함으로 무지성 코딩을 하려는 부분을 최소화 해야겠다는 것을 느꼈습니다. 이런 일이 반복된다면 저는 있는것에서 응용을 하지 못하는 사람으로 될 것 같았죠.단 적인 예로
Date.prototype.format = function(f) {
if (!this.valueOf()) return " ";
var weekName = ["일요일", "월요일", "화요일", "수요일", "목요일", "금요일", "토요일"];
var d = this;
return f.replace(/(yyyy|yy|MM|dd|E|hh|mm|ss|a\/p)/gi, function($1) {
switch ($1) {
case "yyyy": return d.getFullYear();
case "yy": return (d.getFullYear() % 1000).zf(2);
case "MM": return (d.getMonth() + 1).zf(2);
case "dd": return d.getDate().zf(2);
case "E": return weekName[d.getDay()];
case "HH": return (d.getUTCHours() + 100).toString().slice(-2);
case "hh": return ((h = d.getHours() % 12) ? h : 12).zf(2);
case "mm": return d.getMinutes().zf(2);
case "ss": return d.getSeconds().zf(2);
case "a/p": return d.getHours() < 12 ? "오전" : "오후";
default: return $1;
}
});
};
이와 같이 날짜를 포맷하는 부분을 다룬다 했을 때 제 입맛에 맞도록 바꿀려면 저 코드가 어떻게 동작하는지를 알아야 하는데
구조도 모른채 쓰게 된다면 제 입맛에 맞는 코드를 찾게 되는 어이없는 일들이 생기게 될겁니다.
기본을 알아야 응용이 가능하니까요!
시간과 관련된 부분을 많이 다뤄보질 못해서 까다롭고, 헷갈리게 느껴지지만 지속적으로 공부하면 나아지겠죠..?저 처럼 엉뚱한 곳을 삽질하는 일이 없길 바라는 마음에 웃지 못할 에피소드를 꺼내 보았습니다.긴 글 읽어주셔서 감사합니다. ^_^
'프로그래밍(Web) > 업무관련' 카테고리의 다른 글
[바미] 메모리 릭(memory leak)현상을 마주하다. (0) | 2022.03.28 |
---|---|
[바미] 백오피스를 고민하다 (0) | 2022.02.10 |
[바미] JS에서 for-in 보다 for문을 더 쓰자! (0) | 2022.01.12 |
[바미] 전문 통신과 TR 통신에 대해서. (0) | 2022.01.03 |
[바미] Javascript (!) Missing global variable name 에러 해결하기. (0) | 2021.11.01 |