iOS/Swift

for - in / forEach 차이점

KemiKIM 2023. 1. 14. 00:13

 

why?

코드로 작업을 하는 도중 문득, for-in과 forEach의 정확한 차이점이 뭔지 궁금해졌습니다.

뭔가.. 정확한 의미 없이 쓰는 느낌(?)이 좀 들어서, 이번 포스팅 기회로 정확하게 알고자 공부하였습니다.

 

모든 collection을 비교하는 건, 내용이 너무 길어질 것 같아서

비교적 가장 많이 쓰이는 배열(Array)를 대표적인 예시로 설명해보겠습니다.

(모든 예제코드는 playground로 작성되었으며, 하단의 주석은 결과값을 나타냅니다.)

 

 

 

 


 

 

 

 

1. for - in (Array)

컬렉션(여기선 Array)에 저장된 요소 수만큼 반복되며, 저장된 요소가 루프 상수에 하나씩 들어간다.

 

 

 

끊어서 차근차근 읽어보겠습니다.

컬렉션(=Array)에  /  저장된 요소 수만큼  /  반복  /  되며

저장된 요소가  /  루프 상수에  /  하나씩  /  들어간다.

(여기서 루프 상수란, for와 in 사이에 개발자가 선언하는 상수를 의미합니다. 보통 i를 많이 사용하죠.)

 

 

예시 코드를 하나 보겠습니다.

let apple: [String] = ["iPhone", "iPad", "Macbook","AirPods"]
    
for i in apple {
  print(i)
}
   

 // ==== console
 // iPhone
 // iPad
 // Macbook
 // AirPods

 

아주 간단한 코드죠?

apple이란 배열을 for - in 함수에 반복시킨 결과를 나타내고 있습니다.

이제 이 코드를 천천히 해석해봅시다.

 

 

 

for - in 정의를 대입해서 다시 살펴보면, 

 

"apple이란 배열(array)가 있을 때, apple의 요소 갯수( = 총 갯수) 만큼 반복한다."

 

라고 해석해볼 수 있습니다.

 

 

 

1번째 반복: i란 루프 상수에 apple[0] -> "iPhone"

2번째 반복: i란 루프 상수에 apple[1] -> "iPad"

3번째 반복: i란 루프 상수에 apple[2] -> "Macbook"

4번째 반복: i란 루프 상수에 apple[3] -> "AirPods"

 

그럼 n번째 반복은? -> i란 루프 상수에 apple[n-1] 이라고 생각할 수 있겠네요.

 

 

 

 

이제 forEach함수를 살펴봅시다.

 

 

 

 

2. forEach (Array)

반복 실행하려는 코드를 파라미터로 받고, 저장된 요소는 클로저 상수로 전달된다.

 

 

여기서 가장 주목해야할 부분은, '전달'이라는 단어를 중심으로 생각해보시면 됩니다.

 

 

 

예시코드를 살펴보시죠.

let apple: [String] = ["iPhone", "iPad", "Macbook","AirPods"]
    
apple.forEach { i in
  print(i)
}
   
   
 // ==== console
 // iPhone
 // iPad
 // Macbook
 // AirPods

(forEach의 경우 i in을 생략하고, print($0)로도 사용할 수 있습니다. 여기선 정확한 설명을 위해 상세구현합니다.)

 

역시 간단한 코드입니다. apple이란 배열을 forEach 함수에 반복시킨 결과를 나타내고 있습니다.

동일하게 이 코드를 천천히 해석해봅시다.

 

 

 

forEach 정의를 대입해서 다시 살펴보면, 

 

"apple이란 배열(array)가 있을 때, 반복 실행하려는 코드(print)를 파라미터(forEach)로 받고,

이렇게 저장된 요소는 클로저 상수( i )로 전달되어 실행된다."

 

라고 해석해볼 수 있습니다.

 

 

 

