Where The Streets Have No Name

linq.js 본문

Developement/Web

linq.js

highheat 2026. 5. 12. 12:35

JavaScript에서 C# LINQ처럼 데이터 다루기 - linq.js 정리

업무 시스템이나 프론트엔드 개발을 하다 보면 배열 데이터에 대해 조회, 정렬, 그룹화, 집계 같은 처리를 많이 하게 된다.

JavaScript에서는 기본적으로 map, filter, reduce 같은 메서드를 제공하지만,
복잡한 데이터 처리에서는 코드가 길어지고 가독성이 떨어지는 경우가 있다.

이럴 때 사용할 수 있는 라이브러리 중 하나가 linq.js이다.


1. linq.js란?

linq.js는 .NET의 LINQ(Language Integrated Query)를 JavaScript에서 사용할 수 있도록 만든 라이브러리이다.

배열, 객체, 문자열 등의 데이터를 Enumerable 객체로 감싼 뒤 다음과 같은 메서드를 체이닝 방식으로 사용할 수 있다.

  • Where
  • Select
  • GroupBy
  • Join
  • OrderBy
  • Sum
  • Average
  • Distinct

즉, JavaScript 데이터를 SQL이나 C# LINQ처럼 선언적으로 다룰 수 있게 해주는 도구라고 볼 수 있다.


2. 현재 기준 저장소

linq.js는 원래 neuecc/linq.js 프로젝트로 시작되었다.

하지만 원본 저장소는 2019년에 archive 되었고 현재는 유지보수되지 않는다.

현재는 mihaifm/linq fork를 기준으로 사용하는 것이 좋다.

설치

npm install linq

ES Module 방식

import Enumerable from "linq";

CommonJS 방식

CommonJS 환경에서는 버전 3 사용이 안내되어 있다.

npm install linq@3
const Enumerable = require("linq");

3. 기본 사용법

linq.js의 기본 흐름은 다음과 같다.

Enumerable.from(데이터)
  .where(조건)
  .select(변환)
  .toArray();

예제:

import Enumerable from "linq";

const result = Enumerable.from([1, 2, 3, 4, 5, 6])
  .where(x => x % 2 === 0)
  .select(x => x * 10)
  .toArray();

console.log(result);

실행 결과:

[20, 40, 60]

4. JavaScript 기본 배열 메서드와 비교

JavaScript 기본 방식

const users = [
  { id: 1, name: "Kim", dept: "IT", age: 30 },
  { id: 2, name: "Lee", dept: "HR", age: 25 },
  { id: 3, name: "Park", dept: "IT", age: 35 }
];

const result = users
  .filter(user => user.dept === "IT")
  .map(user => user.name);

console.log(result);

결과:

["Kim", "Park"]

linq.js 방식

import Enumerable from "linq";

const result = Enumerable.from(users)
  .where(user => user.dept === "IT")
  .select(user => user.name)
  .toArray();

console.log(result);

결과:

["Kim", "Park"]

단순한 filter, map 정도는 JavaScript 기본 메서드가 더 간단하다.

하지만 다음과 같은 처리가 많아지면 linq.js가 더 읽기 쉬워질 수 있다.

  • GroupBy
  • Join
  • OrderBy
  • Distinct
  • Sum
  • Average

5. 정렬(OrderBy)

const users = [
  { name: "Kim", dept: "IT", age: 30 },
  { name: "Lee", dept: "HR", age: 25 },
  { name: "Park", dept: "IT", age: 35 }
];

const result = Enumerable.from(users)
  .orderBy(user => user.dept)
  .thenByDescending(user => user.age)
  .select(user => ({
    name: user.name,
    dept: user.dept,
    age: user.age
  }))
  .toArray();

console.log(result);

6. 그룹화(GroupBy)

부서별 인원 수를 구하는 예제이다.

const users = [
  { id: 1, name: "Kim", dept: "IT" },
  { id: 2, name: "Lee", dept: "HR" },
  { id: 3, name: "Park", dept: "IT" }
];

const result = Enumerable.from(users)
  .groupBy(
    user => user.dept,
    user => user,
    (dept, group) => ({
      dept,
      count: group.count()
    })
  )
  .toArray();

