반응형
Api를 통해서 받아온 사용자의 데이터를 노출할 때 정보보호를 위해 특정 데이터는 전체를 보여주지 않고 일부를 가려서(Masking) 보여줘야 하는 경우가 발생합니다.
가장 좋은 방법은 Back-End서버에서 데이터가 가공처리되어 전달하고 Front에서는 전달받은 데이터를 화면에 그대로 노출시켜 주는 게 가장 좋은 방법이지만 상황에 따라서 Front에서 데이터를 가공해야 할 경우도 발생합니다. 이럴 때 공통 마스킹 Function을 만들어서 사용하면 굉장히 유용하게 사용할 수 있습니다.
💡 마스킹 처리 함수
/********************************************
* 공통 마스킹
* checkNull : 데이터 Check => 공백 | undefined | null
*
* ※) 이메일 마스킹
* ex 1) emailEndHide
* 원본 데이터 : abcdefg12345@naver.com, 변경 데이터 : ab**********@naver.com
* ex 2) emailEndShow
* 원본 데이터 : abcdefg12345@naver.com, 변경 데이터 : ab**********@naver.com
*
* ※) 휴대폰 번호 마스킹
* ex1) 원본 데이터 : 01012345678, 변경 데이터 : 010****5678
* ex2) 원본 데이터 : 010-1234-5678, 변경 데이터 : 010-****-5678
* ex3) 원본 데이터 : 0111234567, 변경 데이터 : 011***4567
* ex4) 원본 데이터 : 011-123-4567, 변경 데이터 : 011-***-4567
*
* ※) 주민번호 resident
* ex1) 원본 데이터 : 990101-1234567, 변경 데이터 : 990101-1******
* ex2) 원본 데이터 : 9901011234567, 변경 데이터 : 9901011******
*
* ※) 이름 마스킹
* ex1) 원본 데이터 : 김철수, 변경 데이터 : 김철*
* ex2) 원본 데이터 : 대한민국, 변경 데이터 : 대한**
* ex3) 원본 데이터 : 한국, 변경 데이터 : 한*
*
* * ※) 계좌번호 마스킹
* 자리수에 따라서 마스킹 노출 다름 : substring 변경
*********************************************/
let maskingFunc = {
checkNull: function (str) {
if (typeof str === "undefined" || str === null || str === "") {
return true;
}
else {
return false;
}
},
emailEndHide: function (str) {
let emailStr = str.match(/([a-zA-Z0-9._-]+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9._-]+)/gi);
if (this.checkNull(str)) {
return str;
}
let strLength = emailStr.toString().split('@')[0].length - 4;
return str.toString().replace(new RegExp('.(?=.{0,' + strLength + '}@)', 'g'), '*').replace(/.{6}$/, "******");
},
emailEndShow: function (str) {
let emailStr = str.match(/([a-zA-Z0-9._-]+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9._-]+)/gi);
if (this.checkNull(str) == true || this.checkNull(emailStr) == true) {
return str;
}
let strLength = emailStr.toString().split('@')[0].length - 4;
return str.toString().replace(new RegExp('.(?=.{0,' + strLength + '}@)', 'g'), '*');
},
phone: function (str) {
let phoneStr;
let maskingStr;
if (this.checkNull(str)) {
return str;
}
// 1) -가 없는 경우
if (str.toString().split('-').length != 3) {
phoneStr = str.length < 11 ? str.match(/\d{10}/gi) : str.match(/\d{11}/gi);
if (str.length < 11) {
maskingStr = str.toString().replace(phoneStr, phoneStr.toString().replace(/(\d{3})(\d{3})(\d{4})/gi, '$1***$3'));
}
else {
maskingStr = str.toString().replace(phoneStr, phoneStr.toString().replace(/(\d{3})(\d{4})(\d{4})/gi, '$1****$3'));
}
}
// 2) -가 있는 경우
else {
phoneStr = str.match(/\d{2,3}-\d{3,4}-\d{4}/gi);
if (/-[0-9]{3}-/.test(phoneStr)) {
maskingStr = str.toString().replace(phoneStr, phoneStr.toString().replace(/-[0-9]{3}-/g, "-***-"));
} else if (/-[0-9]{4}-/.test(phoneStr)) { // 2.2) 00-0000-0000
maskingStr = str.toString().replace(phoneStr, phoneStr.toString().replace(/-[0-9]{4}-/g, "-****-"));
}
}
return maskingStr;
},
resident: function (str) {
let residentStr;
let maskingStr;
if (this.checkNull(str)) {
return str;
}
// - 이 있는 경우
if (str.length === 14) {
residentStr = str.match(/(?:[0-9]{2}(?:0[1-9]|1[0-2])(?:0[1-9]|[1,2][0-9]|3[0,1]))-[1-4]{1}[0-9]{6}\b/gi);
maskingStr = str.toString().replace(residentStr, residentStr.toString().replace(/(-?)([1-4]{1})([0-9]{6})\b/gi, "$1$2******"));
}
// - 이 없는 경우
if (str.length === 13) {
residentStr = str.match(/\d{13}/gi);
maskingStr = str.toString().replace(residentStr, residentStr.toString().replace(/([0-9]{6})$/gi, "******"));
}
return maskingStr;
},
name: function (str) {
let maskingStr;
if (this.checkNull(str)) {
return str;
}
if (str.length < 3) {
maskingStr = str.replace(/(?<=.{1})./gi, "*");
}
if (str.length === 3) {
maskingStr = str.replace(/(?<=.{2})./gi, "*");
}
if (str.length > 3) {
maskingStr = str.replace(/(?<=.{2})./gi, "*");
}
return maskingStr;
},
account: function (str) {
let maskingStr;
if (this.checkNull(str) == true) {
return str;
}
if (str.length <= 8) {
maskingStr =
str.substring(0, 2) +
str.substring(3, 7).replace(/[0-9a-zA-Z]/g, '*') +
str.substring(6, str.length);
} else if (str.length >= 9 && str.length <= 10) {
maskingStr =
str.substring(0, 2) +
str.substring(3, 8).replace(/[0-9a-zA-Z]/g, '*') +
str.substring(7, str.length);
} else if (str.length > 10) {
maskingStr =
str.substring(0, 3) +
str.substring(3, 8).replace(/[0-9a-zA-Z]/g, '*') +
str.substring(8, str.length);
}
return maskingStr;
},
}
✔ 사용 예시
maskingFunc.emailEndHide("abcdefg12345@naver.com"); // "abc*********@nav******"
maskingFunc.emailEndShow("abcdefg12345@naver.com"); // "abc*********@naver.com"
maskingFunc.phone("0111234567"); // "011***4567"
maskingFunc.phone("011-123-4567"); // "011-***-4567"
maskingFunc.phone("01012345678"); // "010****5678"
maskingFunc.phone("010-1234-5678"); // "010-****-5678"
maskingFunc.resident("9901011234567"); // "9901011******"
maskingFunc.resident("990101-1234567"); // "990101-1******"
maskingFunc.name("한국"); // "한*"
maskingFunc.name("김철수"); // "김철*"
maskingFunc.name("대한민국"); // "대한**"
maskingFunc.account("1233333333333"); // "123*****33333"
✔ 반복문에서 사용 예시
반복문에서도 사용가능하고 React처럼 Render가 이루어지고 화면이 그려지는 경우에도 마스킹 함수를 만들어놓고 아래 예시처럼 사용하면 정상적으로 데이터가 마스킹 처리되어 화면에 보여집니다.
{userData.map((item, idx) => (
<tr>
<td>{item.name}</td>
<td>{maskingFunc.account(item.account)}</td>
</tr>
))}
반응형
'IT > Front-End' 카테고리의 다른 글
Clean Code: 좋은 코드 구현하기(feat. 협업) (0) | 2022.09.02 |
---|---|
웹팩(Webpack), 바벨(Babel), 폴리필(Polyfill) 알아보기 (0) | 2022.08.24 |
CORS는 왜 이렇게 우리를 힘들게 하는걸까? (1) | 2022.07.22 |
디자인패턴 (mvc, mvp, mvvm 그리고 flux) (0) | 2022.07.14 |
CSS 애니메이션 JS 애니메이션 차이 (0) | 2022.07.14 |
광고차단(애드블록)프로그램이나 브라우저를 사용중이시면 프로그램을 비활성화이나 블로그 주소를 예외 처리 해주시면 광고가 노출됩니다. 귀찮고 번거롭겠지만 광고 클릭은 저에게는 큰 힘이 됩니다. 🙇🏻♂️🙇🏻♀️
제 블로그의 모든 글은 제가 직접 작성 하고 다른 글을 참고할 때는 이전 글보다 읽기 편하게 수정해서 작성하고 있습니다. 커피 한잔 사먹고 더 열심히 좋은글로 보답하겠습니다.
오늘도 제 블로그에 와 주셔서 감사합니다. :)
제 블로그의 모든 글은 제가 직접 작성 하고 다른 글을 참고할 때는 이전 글보다 읽기 편하게 수정해서 작성하고 있습니다. 커피 한잔 사먹고 더 열심히 좋은글로 보답하겠습니다.
오늘도 제 블로그에 와 주셔서 감사합니다. :)