재귀함수는 항상 나쁜걸까?

재귀함수?

재귀함수는 일정 조건이 만족될 때 까지 자기 자신을 계속해서 호출하는 함수이다.
간단한 예를 들어본다면

def factorial(x):
    if x == 1:
        return 1
    else:
        return (x * factorial(x-1))

위의 함수는 입력받은 수의 팩토리얼을 계산하는 함수이다.
이 처럼 함수 내부에서 자기자신을 계속해서 호출하는 함수를 재귀함수라고 하며, 특정 조건이 만족 될 경우 차례로 그 결과가 반환되는 방식으로 작동한다.

재귀함수는 나쁘다? 쓰면 안된다?

나와 같은 고민을 한 사람이 한 명도 없을리 없다.
검색해보니 Stack Overflow에 명쾌한 답변이 있었다.

내용을 요약해보면 아래와 같다.

재귀함수는 실무에서 쓸 수 없는 방식이 아닙니다. 단지, 선택지 중 하나일 뿐입니다.
트리 구조나 같은 로직을 계속해서 반복해야할 때 쓰기 좋습니다.
그러나 오버플로가 생길 수 있습니다.
너무 큰 데이터를 사용하지 않도록 주의하세요!

실제로 재귀함수를 서비스에 사용해본 경험

재귀함수를 API에 사용할 때 고려한 사항은 두가지였다.
1. 해당 API의 호출 정도가 얼마나 빈번한가?
2. 해당 함수가 처리하는 데이터의 크기가 어느 정도인가?

재귀함수를 사용한 API는 한 홈페이지의 admin 페이지 메뉴 변경 기능이였다.

메뉴의 데이터베이스 구조는 위와 같았다. 자식과 부모의 관계가 N:1 이었다.

필요한 기능은, Json 형태로 들어오는 새 메뉴 구조를 저장하는 것이었다.
들어오는 구조는 아래와 같았다.


    "menus": [
        {
            "url": "notice",
            "name": "공지사항",
            "children": []
        },
        {
            "url": "board",
            "name": "게시판",
            "children": [
                {
                    "url": "open",
                    "name": "잡담",
                    "children": [
                        {
                            "url": "open1",
                            "name": "잡담 게시판1",
                            "children": []
                        }
                    ]
                }
            ]
        }
    ]
}

메뉴의 depth는 기획에 따라 언제든 3단 이상으로 증가할 수 있는 상황이었다.

재귀함수를 사용하지 않고 해당 기능을 구현할 방법은 있었을 것이다.
그러나 재귀함수를 사용하면 코드가 훨씬 간결할 것이라고 생각했다.

위의 질문에 답변을 생각해보았다.
1) 해당 API의 호출 정도가 얼마나 빈번한가?

  • 관리자가 메뉴를 변경하는 빈도수는 매우 낮을 것으로 예상됨

2) 해당 함수가 처리하는 데이터의 크기가 어느 정도인가?

  • 메뉴에 필요한 데이터는 데이터베이스 상에서, id(int), name(string), url(string), parent(int)로 상대적으로 작음
  • 메뉴는 따로 버전관리를 하지 않으며, 새 메뉴 구조가 만들어질 경우 메뉴를 일괄 삭제하고 새 메뉴를 저장하기 때문에 처리할 데이터의 크기는 상대적으로 작음

위의 답변을 생각해보았을 때, 재귀함수를 사용하지 않을 이유는 없었다.
개발 팀원과 상의 후 큰 문제가 없다고 결론이 내려졌고, 간단하고 확장성있는 API를 작성하게 되었다.

참고자료: Is recursion a Bad Practice in general?, stack overflow

좋은 웹페이지 즐겨찾기