즉, '반복하려는 내용을 묶어서 통째로 넘겨준다'라고 생각해볼 수도 있겠네요.

 

 

 

 


 

 

 

두 함수의 결과값은 동일하나 분명 '다릅니다'

 

 

for-in = 개발자가 '수동 구현'하는 '반복문'

forEach = 개발자가 클로저로 작성해서 넘겨주는 것. = '자동 구현'

 

 

수동 구현을 한다는 것은 개발자가 컨트롤할 수 있지만,

자동 구현을 한다면, 개발자가 일일이 컨트롤할 수 없습니다.

 

 

 

이 말을 코드에 대입해보면,

우리가 반복문을 쓸 때 대표적으로 사용하는 코드들이

break, continue, return 등이 있을텐데, 이 용어들이 대략 어떻게 사용될지 감이 오시나요?

 

 

 

for-in ( 수동 구현 )이라면, break, continue, return을 사용했을 때,

 

i란 루프 상수에 apple[0]의 값이 추출되고 나서

break(멈추거나)

continue(계속 시키거나)

return(끝내거나)

할 수 있겠죠?

// (1) break
func forinVSforEach1() {
  let apple: [String] = ["iPhone", "iPad", "Macbook","AirPods"]
    
  for i in apple {
    print(i)
    break
  }
  
}

forinVSforEach1() // 실행
 
 // ==== console
 // iPhone
 
 
 // ----
 
 
// (2) continue
func forinVSforEach2() {
  let apple: [String] = ["iPhone", "iPad", "Macbook","AirPods"]
    
  for i in apple {
    print(i)
    continue
  }
  
}

forinVSforEach2() // 실행
 
 // ==== console
 // iPhone
 // iPad
 // Macbook
 // AirPods
 
 
 // ----
 
 
 // (3) return
func forinVSforEach3() {
  let apple: [String] = ["iPhone", "iPad", "Macbook","AirPods"]
    
  for i in apple {
    print(i)
    return
  }
  
}

forinVSforEach3() // 실행
 
 // ==== console
 // iPhone

 

 

 

하지만, forEach ( 자동 구현 )이라면?

 

클로저로 작성해서 자동구현하라고 통째로 값을 넘겨줬기 때문에,

break(멈춰야하는데, 멈출게 없어서 -> 불가능),

continue(계속 시켜야하는데, 시킬게 없어서 -> 불가능)

return(끝내야하는데, 자동구현이 다 끝난다음에 즉, 클로저 상수가 끝나고 나서 끝낼 수 있음.)

 (즉 -> 가능은 하지만, 다음 클로저 상수가 없다면, 쓸모 X)

// (1) break
func forinVSforEach1() {
  let apple: [String] = ["iPhone", "iPad", "Macbook","AirPods"]
    
  apple.forEach { i in
    print(i)
    break // Error!
  }
  
}

forinVSforEach1() // 실행
 
 // ==== console
 // Error!
 
 
 // ----
 
 
// (2) continue
func forinVSforEach2() {
  let apple: [String] = ["iPhone", "iPad", "Macbook","AirPods"]
    
  apple.forEach { i in
    print(i)
    continue // Error!
  }
  
}

forinVSforEach2() // 실행
 
 // ==== console
// Error!
 
 
 // ----
 
 
 // (3) return
func forinVSforEach3() {
  let apple: [String] = ["iPhone", "iPad", "Macbook","AirPods"]
    
  apple.forEach { i in
    print(i)
    return
  }
  
}

forinVSforEach3() // 실행
 
 // ==== console
 // iPhone
 // iPad
 // Macbook
 // AirPods

 

 


 

이렇게 간단히 for - inforEach에 대해 알아보았습니다.!

헷갈리는 내용이였는데, 천천히 정리하니 생각보다 재밌고,

어떤 상황에서 쓰일지 기대되네요.

 

오류가 있거나, 피드백이 있다면 언제든지 댓글로 알려주세요!

감사합니다 :)