Revit API FilteredElementCollector로 요소 일괄 조회하고 트랜잭션으로 고치기

한 화면엔 3D 건물 와이어프레임, 다른 화면엔 코드가 떠 있는 개발 환경

Revit API로 무언가를 하려면 거의 항상 첫 단계가 같다. 모델에서 원하는 요소를 골라내는 것이다. 벽만, 특정 레벨의 문만, 배치된 인스턴스만. 이 조회를 담당하는 클래스가 FilteredElementCollector다. 그리고 골라낸 요소의 값을 바꾸려면 반드시 Transaction 안에서 해야 한다. 이 두 가지, “필터로 모으고 트랜잭션으로 고친다”는 패턴은 Revit 플러그인 코드의 8할을 차지한다. 이 글은 컬렉터의 필터 종류와 성능 차이, 그리고 트랜잭션의 시작·커밋·롤백을 실제 C# 코드와 함께 정리한다.

■ FilteredElementCollector의 기본형

컬렉터는 생성자에 Document를 넘기고 필터 메서드를 체인으로 이어 붙이는 방식으로 쓴다. 마지막에 ToElements()ToElementIds()로 결과를 뽑는다.

// 배치된 벽 인스턴스만 모으기
var walls = new FilteredElementCollector(doc)
    .OfCategory(BuiltInCategory.OST_Walls)   // 카테고리: 벽
    .WhereElementIsNotElementType()          // 타입 제외, 인스턴스만
    .ToElements();

WhereElementIsNotElementType()를 빼면 벽 타입(WallType)까지 딸려 나온다. 인스턴스만 필요하면 반드시 붙이고, 타입 정의만 모을 때는 WhereElementIsElementType()를 쓴다. 런타임 클래스 기준으로 걸러야 하면 OfClass(typeof(Wall))을 붙인다.

■ 필터의 종류: 빠른 필터와 느린 필터

Revit의 요소 필터는 크게 세 갈래다. 성능을 좌우하는 것은 Quick(빠른) 필터냐 Slow(느린) 필터냐의 구분이다. 빠른 필터는 요소의 헤더 정보만 읽어 통과 여부를 판단하므로 요소를 메모리로 완전히 펼치지 않아도 된다. 느린 필터는 각 요소를 메모리에 전개해야 판단할 수 있어 비용이 크다.

분류 대표 필터/메서드 특징
빠른(Quick) OfCategory / OfCategoryId 카테고리로 거름, 헤더만 읽음
빠른(Quick) OfClass 런타임 클래스로 거름
빠른(Quick) WhereElementIsNotElementType / IsElementType 인스턴스/타입 구분
느린(Slow) ElementParameterFilter 파라미터 값 조건, 요소 전개 필요
느린(Slow) ElementLevelFilter, 기하 기반 필터 레벨·교차 등, 비용 큼
논리 LogicalAndFilter / LogicalOrFilter 필터 조합

원칙은 하나다. 빠른 필터로 최대한 범위를 좁힌 뒤에 느린 필터나 LINQ를 적용한다. OfCategory 같은 단축 메서드는 모두 빠른 필터에 대응하므로, 이것부터 걸어 후보 집합을 줄이면 느린 조건이 훑을 요소 수가 확 준다. 처음부터 LINQ의 Where()로 전체를 훑는 코드는 대형 모델에서 눈에 띄게 느려진다.

벽·바닥·기둥이 분리된 3D 건물 모델 분해도

■ 성능을 살리는 조회 예시

“1층에 있는, 높이가 3000mm를 넘는 벽”을 찾는다고 하자. 빠른 필터로 벽 인스턴스를 먼저 좁히고, 값 조건은 그 뒤에 건다.

// 빠른 필터로 벽 인스턴스만 확보 (여기서 대부분 걸러진다)
var collector = new FilteredElementCollector(doc)
    .OfCategory(BuiltInCategory.OST_Walls)
    .WhereElementIsNotElementType();

// 값 조건(느림)은 좁혀진 집합에만 적용
double limitFt = UnitUtils.ConvertToInternalUnits(3000, UnitTypeId.Millimeters);
var tallWalls = collector
    .Where(w => {
        var p = w.get_Parameter(BuiltInParameter.WALL_USER_HEIGHT_PARAM);
        return p != null && p.AsDouble() > limitFt;
    })
    .ToList();

