Outsider's Dev Story

Stay Hungry. Stay Foolish. Don't Be Satisfied.
RetroTech 팟캐스트 44BITS 팟캐스트

forEach에 break문 대신 some 사용하기

프로그래밍 언어에는 컬렉션의 요소를 순회하는 forEach문이 존재한다. 자바스크립트에서는 forEach이고 자바에서 for이고 jQuery에서는 each이다. 언어마다 모양은 약간이 달라도 사용방법은 다 동일하다. forEach는 배열이나 객체의 모든 요소를 순회하는 함수인데 사오항에 따라서는 모든 요소를 순회하지 않아도 될 때가 있다. 이럴때 사용하는 것이 break문인데 몇몇 언어에서는 break문을 제공하지 않고 있다. 예를 들어 자바스크립트에도 forEach문은 있지만 break문은 없고 스칼리에서도 2.8이 되어서야 break문이 추가되었다.

어떻게 break문이 없을 수 있는가 궁금하기도 했지만 (나도 잘 모르지만) 이는 약간 함수형 언어의 컨셉적인 부분으로 컬렉션을 순회하는 forEach문이 모두 순회하는 걸 당연하게 생각하고 있기 때문인것 같다. 컬렉션자체를 하나의 객체로 보고 객체를 다루는 메서드로 보고 절차적인 go to문과 비슷한 break문을 포함하지 않는 것같다.(그래도 많은 개발자들이 불평해서인지 대부분은 break문 혹은 return문으로 break의 역할을 할 수 있다. ) 홍민희님이 알려주셨는데 언어차원의 의도적인 결정은 아니고 미처 구현안한 것 뿐이랍니다. 


자바스크립트를 예로 들어보자.

[1,2,3,4,5].forEach(function(v) {
  if (v==2) console.log(v)
});

배열의 값이 2인 경우만 출력하도록 한 것으로 이렇게 배열중 일부값을 찾아서 뭔가를 수행하고자 하는 것이다. 위 예제는 잘 동작하지만 사실 이 예제는 2를 출력한 후에도 불필요하게 3,4,5도 순회하게 되기 때문에 여기서 성능을 위해서 break문으로 불필요한 순회를 없애고 싶어진다.

var Break = new Error('Break');

try {
  [1,2,3,4,5].forEach(function(v) {
    if (v==2) {
      console.log('v: ', v)
      throw Break;
    }
  });
} catch (e) {
  if (e!= Break) throw Break; 
}

자바스크립트의 경우 break문이 없기 때문에 위처럼 Break라는 커스톰 오류객체를 정의해서 순회하다가 멈춰하 하는 곳에서 예외를 던져서 순회를 멈출 수 있다. 이는 try-catch를 교묘히 이용해서 원하는 동작을 하도록 한 것이지만 코드에서 보듯이 원하는 것에 비해서 코드가 너무 지저분해져서 가독성도 그다지 좋지 않다.

여기서 forEach에 break 조합대신 사용할 수 있는 것이 some()이다. some은 컬렉션의 요소 중 최소 1개라도 조건을 만족시키는지 검사하는 메서드이고 언어에 따라 some이 아닌 경우도 있지만 비슷한 기능을 하는 언어는 존재한다.(스칼라의 경우에는 exists이다.) 위에서 작성한 예제와 똑같은 함수를 some()를 사용해서 다음과 같이 작성할 수 있다.

[1,2,3,4,5].some(function(v) {
   if(v == 2) console.log(v);
   return (v ==2);
});

some()은 조건이 true가 되는 순간 순회를 멈추기 때문에 우리가 원하는 동작을 충족시킬 수 있다. 억지로 break문을 사용하는 것보다는 훨씬 소스도 깔끔해 졌고 함수의 용도에도 맞아보인다.
2012/10/06 02:31 2012/10/06 02:31