데이터클래스에 선언된 필드명을 파일 헤더로 이용하기(실패(?))

Hue·2024년 7월 17일

입력받은 학생의 정보를 CSV 파일로 만들어 저장할 것

유저(학생)에게 입력받을 데이터에 해당하는 데이터 클래스를 통해 StringBuilder에 append()하여 헤더와 내용을 구분하여 작성할 것이다.

그런데 헤더를 작성하려고 보니 유저에게 입력받는 값이 달라지게 되면 그 때마다 유저 데이터 클래스와 파일 헤더 모두 수정해야 하는 것이 흠 별로였다.

이 데이터 클래스로부터 헤더를 받아오게 되면 데이터 클래스 수정하고 값 받는 부분만 수정해주면 되지 않을까 싶어 시도해보았다.

먼저 데이터 클래스를 다음과 같이 만들고

data class Student(
    var name: String,
    var age: Int,
    var grade: Int
)

파일을 만들 클래스에서 클래스의 프로퍼티 이름을 리턴하는 메소드를 만들어준다. (implementation ("org.jetbrains.kotlin:kotlin-reflect:1.9.0") 의존성 추가)

private fun getStudentPropertyNames(): ArrayList<String> {

    val properties = Student::class.memberProperties
    val propertyNames = arrayListOf<String>()
    subjectProperties.forEach { property -> propertyNames.add(property.name) 
    
    return propertyNames
}

파일 헤더 작성할 때 호출

fun writeStudentInfo() {
    try {
        val builder = StringBuilder()
        val header = getStudentPropertyNames()
        
        ...
        
    } catch (e: Exception) {
        ...
    }

값을 확인해보기 위해 로그를 작성하고 첫 화면에서 호출해보았다.

fun writeStudentInfo() {
    try {
        val builder = StringBuilder()
        val header = getStudentPropertyNames()
        Log.i("check", getStudentPropertyNames().toString())
        ...
        
    } catch (e: Exception) {
        ...
    }

예상 [name, age, grade]
결과 [age, grade, name]

잘 가져오긴 했는데 오름차순으로 가져온다. 이러면 나중에 필드명 하나 수정하고 싸그리 고치는 일이 생길 것 같아 그대로 가져올 방법을 GPT에게 물어보았다.

private fun getStudentPropertyNames(): List<KProperty1<PatientData, *>> {
    val properties = Student::class.declaredMemberProperties
    properties.forEach { it.isAccessible = true }

    return properties.sortedBy { it.javaField?.name }
}

declaredMemberProperties를 사용하여 선언된 순서대로 속성 정보를 가져온 다음, sortedBy를 사용하여 javaField?.name 기준으로 정렬하는 것입니다. 이 접근법은 속성의 선언 순서를 보장하지 않지만, 선언된 순서와 동일한 순서로 속성 이름을 가져올 수 있는 다른 방법입니다.

순서를 보장하지 않으면 문제가 있어보였다.
그리고 결국 순서는 그대로였다ㅋ.ㅋ

// 내 방법
[age, gender, id,...

// GPT 방법
[var com.???.???.model.PatientData.age: kotlin.Int?, 
var com.???.???.model.PatientData.gender: com.???.???.model.Gender?, 
var com.???.???.model.PatientData.id: kotlin.String, 
...

내내 이것만 잡고 있을만큼 구현에 중요한 부분은 아니라 헤더는 다음과 같이 하드코딩 했다.

fun writeStudentInfo() {
    try {
        val builder = StringBuilder()
        val header = arrayOf("name", "age", "grade")
        ...
        
    } catch (e: Exception) {
        ...
    }

다른 회사들은 어떻게 하려나... 계속 고민해봐야겠다.

0개의 댓글