Linq 메소드 쓸 때 주의점

LINQ 메소드 등 IEnumerable 형태를 반환하는 메소드들은 내부적으로 yield로 구현되어 있을 가능성이 높습니다. 그렇기 때문에 메모리 사용 측면에서 유리한데요, 즉, 매번 목록을 생성하지 않고 코드블럭을 결합시키기 때문인데, 실질적으로의 조회는 소비하는 코드의 foreach에서 발생하기 때문에 일종의 지연로딩이 됩니다.

물론 문제도 있습니다. 이 문제를 경험하지 않으면 다양한 버그를 양상할 수 있게 되는데요 먼저 문제를 먼저 봅시다.

  • 여러개의 LINQ 메소들을 결합한 결과를 여러번 조회(foreach)하게 되면 그때그때 마다 결합된 메소드 만큼의 수행을 다시 합니다. => 속도가 느려집니다.
  • LINQ 메소드들는 내부적으로 yield를 사용하므로 조회가 소비하는 코드와 결합하게되는데, 전체 조회시간이 길어지면서 멀티스레드의 환경에서 대상(source)의 목록이 바뀌게 되면 예외가 발생하기가 쉬워집니다.

C#은 이런 상황을 제한하지 않으므로 두번째의 문제 특히 소스코드량이 많고 부분작업을 진행하고 있을 때 빈번하게 발생할 수 있습니다.

그래서 LINQ 메소드를 코드에 사용할 때는 모든 결합이 끝나면 마지막에 ToList()로 최종 확정된 목록으로 만들어주는게 좋습니다.

반대로,

yield에 의해 LINQ 메소드가 결합된다는 의미는, 조회할 때마다 결합된 조건들이 반영되므로 다양한 조건들을 미리 생성해 둔 다음, 원천소스에 결합시키는 기법을 사용하면 코드를 우아하게 작성할 수 도 있겠습니다.
이런 장점은 Entity Framework에서 종종 쓰는 기법이 됩니다.