728x90

중첩 함수는 나쁜 아이가 아니에요

대게 함수를 중첩 해서 사용은 가능은 하지만 잘 하지 않는다. 그런 이유는 코드가 복잡해지고, 코드가 난해하다는 느낌이 들기도 하기 때문이다.

하지만 중첩 함수가 괜찮은 친구처럼 보이는 경우는 언제일 수 있을까? 내가 생각했을 때엔 응집도를 고려했을 때가 아닐까 싶다.

보통 코드에 대한 응집도를 높이기 위해 관련 있는 코드끼리 모아두려고 한다. 그래서 클래스를 사용한다고 본다. 

그런데 클래스에 들어가는 함수에서, 함수를 호출하는 경우 코드가 복잡해지는 경향이 있다. 왜 그런가 싶으면 코드가 떨어져 있어 연결되어 있음을 볼 수가 없다.

그래서 코드를 파악하기 힘들다.

중첩 함수가 괜찮은 녀석인지 보기 위해 코드를 하나 봐보자.

function order(menu) {
    console.log(menu);
}
 
 
function brand(brandName) {
    switch(brandName) {
        case "ABC_Market":
            order("신발");
            break;
        case "Mart":
            order("음료수");
            break;
    }
}

위 코드와 같이 order가 계속 호출 되니 함수로 따로 빼서 쓰는 것이 맞다.

 

현재는 코드가 짧기 때문에, 그리고 작성한 이는 의도를 알지만, 코드가 길어지거나 다른 이가 보았을 때 코드를 이해하기 쉬울까?

order가 brand에서만 사용되는지 알 수 있을까? 확실하게!? 모를 것이다.

 

그래서 코드의 응집도를 높일 수가 있다.

function brand(brandName) {
    function order(menu) {
        console.log(menu);
    }
    switch(brandName) {
        case "ABC_Market":
            order("신발");
            break;
        case "Mart":
            order("음료수");
            break;
    }
}

남들이 보았을 때 거부감이 들 수 있으나 order 함수가 명확하게 brand에서만 사용이 됨을 알 수 있습니다.


Currying이 뭐에요? 먹는건가요?

 함수형 프로그래밍에서 나오는 개념으로, 기존의 복잡한 파라미터를 넘겨 복잡한 처리를 하는 함수를 읽기 쉬운 나누어진 코드로 변경하는 것을 말한다.

코드를 한번 봐보자.

function Hello(text) {
    return function (text2) {
        console.log(text, text2);
    }
}

이게 무슨 코드인지 너무 난해하다고 느낄 수 있다. 하지만 사용 방법은 더 난해하다.

코드를 보고 다 고개를 절레절레 지울 수 있는 으뜸한 코드가 완성되었다.

사실 그렇게 나쁘지 않아요 ( ╯□╰ )

함수를 호출 시에 파라미터를 저렇게 넘겨서 사용하니 정말 별로에 별로이지만 다음 호출 방법을 보면 생각이 조금 달라진다.

let hello_Name_To_Text = Hello("아무개님");
hello_Name_To_Text("안녕하세요");

이렇게 작성하니 뭔가 편해지는 느낌과 더불어 머리에 이런 방법도 가능하네?

기존에 불편하게 작성했던 코드를 쉽게 작성할 수 있을 것 같은 생각이 날 수 있다.

  • Partial Application은 Currying 방법을 다르게 부르는 동의어라고 보시면 됩니다.

기존에 하나의 함수에서 복잡하게 작성하였던 코드들이 잘게 분리되면서 복잡도가 낮아지며 코드가 유연해지는 쪽으로 사용하면 좋을 것이다.

  • 참고, 화살표를 사용한 코드 단축화

 코드가 중복적으로 들어가는 쓸데없는 코드를 보일러레이트 코드(Boilerplate code)라 부른다. 위 에서는 function과 return으로 코드가 장풍을 맞은 것마냥 들어가버린다.

이를 없앨 수 있는 방법은 화살표다. const로 변수처럼 함수를 사용할 때엔 Func를 붙이기를 추천하고, 아래 코드가 짧아지긴 했으나 더 헷갈릴 것 같다는 생각이 든다.

const Hello = text => text2 => {
        console.log(text, text2);
}

왜 갑자기 확장 함수가 떠오를까?

위 코드들을 보다 보면 확장 함수가 생각난다. 코틀린에서 확장 함수를 지원해주는데 뭔가 위 코드와 비슷한 것 같은 느낌이 든다.

fun List<Int>.getHigherThan(num: Int): List<Int> {
    val result = arrayListOf<Int>()
    for (item in this) {
        if (item > num) {
            result.add(item)
        }
    }
    return result
}
 
fun main() {
    val numbers: List<Int> = listOf(1, 2, 3, 4, 5, 6)
    val filtered = numbers.getHigherThan(3).toString()
    System.out.println(filtered)
}

확장 함수는 다음 코드와 같이 돌아간다.

눈 여겨 볼만한 것은 List<Int>라는 타입에 getHigarThan을 넣었다는 점이다.

기존이었다면 getHigherThan 함수를 만들고 getHigherThan(numbers, 3).toString()으로 호출했을 것이다.

 numbers.getHigherThan(3).toString() 코드에 비해  getHigherThan(numbers, 3).toString()은 어디로부터 시작하는지 명시가 되어있지 않는다는 느낌이 든다.

정리

위 모든 코드들이 코드를 단순하게 만들기 위한 기법이라 생각한다. 생소하지만 어느 한 구석 잘 적용한다면 유지 보수하기 좋은 코드가 탄생할 것일까 말까 아무도 모른다.

 

 
반응형

'코딩 관련 > 자바스크립트' 카테고리의 다른 글

generator function  (0) 2023.10.19
getDay(), getDate()  (0) 2023.10.19
Map 섞어 쓰면 에러 발생  (0) 2023.10.19
Javascript Template literal  (1) 2023.10.19
배열 초기화 & Json 값만 배열로 변경하기  (0) 2023.10.19

+ Recent posts