Java/Short 개발
[Java/Short] 마스킹(Masking) 적용 방법 : 이름, 휴대폰 번호, 이메일, 계좌번호, 주소
adjh54
2024. 7. 26. 23:35
반응형
해당 글에서는 파라미터로 전달 받은 데이터를 마스킹 처리하여 반환하는 방법에 대해 알아봅니다.
1) 마스킹(Masking)
💡 마스킹(Masking)
- 민감한 정보를 보호하기 위해 데이터를 숨기거나 부분적으로 가리는 기술입니다. 이는 개인 식별 정보(PII)와 같은 민감한 데이터를 안전하게 유지하는 데 사용됩니다.
- 예를 들어, 클라이언트가 사용자 정보를 서버로 요청하였을때, 응답값으로 노출이 될 수 있기에 클라이언트에게 전달을 할때 서버내에서 마스킹처리를 하여서 클라이언트로 사용자 정보를 반환해줍니다.
💡 [참고] 아래의 구성사항은..
- 해당 마스킹을 적용한 경우는 클라이언트로부터 어느정도 정재된 상태에 Java 서버로 전달된다는 가정하에 구성을 해보았습니다.
- 또한 '정규식'으로 마스킹 처리가 가능하지만 실제로 로직적으로 어떻게 처리되는지에 대해 확인해보기 위해 직접 코드로 구성하였습니다.
2) 이름 마스킹
💡 이름 마스킹
- 이름의 형태가 2자리, 3자리, 4자리, 5자리 이상의 문자열 형태를 가진다는 가정하에 이에 대한 마스킹을 수행합니다.
이름 길이 | 마스킹 방법 | 예시 |
2자리 | 첫 번째 문자를 “*”로 마스킹 | 이슬 → *슬 |
3자리 | 두 번째 문자를 “*”로 마스킹 | 홍길동 → 홍*동 |
4자리 | 가운데 두 문자를 “*”로 마스킹 | 독고재형 → 독**형 |
5자리 이상 | 첫 번째, 마지막 문자를 제외하고 “*”로 마스킹 | 크리스티나 → 크***나 |
@NoArgsConstructor
public class MaskingUtil {
/**
* 이름에 대한 마스킹을 수행합니다.
*
* @param name {String} : 마스킹 이전 이름
* @return {String} 마스킹 이후 이름
*/
public static String maskName(String name) {
// 기본 형식에 맞지 않는 이름의 경우, 파라미터 값을 그대로 반환합니다.
if (name == null || name.length() < 2) {
return name;
}
int length = name.length();
StringBuilder maskedName = new StringBuilder(name);
// [CASE1] 이름이 2자리 인 경우 => 첫 번째 문자에 대해 마스킹
if (length == 2) {
maskedName.setCharAt(0, '*');
}
// [CASE2] 이름이 3자리 인 경우 => 두 번째 문자에 대해 마스킹
else if (length == 3) {
maskedName.setCharAt(1, '*');
}
// [CASE3] 이름이 4자리 인 경우 => 두 번째, 세 번째 문자에 대해 마스킹
else if (length == 4) {
maskedName.setCharAt(1, '*');
maskedName.setCharAt(2, '*');
}
// [CASE4] 이름이 5자리 이상인 경우 => 첫 번째와 마지막 문자를 제외한 모든 문자에 대해 마스킹
else if (length == 5) {
maskedName.setCharAt(1, '*');
maskedName.setCharAt(2, '*');
maskedName.setCharAt(3, '*');
}
// [CASE5] 이름이 5자리 이상인 경우 => 첫 번째와 마지막 문자를 제외한 모든 문자에 대해 마스킹
else {
for (int i = 1; i < length - 1; i++) {
maskedName.setCharAt(i, '*');
}
}
return maskedName.toString();
}
public static void main(String[] args) {
// 테스트 케이스
System.out.println(maskName("이슬")); // *슬
System.out.println(maskName("홍길동")); // 홍*동
System.out.println(maskName("독고재형")); // 독**형
System.out.println(maskName("홍길동김")); // 홍***김
System.out.println(maskName("김철수박")); // 김***박
}
}
3) 휴대폰 번호 마스킹
💡 휴대폰 번호 마스킹
- 하이픈이 포함되지 않은 휴대폰 번호의 경우 10자리 혹은 11자리를 가집니다. 이 중에서 가운데 3자리 혹은 4자리에 대해 마스킹 처리를 합니다.
- 하이픈이 포함된 경우는 휴대폰 번호의 경우에는 가운데 3자리 혹은 4자리에 대해 마스킹 처리를 합니다.
휴대번호 길이 | 마스킹 방법 | 예시 |
10자리 | 가운데 3자리를 마스킹 처리합니다 | 0101231234 → 010***1234 |
11자리 | 가운데 4자리를 마스킹 처리합니다 | 01012341234 → 010****1234 |
10자리에 하이픈 포함 | 가운데 3자리를 마스킹 처리합니다. | 010-123-5678 → 010-***-5678 |
11자리에 하이픈 포함 | 가운데 4자리를 마스킹 처리합니다. | 010-9876-5432 → 010-****-5432 |
@NoArgsConstructor
public class MaskingUtil {
/**
* 휴대폰 번호에 대한 마스킹을 수행합니다.
*
* @param phoneNumber {String} 마스킹 이전 휴대폰 번호
* @return {String} 마스킹 된 휴대폰 번호
*/
public static String maskPhoneNumber(String phoneNumber) {
// 기본 형식에 맞지 않는 핸드폰 번호의 경우, 파라미터 값을 그대로 반환합니다.
if (phoneNumber == null || phoneNumber.length() < 10) {
return phoneNumber;
}
StringBuilder maskedPhoneNumber = new StringBuilder(phoneNumber);
int length = phoneNumber.length();
// [CASE1] 핸드폰 번호의 하이픈이 포함된 경우
if (phoneNumber.contains("-")) {
String[] parts = phoneNumber.split("-");
if (parts.length == 3) {
// [CASE2-1] 가운데 번호가 3자리인 경우
if (parts[1].length() == 3) {
maskedPhoneNumber.replace(4, 7, "***"); // 가운데 3자리를 마스킹
}
// [CASE2-2] 가운데 번호가 4자리인 경우
else if (parts[1].length() == 4) {
maskedPhoneNumber.replace(4, 8, "****"); // 가운데 4자리를 마스킹
}
}
}
// [CASE2] 핸드폰 번호의 하이픈이 포함되지 않은 경우
else {
// [CASE2-1] 가운데 번호가 3자리인 경우
if (length == 10) {
maskedPhoneNumber.replace(3, 6, "***"); // 가운데 3자리를 마스킹
}
// [CASE2-2] 가운데 번호가 4자리인 경우
else if (length == 11) {
maskedPhoneNumber.replace(3, 7, "****"); // 가운데 4자리를 마스킹
}
}
return maskedPhoneNumber.toString();
}
public static void main(String[] args) {
// 테스트 케이스
System.out.println(maskPhoneNumber("0101231234")); // 010***1234
System.out.println(maskPhoneNumber("01012341234")); // 010****1234
System.out.println(maskPhoneNumber("010-123-5678")); // 010-***-5678
System.out.println(maskPhoneNumber("010-9876-5432")); // 010-****-5432
}
}
4) 이메일 마스킹
💡 이메일 마스킹
- 이메일의 아이디는 일반적으로 4자리 이상을 사용하기를 권장하기에 해당 기준에 맞추어서 마스킹을 진행합니다.
- 아이디가 3자리 이하인 경우는 그대로 반환하고, 4자리 이상인 경우는 아이디의 앞의 3자리를 제외하고 모두 마스킹 처리를 합니다.
이메일 마스킹 | 이메일 마스킹 방법 | 예시 |
3자리 이하 | 그대로 출력을 합니다 | man@naver.com → man@naver.com |
4자리 이상 | 아이디의 앞의 3자리를 제외하고 모두 마스킹 처리를 합니다. | adjh54@naver.com → adj***@naver.com |
import lombok.NoArgsConstructor;
@NoArgsConstructor
public class MaskingUtil {
/**
* 이메일 주소에 대한 마스킹을 수행합니다.
*
* @param email {String} : 마스킹 이전 이메일 주소
* @return {String} 마스킹 된 이메일 주소
*/
public static String maskEmail(String email) {
// 기본 형식에 맞지 않는 이메일 주소의 경우, 파라미터 값을 그대로 반환합니다.
if (email == null || !email.contains("@")) {
return email;
}
String[] parts = email.split("@");
String idPart = parts[0]; // 아이디
String domainPart = parts[1]; // 이메일 도메인
// 기본 형식에 맞지 않는 이메일 주소의 경우, 파라미터 값을 그대로 반환합니다.
if (idPart.length() <= 3) {
return email;
}
StringBuilder maskedEmail = new StringBuilder();
maskedEmail.append(idPart.substring(0, 3));
for (int i = 3; i < idPart.length(); i++) {
maskedEmail.append('*');
}
maskedEmail.append('@').append(domainPart);
return maskedEmail.toString();
}
public static void main(String[] args) {
// 테스트 케이스
System.out.println(maskEmail("test@example.com")); // tes****@example.com
System.out.println(maskEmail("myemail@domain.com")); // mye*****@domain.com
System.out.println(maskEmail("abc@xyz.com")); // abc@xyz.com
}
}
5) 계좌번호 마스킹
💡 계좌번호 마스킹
- 계좌번호 마스킹의 경우 정해진 계좌번호의 길이는 없지만, 앞 뒤 3자리씩 남겨두고 중간에 숫자를 마스킹 처리를 합니다.
계좌번호 길이 | 계좌번호 마스킹 방법 | 예시 |
3자리 | 3자리 계좌번호는 존재하지 않기에 그대로 반환합니다. | 123 → 123 |
4자리 이상 | 앞의 자리 3글자와 뒤에 3글자를 제외하고 모두 “*”으로 마스킹 | 1234567890 → 123****890 |
import lombok.NoArgsConstructor;
@NoArgsConstructor
public class MaskingUtil {
/**
* 계좌번호에 대한 마스킹을 수행합니다.
*
* @param accountNumber {String} : 마스킹 이전 계좌번호
* @return {String} 마스킹 된 계좌번호
*/
public static String maskAccountNumber(String accountNumber) {
// 기본 형식에 맞지 않는 계좌번호의 경우, 파라미터 값을 그대로 반환합니다.
if (accountNumber == null || accountNumber.length() < 7) {
return accountNumber;
}
int length = accountNumber.length();
StringBuilder maskedAccount = new StringBuilder(accountNumber);
// 계좌번호의 앞 3자리와 마지막 3자리를 제외한 부분을 마스킹
for (int i = 3; i < length - 3; i++) {
maskedAccount.setCharAt(i, '*');
}
return maskedAccount.toString();
}
public static void main(String[] args) {
// 테스트 케이스
System.out.println(maskAccountNumber("1234567890")); // 123****890
System.out.println(maskAccountNumber("987654321")); // 987**321
System.out.println(maskAccountNumber("1234567")); // 123*567
}
}
6) 주소 마스킹
💡 주소 마스킹
- 주소 마스킹의 경우, 상세 주소를 제외한 나머지 주소를 마스킹 처리합니다.
- 예를 들어, 도로명이나 건물번호는 그대로 두고, 상세 주소는 마스킹합니다.
주소 마스킹 길이 | 주소 마스킹 방법 | 예시 |
상세 주소 포함 | 도로명/건물번호를 제외하고 상세 주소를 마스킹 | 서울특별시 강남구 테헤란로 123 ABC빌딩 101호 → 서울특별시 강남구 테헤란로 123 ABC빌딩 ***호 |
import lombok.NoArgsConstructor;
@NoArgsConstructor
public class MaskingUtil {
/**
* 주소에 대한 마스킹을 수행합니다.
*
* @param address {String} : 마스킹 이전 주소
* @return {String} 마스킹 된 주소
*/
public static String maskAddress(String address) {
// 기본 형식에 맞지 않는 주소의 경우, 파라미터 값을 그대로 반환합니다.
if (address == null || address.length() < 10) {
return address;
}
// 주소를 공백 기준으로 나눔
String[] parts = address.split(" ");
// 상세 주소를 마스킹
StringBuilder maskedAddress = new StringBuilder();
for (int i = 0; i < parts.length - 1; i++) {
maskedAddress.append(parts[i]).append(" ");
}
maskedAddress.append("***");
return maskedAddress.toString();
}
public static void main(String[] args) {
// 테스트 케이스
System.out.println(maskAddress("서울특별시 강남구 테헤란로 123 ABC빌딩 101호")); // 서울특별시 강남구 테헤란로 123 ABC빌딩 ***호
System.out.println(maskAddress("부산광역시 해운대구 해운대로 456 XYZ아파트 202호")); // 부산광역시 해운대구 해운대로 456 XYZ아파트 ***호
}
}
💡 [참고] 해당 전체 내용은 아래의 Github Repository 내에서 확인이 가능합니다.
오늘도 감사합니다. 😀
반응형