Skip to content
Back to skills

Replace Loop With Pipeline

ASecurity

명령형 for/while 루프를 Stream API/Collection Pipeline으로 변환하여 데이터 흐름 의도 명확화. "스트림으로 바꿔", "루프를 파이프라인으로", "for문 stream", "/replace-loop-with-pipeline" 요청 시 사용. 단, 루프 안 로직이 컬렉션 클래스로 모여야 하면 /first-class-collection이 적합. /replace-loop-with-pipeline [commit-ref]로 호출.

  • 8 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added September 20, 2026
code-qualitygojavarefactoringgitapi

Works with

  • api

Security analysis

A100/100

Scanned September 20, 2026

npx -y skills add msbaek/msbaek-claude-plugins --skill replace-loop-with-pipeline --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Replace Loop With Pipeline?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Replace Loop With Pipeline
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/msbaek-replace-loop-with-pipeline/badge)](https://www.skillsdirectory.com/skills/msbaek-replace-loop-with-pipeline)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: replace-loop-with-pipeline
description: 명령형 for/while 루프를 Stream API/Collection Pipeline으로 변환하여 데이터 흐름 의도 명확화. "스트림으로 바꿔", "루프를 파이프라인으로", "for문 stream", "/replace-loop-with-pipeline" 요청 시 사용. 단, 루프 안 로직이 컬렉션 클래스로 모여야 하면 /first-class-collection이 적합. /replace-loop-with-pipeline [commit-ref]로 호출.
argument-hint: "[commit-ref]"
---

# Replace Loop with Pipeline

## GOAL

명령형 루프를 Stream API/Collection Pipeline으로 변환하여:
- **what** vs **how**: Pipeline은 "무엇을" 하는지, 루프는 "어떻게" 하는지 표현
- 필터링/변환/집계의 의도가 메서드 체인으로 드러남
- 중간 변수/플래그 변수 제거

## CONSTRAINTS

- **계열**: Tidy — 후보 보고 후 **승인 없이 적용** (`../../references/refactoring-procedure.md` §0·§3-A)
- **동작 변경 금지**: 구조 개선만 수행 (기능 변경 없음)
- **테스트 수정 금지**: 구조 변경이 테스트를 실패시키면 되돌리기
- **명시적 git add**: `git add -A` 금지, 변경된 파일만 명시

## 적용 패턴

### 패턴 1: 필터링 + 변환
```java
// Before
List<String> result = new ArrayList<>();
for (Order order : orders) {
    if (order.isActive()) {
        result.add(order.getCustomerName());
    }
}

// After
List<String> result = orders.stream()
    .filter(Order::isActive)
    .map(Order::getCustomerName)
    .toList();
```

### 패턴 2: 집계
```java
// Before
int total = 0;
for (LineItem item : items) {
    if (item.getQuantity() > 0) {
        total += item.getPrice() * item.getQuantity();
    }
}

// After
int total = items.stream()
    .filter(item -> item.getQuantity() > 0)
    .mapToInt(item -> item.getPrice() * item.getQuantity())
    .sum();
```

### 패턴 2-1: 집계 — 객체 타입 (BigDecimal 등)

primitive가 아닌 타입은 `sum()`이 없으므로 `reduce(항등원, 누적 연산)`을 쓴다.
금액(BigDecimal) 합산이 대표 사례:

```java
// Before
BigDecimal total = BigDecimal.ZERO;
for (Line line : lines) {
    total = total.add(line.amount());
}

// After
BigDecimal total = lines.stream()
    .map(Line::amount)
    .reduce(BigDecimal.ZERO, BigDecimal::add);
```

### 패턴 3: 검색 (첫 번째 매칭)
```java
// Before
Employee found = null;
for (Employee e : employees) {
    if (e.getDepartment().equals("Engineering")) {
        found = e;
        break;
    }
}

// After
Optional<Employee> found = employees.stream()
    .filter(e -> e.getDepartment().equals("Engineering"))
    .findFirst();
```

### 패턴 4: 존재 여부 확인
```java
// Before
boolean hasOverdue = false;
for (Invoice invoice : invoices) {
    if (invoice.isOverdue()) {
        hasOverdue = true;
        break;
    }
}

// After
boolean hasOverdue = invoices.stream()
    .anyMatch(Invoice::isOverdue);
```

### 패턴 5: 그룹핑
```java
// Before
Map<String, List<Employee>> byDept = new HashMap<>();
for (Employee e : employees) {
    byDept.computeIfAbsent(e.getDepartment(), k -> new ArrayList<>()).add(e);
}

// After
Map<String, List<Employee>> byDept = employees.stream()
    .collect(Collectors.groupingBy(Employee::getDepartment));
```

## 적용 기준

### 적용 대상
- 컬렉션 순회 + 필터링/변환/집계/검색 패턴
- 중간 변수(`result`, `total`, `found`)에 결과를 누적하는 루프
- 플래그 변수(`boolean found = false`)로 제어하는 루프
- 중첩 루프에서 내부 루프가 독립적 검색/필터인 경우
- `computeIfAbsent` + `add` 패턴의 그룹핑 루프

### 적용 제외
- **부수효과가 핵심인 루프**: DB 저장, 로깅 등 각 요소마다 side effect 수행 (forEach로만 바꾸는 것은 가치 없음)
- **인덱스 기반 접근 필수**: `list.get(i-1)` 비교, 인접 요소 참조 등
- **break/continue 조건이 복잡**: Stream으로 변환하면 오히려 난해
- **성능 크리티컬 루프**: primitive 배열 대량 처리 등 Stream 오버헤드가 문제
- **Java 8 미만 프로젝트**: Stream API 사용 불가
- **단순 forEach 전환**: `for → stream().forEach()`는 가독성 이점 없음

## OUTPUT FORMAT

### 실행 절차

공통 골격(대상 파일 수집 → 후보 제시(계열별 승인 규칙) → 적용 → 테스트 → 커밋/되돌리기, 브랜치·PR이
필요한 조건)은 이 스킬 디렉터리 기준 `../../references/refactoring-procedure.md`가 정본이다.
아래는 이 기법에 고유한 부분만 규정한다.

#### 후보 식별 (공통 절차 2단계)

- 루프 패턴 탐지:
  - `new ArrayList<>()` + for + `add()` → filter/map + toList
  - `int/long sum = 0` + for + `+=` → mapToInt + sum
  - `T acc = 항등원` + for + 재대입 누적 (BigDecimal 등 객체 타입) → map + reduce(항등원, 누적 연산)
  - `T found = null` + for + break → filter + findFirst
  - `boolean flag = false` + for + break → anyMatch/noneMatch
  - `computeIfAbsent` + for → groupingBy
- 각 후보에 대해:
  - 파일명 및 라인 번호
  - 변환 유형 (필터링/집계/검색/존재확인/그룹핑)
  - Before/After 코드 미리보기

#### 후보 제시 예시 (공통 절차 3단계)

```
발견된 후보 3개:

1. OrderService.java:30-36
   유형: 필터링 + 변환
   → orders.stream().filter(...).map(...).toList()

2. ReportService.java:50-55
   유형: 집계 (합계)
   → items.stream().mapToInt(...).sum()

3. UserService.java:20-27
   유형: 검색
   → users.stream().filter(...).findFirst()

→ 승인 없이 적용 (Tidy 계열)
```

#### 리팩토링 적용 (공통 절차 4단계)

- 루프를 해당 Stream Pipeline으로 변환
- 중간 변수/플래그 변수 제거
- 필요시 import 추가 (java.util.stream.Collectors 등)

커밋 메시지: `refactor: replace loop with pipeline in <클래스명>` (공통 절차 6단계)

### 출력 예시
```
완료: Replace Loop with Pipeline

변경 내용:
- OrderService.java:30-36
  필터링+변환: for+if+add → stream().filter().map().toList()

- ReportService.java:50-55
  집계: for+if+= → stream().filter().mapToInt().sum()

테스트: 모든 테스트 통과 (23 tests)
커밋: refactor: replace loop with pipeline in OrderService, ReportService
```

## FAILURE CONDITIONS

공통 실패 조건(계열별 승인 규칙 위반, 테스트 실패 방치, 테스트 수정, 커밋 단위, `git add -A`, heredoc
한글 메시지)은 `../../references/refactoring-procedure.md`에 있다. 아래는 이 기법에 고유한 것만.

- [ ] 부수효과가 핵심인 루프를 단순 forEach로 변환함
- [ ] Stream으로 변환하여 오히려 가독성이 떨어짐
- [ ] 인덱스 기반 접근이 필요한 루프를 변환함

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…