Kotlin Label Return 정리

헨도·2026년 3월 9일

Kotlin

목록 보기
1/4
post-thumbnail

Kotlin에서 map, forEach 같은 고차 함수 내부에서 반복을 제어할 때 @label을 사용할 수 있다.

특히 람다 내부에서 특정 조건일 때 현재 iteration만 건너뛰고 다음 요소로 넘어가고 싶을 때 return@label을 사용한다.

공휴일 정책을 개발하면서 사용했던 Label Return 개념과 사용 방법을 정리해보려고 한다.


문제 상황

외부 API를 통해 공휴일 데이터를 가져온 뒤, 이미 존재하는 날짜는 제외하고 새로운 공휴일만 추출하는 상황

private fun extractNewHolidays (
	existingDates: List<LocalDate>,
    apiDataList: List<openApiResponse>
): List<Holiday> {
	
    return apiDataList.mapNotNull { item ->
    	val data = LocalDate.parse(
        	item.data!!,
            DateTimeFormatter.ofPattern("yyyyMMdd")
        )
        
        if (date in existingDates) {
        	// 이미 존재하는 날짜는 제외
        }
        
        item.dateName?.let {
        	Holiday (
            	name = it,
                date = date
            )
        }
    }
}

여기서 문제는 "이미 존재하는 날짜라면 해당 iteration만 건너뛰고 싶다"


Label Return 사용

이럴 때 return@mapNotNull을 사용할 수 있다.

private fun extractNewHolidays(
    existingDates: List<LocalDate>,
    apiDataList: List<HolidayXmlResponseItem>
): List<Holiday> {

    return apiDataList.mapNotNull { item ->

        val date = LocalDate.parse(
            item.locdate!!,
            DateTimeFormatter.ofPattern("yyyyMMdd")
        )

        if (date in existingDates) return@mapNotNull null

        item.dateName?.let {
            Holiday(
                name = it,
                date = date
            )
        }
    }
}

여기서 핵심 코드는 이 부분이다.

if (date in existingDates) return@mapNotNull null

현재 item에 대한 람다 실행만 종료하고 다음 요소로 넘어간다

또한, mapNotNullnull을 반환하면 결과 리스트에 포함되지 않기 때문에 결과적으로 이미 존재하는 날짜는 필터링되는 효과가 있다.


Label Return이 필요한 이유

Kotlin의 람다는 non-local return이 가능하다.

즉, 람다 내부에서 return을 사용하면 람다를 포함하고 있는 외부 함수가 종료될 수 있다.

fun test() {
	listOf(1, 2, 3).forEach {
    	if (it == 2) return
    }
    
    println("end')
}

이 코드의 실행 흐름은 다음과 같다.

  1. 1 -> 정상 실행
  2. 2 -> return
  3. 3 -> test() 함수 전체 종료

즉, forEach만 종료되는 것이 아니라 외부 함수까지 종료된다.

그래서 이런 상황을 제어하기 위해 Label Return을 사용한다.


Label Return 사용 방식

Kotlin에서는 2가지 방식으로 label을 사용할 수 있다.

  • 명시적 Label
  • 묵시적 Label

명시적 Label

람다에 직접 label을 지정하는 방식

fun test() {
	listOf(1, 2, 3, 4, 5).forEach lit@{
    	if (it == 3) return@lit
        
        print(it)
    }
    
    print(" 명시적 label")
}
1245 명시적 label

it == 3인 경우 현재 람다 실행만 종료하고 다음 iteration으로 넘어간다.

묵시적 Label

람다를 호출한 함수 이름을 label로 사용하는 방식

fun test() {
	listOf(1, 2, 3, 4, 5).forEach {
    	if (it == 3) return@forEach
        
        print(it)
    }
    
    print(" 묵시적 label")
}
1245 묵시적 label

return@forEach는 forEach 람다의 현재 실행만 종료한다.


Label Return 정리

표현의미
return외부 함수까지 종료
return@forEach현재 람다 실행만 종료
return@label지정한 label 람다 실행 종료

예를 들어 아래는 다음과 같은 의미를 가진다.

return @mapNotNull null

현재 요소는 무시하고 다음 요소로 넘어간다


마무리

Kotlin에서 Label Return은 람다 내부의 흐름 제어를 명확하게 만들기 위해 매우 자주 사용된다.

특히 유용한 상황이 있는데...

  • forEach에서 특정 조건일 때 iteration 건너뛰기
  • mapNotNull에서 특정 요소 제외하기
  • 람다 내부에서 외부 함수 종료를 방지하기

처음 보면 낯설 수 있지만, return@함수이름 형태만 이해하면 비교적 쉽게 사용할 수 있다.

profile
Junior Backend Developer

0개의 댓글