console.log(result);

결과:

[
  { dept: "IT", count: 2 },
  { dept: "HR", count: 1 }
]

7. 합계(Sum)

const orders = [
  { item: "A", qty: 2, price: 1000 },
  { item: "B", qty: 1, price: 3000 },
  { item: "C", qty: 5, price: 500 }
];

const total = Enumerable.from(orders)
  .sum(order => order.qty * order.price);

console.log(total);

결과:

7500

8. Join 예제

두 배열을 조인하는 예제이다.

const users = [
  { id: 1, name: "Kim", deptId: "D01" },
  { id: 2, name: "Lee", deptId: "D02" },
  { id: 3, name: "Park", deptId: "D01" }
];

const departments = [
  { id: "D01", name: "개발팀" },
  { id: "D02", name: "인사팀" }
];

const result = Enumerable.from(users)
  .join(
    departments,
    user => user.deptId,
    dept => dept.id,
    (user, dept) => ({
      userName: user.name,
      deptName: dept.name
    })
  )
  .toArray();

console.log(result);

결과:

[
  { userName: "Kim", deptName: "개발팀" },
  { userName: "Lee", deptName: "인사팀" },
  { userName: "Park", deptName: "개발팀" }
]

9. 지연 평가(Lazy Evaluation)

linq.js의 중요한 특징 중 하나는 lazy evaluation(지연 평가)이다.

where, select 같은 중간 연산은 즉시 실행되지 않는다.

실제로는 toArray(), first(), count() 같은 최종 연산이 호출될 때 평가된다.

const query = Enumerable.from([1, 2, 3, 4, 5])
  .where(x => {
    console.log("where:", x);
    return x % 2 === 0;
  })
  .select(x => {
    console.log("select:", x);
    return x * 10;
  });

console.log("아직 실행 안 됨");

const result = query.toArray();

console.log(result);

이런 구조 덕분에 중간 배열 생성을 줄일 수 있다.


10. JavaScript 기본 기능과의 차이

JavaScript 자체도 이미 강력한 배열 메서드를 제공한다.

array.filter(...)
array.map(...)
array.reduce(...)
array.find(...)
array.some(...)
array.every(...)

따라서 단순 배열 처리만 한다면 굳이 linq.js가 필요하지 않을 수도 있다.

하지만 다음과 같은 경우에는 유용하다.

  • C# LINQ에 익숙한 개발자가 JavaScript를 다룰 때
  • SQL 스타일 데이터 처리를 선호할 때
  • GroupBy, Join, Sum 같은 처리가 많은 경우
  • 업무 시스템에서 조회 데이터를 가공하는 경우

11. 주의할 점

1) 최신 JavaScript 기능과 비교 필요

최근 JavaScript는 기본 배열 메서드가 매우 강력하다.

단순 데이터 처리라면 기본 메서드만으로도 충분한 경우가 많다.


2) 번들 크기 고려

프론트엔드 프로젝트에서는 라이브러리 추가에 따른 번들 크기 증가를 고려해야 한다.


3) 모듈 방식 확인 필요

최신 npm 패키지는 ES Module 기준이다.

Node.js 환경에서는 CommonJS 여부를 확인해야 한다.


12. 정리

linq.js는 JavaScript에서 C# LINQ 스타일의 데이터 처리를 가능하게 해주는 라이브러리이다.

단순 배열 처리라면 JavaScript 기본 메서드가 더 간단할 수 있다.

하지만 다음과 같은 상황에서는 상당히 유용하다.

  • 복잡한 데이터 가공
  • 그룹화 및 집계
  • SQL 스타일 처리
  • 업무 시스템 데이터 변환
  • C# 개발자의 JavaScript 작업

특히 ERP, 통계 화면, 조회 데이터 가공처럼
JSON 데이터를 화면용으로 재구성하는 작업에서 꽤 편리하게 사용할 수 있다.


참고 링크

원본 프로젝트

https://github.com/neuecc/linq.js

현재 유지보수 fork

https://github.com/mihaifm/linq

npm

https://www.npmjs.com/package/linq