[그룹웨어] 공통 기능 만들기_Util (toString 기능 만들기)

yihyun·2024년 12월 14일

ERP 개발 프로젝트

목록 보기
8/11

toString 공통 기능 만들기

개발을 하다 보면, 메서드나 서비스로 전달된 파라미터 값을 확인해야 할 일이 자주 있다.

간단한 경우에는 System.out.println()으로 출력할 수 있지만, 다음과 같은 상황에서는 조금 더 복잡해진다.

  • 배열이나 컬렉션(List, Map, Set 등): 객체의 값을 일일이 확인하기 위해 반복문 필요
  • DTO(사용자 정의 객체): 객체 내부 필드 값을 확인하기 위해 별도의 toString() 메서드를 오버라이드 해야함
  • 기타 복합 데이터 구조: Map 내부의 값이 List인 경우 등 중첩된 데이터를 확인하려면 더 많은 코드가 필요

이럴 때 어떤 객체든 문자열로 변환하여 구조와 값을 확인할 수 있는 공통 toString 기능이 있다면 개발 생산성을 크게 높일 수 있을거라 생각해 공통 기능을 개발해보았다!

주요 기능

  • String, Number, Boolean 등 단순 객체는 toString()을 사용.

  • Array(배열), List, Map, Set, DTO 등 복합 객체는 각 형태에 맞게 처리.

  • 배열(Array) 출력 지원:배열의 각 요소를 순회하여 문자열로 변환하고, [value1, value2] 형식으로 출력.

  • 컬렉션(Collection) 출력 지원: List, Set 등 Collection 타입은 각 요소를 순회하여 문자열로 변환.

  • 맵(Map) 출력 지원:Map 타입은 각 키-값 쌍을 순회하여 key: value 형식으로 변환.

  • DTO 출력 지원: 객체의 모든 필드를 반영하여 필드명=값 형태로 출력.

  • Reflection을 사용하여 private 필드도 포함.
    → 자바 리플렉션(Reflection) API를 활용해 객체의 private 접근 제한자를 무시하고, 해당 필드의 값을 읽을 수 있게 처리

코드

	public static String toString(Object obj) {
		
		if(obj == null) {
			return "null";
		}
		
		if(obj instanceof String || obj instanceof Number || obj instanceof Boolean || obj instanceof Character) {
			return obj.toString();
		} else if(obj.getClass().isArray()) {
			int length = Array.getLength(obj);
			StringBuilder sb = new StringBuilder("[");
			for (int i = 0; i < length; i++) {
				sb.append(Array.get(obj, i)); 
				if(i < length -1) {
					sb.append(", ");
				}
				
			}
			sb.append("]");
			return sb.toString();
		} else if(obj instanceof Collection) {
			Collection<?> collection = (Collection<?>) obj;
			StringBuilder sb = new StringBuilder("[");
			for (Object item : collection) {
				sb.append(toString(item)).append(",");
			}
			
			if(!collection.isEmpty()) {
				sb.setLength(sb.length() -2); // 마지막 콤마 제거
			}
			
			sb.append("]");
			return sb.toString();
			
		} else if(obj instanceof Map) {
			Map<?, ?> map = (Map<?, ?>) obj;
			StringBuilder sb = new StringBuilder("{");
			for (Map.Entry<?, ?> entry : map.entrySet()) {
				sb.append(toString(entry.getKey()))
				.append(" : ")
				.append(toString(entry.getValue()))
				.append(", ");
			}
			
			if(!map.isEmpty()) {
				sb.setLength(sb.length() -2);
			}
			sb.append("}");
			return sb.toString();
		} else {
			return dtoToString(obj);
		}
			
	}
    
    public static String dtoToString(Object obj) {
        StringBuilder sb = new StringBuilder();
        Class<?> clazz = obj.getClass();
        sb.append(clazz.getSimpleName()).append(" {");

        // 모든 필드 가져오기
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            // static 필드는 무시
            if (Modifier.isStatic(field.getModifiers())) {
                continue;
            }

            field.setAccessible(true); // private 필드 접근 가능하도록 설정
            try {
                Object value = field.get(obj); // 필드 값 가져오기
                sb.append(field.getName())
                  .append("=")
                  .append(value)
                  .append(", ");
            } catch (IllegalAccessException e) {
                sb.append(field.getName()).append("=ACCESS_ERROR, ");
            }
        }

        if (fields.length > 0) {
            sb.setLength(sb.length() - 2); // 마지막 콤마 제거
        }

        sb.append("}");
        return sb.toString();
    }

사용 예시

  1. 기본 객체
System.out.println(toString("Hello")); // "Hello"
System.out.println(toString(42));      // "42"
  1. 배열
int[] arr = {1, 2, 3};
System.out.println(toString(arr)); // "[1, 2, 3]"
  1. 컬렉션
List<String> list = Arrays.asList("Apple", "Banana", "Cherry");
System.out.println(toString(list)); // "[Apple, Banana, Cherry]"
Map<String, Integer> map = new HashMap<>();
map.put("A", 1);
map.put("B", 2);
System.out.println(toString(map)); // "{A: 1, B: 2}"
  1. DTO
class User {
    private String name;
    private int age;

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

User user = new User("John", 30);
System.out.println(toString(user)); // "User {name=John, age=30}"



이제 개발할 때 데이터를 확인하는데 중복 코드를 줄이고 조금 더 쉽게 값을 확인할 수 있게 되었다!!

뿌듯하다!! 🥳🥳

profile
개발자가 되어보자

0개의 댓글