주의할 점: 하나의 컬렉터 인스턴스는 결과를 한 번 소비하면 재사용이 어렵다. 같은 조건을 여러 번 쓸 거라면 ToElements()로 리스트를 뽑아 두고 그 리스트를 재사용한다. 또 Revit 내부 길이 단위는 피트이므로 mm 값을 비교할 때는 위처럼 UnitUtils로 환산해야 값이 어긋나지 않는다.

■ Transaction: 시작·커밋·롤백

모델을 바꾸는 모든 수정은 트랜잭션 안이어야 한다. 밖에서 값을 바꾸려 하면 예외로 막힌다. 트랜잭션은 Start()로 열고 Commit()으로 확정하며, 문제가 생기면 RollBack()으로 통째로 되돌린다. 사용자 입장에선 이 한 덩어리가 실행 취소(Undo) 한 단계로 묶인다.

using (Transaction t = new Transaction(doc, "벽 주석 일괄 입력"))
{
    t.Start();
    try
    {
        foreach (Element w in tallWalls)
        {
            Parameter cmt = w.LookupParameter("Comments");
            if (cmt != null && !cmt.IsReadOnly)
                cmt.Set("검토완료");
        }
        t.Commit();   // 정상 종료 → 하나의 Undo 단위로 확정
    }
    catch (Exception ex)
    {
        if (t.HasStarted() && !t.HasEnded())
            t.RollBack();   // 예외 시 전부 되돌림
        throw;
    }
}

using으로 감싸면 커밋이나 롤백을 빠뜨려도 트랜잭션이 안전하게 정리된다. 여러 트랜잭션을 묶어 한 번에 되돌리고 싶으면 TransactionGroup을, 반복 안에서 성능이 급할 때는 재생성 억제 옵션을 검토한다.

■ 파라미터 수정 시 자주 나는 실수

증상 원인 대응
Set 호출에서 예외 트랜잭션 밖에서 수정 Start~Commit 안으로 이동
LookupParameter가 null 이름 오타 또는 미바인딩 매개변수 존재·바인딩 여부 확인 후 접근
IsReadOnly 매개변수에 Set 계산식/시스템 매개변수 IsReadOnly 검사 후 건너뜀
길이 값이 이상함 피트↔mm 단위 미환산 UnitUtils로 내부 단위 변환

여러 모니터로 대형 3D 건물 모델을 검토하는 엔지니어

■ 눈여겨볼 것

같은 이름의 매개변수가 여러 개라도 LookupParameter는 그중 하나만 돌려준다. 결과가 예측과 다르면 GetParameters(name)로 목록을 확인하는 편이 안전하다. 성능 면에서 가장 큰 실수는 반복문 안에서 컬렉터를 새로 만드는 것이다. 조회는 반복 밖에서 한 번만 하고, 결과 리스트를 돌려야 한다. 이 “빠른 필터 → 값 조건 → 트랜잭션 수정” 패턴은 Revit 2026 API에서도 동일하며, pyRevit이나 Dynamo의 파이썬 노드에서도 문법만 파이썬으로 바뀔 뿐 구조는 그대로 쓴다.

■ 이런 분께 도움이 됩니다

  • Revit 플러그인을 처음 짜는 개발자 — 컬렉터와 트랜잭션은 거의 모든 스크립트의 뼈대다
  • 대형 모델에서 스크립트가 느린 실무자 — 필터 순서만 바꿔도 체감 속도가 달라진다
  • Dynamo·pyRevit 사용자 — 같은 개념을 파이썬으로 그대로 옮길 수 있다

■ 참고

BuiltInCategory·BuiltInParameter 열거형 이름과 단위 식별자(UnitTypeId 등)는 Revit 버전에 따라 달라질 수 있으므로, 배포 전 대상 버전의 API 문서에서 확인한다. 대량 수정 스크립트는 반드시 사본 모델에서 먼저 돌려 결과를 검증한 뒤 실제 프로젝트에 적용한다.


공식 참고 자료 및 적용 범위

이 글은 Revit API의 요소 조회와 트랜잭션 사용 원칙을 설명합니다. 필터 결과·수정 가능성·예외 처리는 Revit API 버전, 문서·요소 상태와 실행 컨텍스트에 따라 달라질 수 있습니다.

아래 자료는 확인일 기준의 제조사·표준기구 또는 공공기관 공식 문서입니다. 제품 기능·표준·정책은 개정될 수 있으므로 실제 프로젝트 적용 전에는 사용 중인 버전의 최신 원문과 프로젝트 기준을 확인하세요.

확인일: 2026-08-15