0 quality - utility
source: categories/study/youtube-developers_quality/quality0.md
1. array filter
1.1 filter 메소드 - 실무에서 어떤 경우에 사용할까?
const userList = [
{userId: "1", userName: "James", phone: "010-1111-1111", address: "Seoul"},
{userId: "2", userName: "Jeremy", phone: "010-1111-1112", address: "Jeju"},
{userId: "3", userName: "Justin", phone: "010-1111-1113", address: "Seoul"},
]
let selectedUserInfo = {};
for (let i = 0; i < userList.length; i++) {
if (userList[i].userId === "2") {
selectedUserInfo = userList[i]
}
}
console.log(selectedUserInfo); // {userId: '2', userName: 'Jeremy', phone: '010-1111-1112', address: 'Jeju'}
let selectedUserInfo2 = userList.filter(u => u.userId === "2")[0]
console.log(selectedUserInfo2); // {userId: '2', userName: 'Jeremy', phone: '010-1111-1112', address: 'Jeju'}
2. array map
const userList = [
{userId: "1", firstName: "Seungwon", lastName: "Go", yyyymmdd: "19770513", phone: "010-1111-1111", address: "Jeju"},
{userId: "2", firstName: "Jeremy", lastName: "Go", yyyymmdd: "19800103", phone: "010-1111-1112", address: "Seoul"},
{userId: "3", firstName: "James", lastName: "Go", yyyymmdd: "19821113", phone: "010-1111-1113", address: "Seoul"},
]
const mon = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
const newUserList = userList.map(u => (
{
userId: u.userId,
firstName: u.firstName,
lastName: u.lastName,
fullName: u.firstName + ' ' + u.lastName,
yyyymmdd: u.yyyymmdd,
year: u.yyyymmdd.substring(0, 4),
month: u.yyyymmdd.substring(4, 6),
day: u.yyyymmdd.substring(6, 8),
usDateFormat: mon[parseInt(u.yyyymmdd.substring(4, 6)) - 1] + ' ' + parseInt(u.yyyymmdd.substring(6, 8)) + ', ' + u.yyyymmdd.substring(0, 4), // 미국식 날짜 타입
phone: u.phone,
address: u.address
}
))
console.log(newUserList);
// [
// {
// address: "Jeju"
// day: "13"
// firstName: "Seungwon"
// fullName: "Seungwon Go"
// lastName: "Go"
// month: "05"
// phone: "010-1111-1111"
// usDateFormat: "May 13, 1977"
// userId: "1"
// year: "1977"
// yyyymmdd: "19770513"
// },
// {
// address: "Seoul"
// day: "03"
// firstName: "Jeremy"
// fullName: "Jeremy Go"
// lastName: "Go"
// month: "01"
// phone: "010-1111-1112"
// usDateFormat: "Jan 3, 1980"
// userId: "2"
// year: "1980"
// yyyymmdd: "19800103"
// },
// {
// address: "Seoul"
// day: "13"
// firstName: "James"
// fullName: "James Go"
// lastName: "Go"
// month: "11"
// phone: "010-1111-1113"
// usDateFormat: "Nov 13, 1982"
// userId: "3"
// year: "1982"
// yyyymmdd: "19821113"
// }
// ]
3. moment.js
npm i moment
# OR
yarn add moment
const moment = require('moment');
const today = moment().format('YYYY-MM-DD');
const usFormatToday = moment().format('MMM D, YYYY');
console.log('오늘 ', today); // 오늘 2021-11-01
console.log('오늘날짜 미국형식 ', usFormatToday); // 오늘날짜 미국형식 Nov 1, 2021
const tomorrow = moment().add(1, 'day').format('YYYY-MM-DD');
console.log('내일 ', tomorrow); // 내일 2021-11-02
const yesterday = moment().subtract(1, 'day').format('YYYY-MM-DD');
const yesterday2 = moment().add(-1, 'day').format('YYYY-MM-DD');
const before3 = moment().subtract(3, 'day').format('YYYY-MM-DD');
console.log('어제 ', yesterday); // 어제 2021-10-31
console.log('어제2 ', yesterday2); // 어제2 2021-10-31
console.log('3일전 ', before3); // 3일전 2021-10-29
const week = moment().add(1, 'week').format('YYYY-MM-DD');
const week2 = moment().subtract(1, 'week').format('YYYY-MM-DD');
console.log('1주일후 ', week); // 1주일후 2021-11-08
console.log('1주일전 ', week2); // 1주일전 2021-10-25
const month = moment().add(1, 'month').format('YYYY-MM-DD');
const month2 = moment().subtract(1, 'month').format('YYYY-MM-DD');
console.log('1달후 ', month); // 1달후 2021-12-01
console.log('1달전 ', month2); // 1달전 2021-10-01
const year = moment().add(1, 'year').format('YYYY-MM-DD');
console.log('1년후 ', year); // 1년후 2022-11-01
// 사용자 로그인 후 해당 사용자의 타임존을 설정하는 경우가 있음 - 시차
// 데이터베이스는 한군데 있고 사용자는 각 나라 여러곳에 있는 경우
// 데이터베이스는 각 나라별 날짜 포멧을 저장하지 않는다. 당연히 하나의 시간만 저장이 된다. 글로벌 서비스 같은 경우 UTC +0 기준으로 저장이 될 것이다.
// 대한민국은 타임존이 UTC +9 <- 이거 많이 봤지?
// 실제 데이터베이스에 저장된 시간을 그대로 우리나라 사람들에게 보여줬을 때, 우리나라 시간과 9시간의 gap이 생긴다.
// 우리나라 사람에게 보여줄 땐 +9 아홉시간을 더한 후 보여줘야지만 동일한 시간을 받을 수 있다.
// 아래 create_date를 현재 사용자의 타임존에 맞는 시간으로 보여줘야한다.
// 현재 사용자가 UTC +9라면 그 기준에 맞춰줘야한다.
const create_date = new Date(); // UTC +0 기준
const user_timezone = 9;
const system = moment(create_date).format('YYYY-MM-DD HH:mm:ss');
const timezone = moment(create_date).add(user_timezone, 'hour').format('YYYY-MM-DD HH:mm:ss');
console.log('타임존 적용 전 시스템시간 ', system); // 타임존 적용 전 시스템시간 2021-11-01 21:20:24
console.log('해당유저의 타임존에 맞게 변화 ', timezone); // 해당유저의 타임존에 맞게 변화 2021-11-02 06:20:24
Note
날짜말고 또 중요한거. 금액.
우리나라는 3자리마다 콤마, 소수점 이하는 없음
유럽이나 미국은 소수점에도 있음, 그리고 3자리마다 점이고 소수점에 콤마를 씀. 우리나라랑 반대
이런 부분들을 고려를해서 개발해야됨
4. 데이터그리드 구현 (테이블 정렬)
const array1 = [1, 30, 4, 21, 100000];
const res = array1.sort(function (a,b) {
if (a < b) return -1;
else if (a > b) return 1;
return 0;
})
console.log(res);
const res2 = array1.sort((a, b) => a - b);
console.log(res2);
// return하는 -1, 1, 0은 사실 중요하지않고 0보타 큰지 0보다 작은지가 중요한 것이다.
// a가 b보다 크면 a - b 에서 +가 나올 것이고
// a가 b보다 작으면 -
// a랑 b가 같으면 0
// 아래 화살표함수식이 결국 그 위 식이랑 똑같은 것이다.
const numbers = [4, 2, 5, 1, 3];
numbers.sort(function(a, b) {
console.log(a, b, a - b);
return a - b;
});
console.log(numbers);
// 2 4 -2
// 5 2 3
// 5 4 1
// 1 4 -3
// 1 2 -1
// 3 4 -1
// 3 2 1
// [1, 2, 3, 4, 5]
Note
안에서 인자 a, b에 넘길 때 따로 내부로직이 있는 듯하다.
우리가 신경쓸 것은 배열 요소 하나하나를 서로 어떻게 비교할지만 신경쓰면된다.
const userList = [
{userId: "1", firstName: "Seungwon", lastName: "Go", yyyymmdd: "19770513", phone: "010-1111-1111", address: "Jeju"},
{userId: "2", firstName: "Jeremy", lastName: "Go", yyyymmdd: "19800103", phone: "010-1111-1112", address: "Seoul"},
{userId: "3", firstName: "James", lastName: "Go", yyyymmdd: "19821113", phone: "010-1111-1113", address: "Seoul"},
]
// firstName순으로 정렬해보자.
const sortUserList = userList.sort((a, b) => a.firstName < b.firstName ? -1 : a.firstName > b.firstName ? 1 : 0);
console.log(sortUserList);
// [
// {userId: '3', firstName: 'James', lastName: 'Go', yyyymmdd: '19821113', phone: '010-1111-1113', …}
// {userId: '2', firstName: 'Jeremy', lastName: 'Go', yyyymmdd: '19800103', phone: '010-1111-1112', …}
// {userId: '1', firstName: 'Seungwon', lastName: 'Go', yyyymmdd: '19770513', phone: '010-1111-1111', …}
// ]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>table sort</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
</head>
<body>
<div class="container">
<div class="mb-2">
<input type="search" class="form-control" onkeydown="doSearch(event, this.value)">
</div>
<table class="table table-bordered table-sm">
<thead>
<tr>
<th onclick="sort('userId');">userId</th>
<th onclick="sort('firstName');">firstName</th>
<th onclick="sort('lastName');">lastName</th>
<th onclick="sort('yyyymmdd');">yyyymmdd</th>
<th onclick="sort('phone');">phone</th>
<th onclick="sort('address');">address</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
<script>
let userList = [
{userId: "1", firstName: "Seungwon", lastName: "Go", yyyymmdd: "19770513", phone: "010-1111-1111", address: "Jeju"},
{userId: "2", firstName: "Jeremy", lastName: "Go", yyyymmdd: "19800103", phone: "010-1111-1112", address: "Seoul"},
{userId: "3", firstName: "James", lastName: "Go", yyyymmdd: "19821113", phone: "010-1111-1113", address: "Seoul"},
]
let sortOption = {
userId: true,
firstName: true,
lastName: true,
yyyymmdd: true,
phone: true,
address: true,
}
function sort(sortField) {
if (sortOption[sortField]) {
userList = userList.sort((a, b) => a[sortField] < b[sortField] ? -1 : a[sortField] > b[sortField] ? 1 : 0);
} else {
userList = userList.sort((a, b) => a[sortField] < b[sortField] ? 1 : a[sortField] > b[sortField] ? -1 : 0);
}
sortOption[sortField] = !sortOption[sortField];
renderTable(userList);
}
function doSearch(e, keyword) {
if (e.keyCode === 13) { // enter 키 입력했을 때
const regexp = new RegExp(keyword, 'gi'); // g 모든걸 찾아라 i 대소문자 구분하지말고 찾아라
const data = userList.filter(item => regexp.test(item.userId) || regexp.test(item.firstName) || regexp.test(item.lastName) || regexp.test(item.yyyymmdd) || regexp.test(item.phone) || regexp.test(item.address));
renderTable(data);
}
}
function renderTable(data) {
const oTable = document.querySelector('table tbody');
const h = [];
data.forEach(item => {
h.push("<tr>")
h.push("<td>" + item.userId + "</td>")
h.push("<td>" + item.firstName + "</td>")
h.push(`<td>${item.lastName}</td>`)
h.push(`<td>${item.yyyymmdd}</td>`)
h.push(`<td>${item.phone}</td>`)
h.push(`<td>${item.address}</td>`)
h.push("</tr>")
})
oTable.innerHTML = h.join('');
}
renderTable(userList);
</script>
</body>
</html>
5. i18n (다국어 구현) - internalization
구글 검색하면 이미 만들어져있는 모듈이 굉장히 많다.
하지만 이번 시간엔 그런 모듈들을 사용하지 않고 직접 만들어보도록 하겠다.
const text = "My name is {fullName}. I am from {city}.";
const data = {
id: "1",
fullName: "HyungJu Lee",
city: "Seoul",
company: "ReturnValues",
}
const i18n = {
en: {
"My name is {fullName}. I am from {city}.": "My name is {fullName}. I am from {city}.",
},
ko: {
"My name is {fullName}. I am from {city}.": "제 이름은 {fullName} 입니다. 저는 {city} 출신입니다."
}
}
// 사용자가 로그인한 순간에 사용자가 사용하는 언어에 대한 정보를 가지고온다고 가정
const userLanguage = "ko";
function t(form, params = {}) {
// g - 모든 문자에서 검색
// { 이걸로 시작
// } 이걸로 끝
// 사이에 } <- 이거 제외한 아무 문자
return form.replace(/{[^}]*}/g, match => {
console.log(match);
console.log(match.slice(1, -1));
return params[match.slice(1, -1)];
})
}
console.log(t(text, data));
// {fullName}
// fullName
// {city}
// city
// My name is HyungJu Lee. I am from Seoul.
const translation = t(i18n[userLanguage]["My name is {fullName}. I am from {city}."], data);
console.log(translation);
// {fullName}
// fullName
// {city}
// city
// 제 이름은 HyungJu Lee 입니다. 저는 Seoul 출신입니다.
위와 같이하면 굉장히 간단한 다국어 시스템을 만들 수 있습니다.
오픈소스도 많지만 오픈소스를 보다보니까 굳이 필요없는 코드들이 들어있는 경우도 많더라구요.
오픈소스를 쓸 수도 있지만 이렇게 간단하게 다국어 시스템을 코드로 직접 만들어서 사용할 수도 있습니다.
6. 통화 포멧 구현하기 - Currency
각국마다 금액을 표기하는 방법이 다릅니다.
// 한국 - 3,000 (소수점이 없다)
// 미국, 유럽 (소수점 있다) 3,000.12
// 유럽 3.000,12 (유럽의 몇몇 국가는 이렇게 소수점과 점을 바꿔서 쓰는 경우도 있다)
// 포멧을 보통 이런식으로 많이 정의합니다. - #,###.## (세자리마다 콤마, 소수점이하는 두자리마다 점으로 표시하라 라는 뜻이다)
function currency(value, format) {
// 아래 선언한 currencyUnit의 역할
// $#,###.## <- 간혹가다가 이렇게 화폐 단위가 맨 앞에 오는 포멧이 있다.
// 어떤 심볼이던지 받기 위한 변수이다.
let currencyUnit = "";
// $#,###.## <- 맨 앞에 $처럼 #이 아닌 것이 왔다면 심볼이라고 여긴다.
if (format.substring(0, 1) !== "#") {
currencyUnit = format.substring(0, 1);
}
// 3자리마다 어떤 구분자로 나눌 것인지. default 값은 , 쉼표
let groupingSeparator = ",";
// 소수점 이하 몇자리까지 보여줄 것인지.
let maxFractionDigits = 0;
// 소수점 이하 표기는 .으로할건지 ,로 할건지. default는 .
let decimalSeperator = ".";
// #,###.## <- 포멧이 이렇다면 ,의 index는 1이 리턴
// .의 index는 5가 리턴
// ,의 index가 작으므로 groupingSeparator는 그대로 ,
// maxFractionDigits은 . 뒤에 #이 몇개가 있는지를 보면된다.
if (format.indexOf(",") < format.indexOf(".")) {
maxFractionDigits = format.length - format.indexOf(".") - 1;
} else {
// #.###,##
groupingSeparator = ".";
decimalSeperator = ",";
maxFractionDigits = format.length - format.indexOf(",") - 1;
}
let prefix = "";
let d = "";
let dec = 1;
for (let i = 0; i < maxFractionDigits; i++) {
dec = dec * 10;
}
// maxFractionDigits이 2라면, 1324.12345 -> 1324.12로 반환되게끔
let v = String(Math.round(parseFloat(value) * dec) / dec);
// if (v.startsWith("-"))
if (v.indexOf("-") > -1) {
prefix = "-";
v = v.substring(1); // 앞에 -가 붙어있다면 - 잘라내버리고 숫자만 v에 저장
}
// #,###.#0 <- format이 이렇게 들어왔다면. 끝에 0이 붙어있다면. <- 이거는 소수점 2자리까진 무조건 표시해라 라는뜻. 표시할 소수점이없어도.
// 소수점 이하 몇자리까지 표시하는게 있고 마지막이 0이라면
if (maxFractionDigits > 0 && format.substring(format.length - 1) === "0") {
// 소수점 maxFractionDigits자리까지 무조건 만드는 함수.. 소수점이 없다면 0을 붙여서 만들어주는 함수다.
v = String(parseFloat(v).toFixed(maxFractionDigits)); // 12.333.toFixed(4) -> 12.3330
}
// 소수점 이하까지 표현하겠다면,
if (maxFractionDigits > 0 && v.indexOf(".") > -1) {
d = v.substring(v.indexOf(".")); // v가 1324.12라면 d에 .12가 들어옴
d = d.replace(".", decimalSeperator); // decimalSeperator가 ,라면 ,12로 바뀐다
v = v.substring(0, v.indexOf(".")); // 1324
}
// \d는 숫자를 의미
// 하나 이상의 숫자가있고 연속된 숫자가 3개
// v에 1324가 담겨있다면
const r = /(\d+)(\d{3})/; // 앞괄호 $1, 뒷괄호 $2 <- 이렇게 자동으로 매핑
while (r.test(v)) {
v = v.replace(r, "$1" + groupingSeparator + "$2"); // 1 + "," + 324 -> 1,324
// 만약 v가 4234523라면
// 처음엔 4234 + "," + 523 -> 4234,523
// 그 다음엔 4 + "," + 234 -> 4,234
}
return prefix + currencyUnit + String(v) + String(d);
}
console.log(currency(4234523.12, "#,###.##"));
// 4,234,523.12
console.log(currency(4234523.12, "#.###,##"));
// 4.234.523,12
console.log(currency(4234523.12, "$#.###,##"));
// $4.234.523,12
console.log(currency(-4234523.12, "$#.###,##"));
// -$4.234.523,12
console.log(currency(-4234523.1, "$#.###,##"));
// -$4.234.523,1
console.log(currency(-4234523.1, "$#.###,#0"));
// -$4.234.523,10