모든 글

Reader, Finder, Searcher를 행위로 구분하는 법

Reader, Finder, Searcher를 조회 건수가 아니라 직접 읽기, 추가 필터링, 복합 검색이라는 행위로 구분하는 기준을 설명한다.

출처 및 AI 안내: 이 글은 제미니의 개발실무 유튜브를 기반으로 작성되었습니다. gpt-5.6-sol 모델을 사용해 생성·편집했습니다.

Reader, Finder, Searcher는 구현 계층에서 비슷한 일을 하는 컴포넌트 이름처럼 보일 수 있다. 그래서 “Reader는 단건을 반환하고 Finder는 여러 건을 반환한다”처럼 단순한 규칙으로 구분하기 쉽다. 내가 사용하는 기준은 조회 결과의 개수가 아니다. 건수만으로는 코드가 실제로 어떤 일을 하는지 알기 어렵다.

나는 클래스가 드러내는 행위에 따라 세 이름을 고른다. 이미 있는 데이터를 곧바로 읽는가? 데이터를 가져온 뒤 조건을 더 적용해 필요한 결과를 찾는가? 여러 데이터 소스와 필터를 조합해 검색에 가까운 작업을 하는가? 클래스 내부를 열기 전에도 이름을 통해 이 차이를 예상할 수 있어야 한다.

Reader: 있는 데이터를 직접 읽는다

행위가 단순한 조회에 가깝다면 Reader를 사용한다. 예를 들어 UserReaderUserRepository에만 의존하고, 별도의 필터링이나 가공 책임 없이 리포지토리를 통해 데이터를 가져오는 경우다.

중요한 것은 결과가 사용자 한 명인지 목록인지가 아니라 행위가 얼마나 직접적인지다. 클래스를 본 사람이 “사용자 데이터를 읽는 역할”이라고 이해해도 실제 코드와 어긋나지 않아야 한다.

따라서 Reader는 가장 단순한 경우에 잘 맞는다. 리포지토리에 조회 메서드가 여러 개 있다는 이유만으로 더 거창한 이름을 붙일 필요는 없다. 컴포넌트가 여전히 존재하는 데이터로 가는 명확한 통로라면 Reader라는 이름으로 충분하다.

Finder: 조회에 찾기 조건이 더해진다

조회가 작업의 전부가 아니라면 Finder를 고려한다. UserFinderUserRepository를 사용하면서 validator, filter 또는 다른 보조 코드와 협력하는 경우를 생각할 수 있다. 데이터를 가져온 뒤 호출자가 원하는 대상을 찾기 위해 범위를 좁히거나 가공한다.

이 추가 행위 때문에 클래스가 주는 인상도 달라진다. 이미 있는 데이터를 그대로 읽어 주는 데서 끝나지 않고, 어떤 조건에 맞는 결과를 찾는다. 둘 사이에 기계적으로 적용할 수 있는 경계가 있는 것은 아니지만, Finder라는 이름은 조회한 데이터 주위에 선택이나 가공이 있다는 점을 알려 준다.

단건 조회와 다건 조회가 약한 명명 기준인 이유도 여기에 있다. 어느 쪽이든 직접 읽기로 구현할 수 있고, 어느 쪽이든 추가 필터링이 필요할 수 있다. 결과 개수보다 행위가 더 유용한 구분 기준이다.

Searcher: 여러 요소를 조합해 검색한다

Searcher는 여러 리포지토리나 데이터 종류를 합치고, 여러 필터를 적용해 결과를 만드는 복합적인 검색에 어울린다. 예를 들어 사용자와 그룹을 함께 검색한다면 각각의 리포지토리와 사용자-그룹 필터를 조합해 답을 만들 수 있다.

세 이름이 주는 행위의 인상은 다음처럼 정리할 수 있다.

이름 행위가 주는 인상
Reader 있는 데이터를 직접 읽는다
Finder 데이터를 가져와 필터링하거나 가공해 결과를 찾는다
Searcher 여러 데이터 소스와 조건을 조합해 더 복잡한 검색을 수행한다

이는 뉘앙스의 차이지 공식적인 계층 구조가 아니다. 코드베이스마다 경계를 다르게 그을 수 있으며, 모든 작업에 세 종류의 컴포넌트가 전부 필요한 것도 아니다.

컴포넌트는 서로 조합할 수 있다

이 이름들이 모든 클래스의 리포지토리 직접 접근을 요구하는 것은 아니다. UserFinder를 여러 Reader로 구성할 수 있다. 예를 들어 협력 객체 중 하나로 GroupReader를 사용할 수 있다. 바깥 컴포넌트가 여러 읽기 행위를 조율해 결과를 찾는다면 그 컴포넌트의 행위는 여전히 Finder다.

이 조합은 의존성 개수로 이름을 정하면 안 되는 이유도 보여 준다. 리포지토리, Reader, filter, validator는 구현에 쓰이는 재료다. 클래스 이름은 그 재료를 조합해 만든 행위를 설명한다.

이 이름을 올바르게 만드는 보편적인 명세는 없다. 나는 만들고 있는 소프트웨어의 상황과 코드가 주는 느낌을 기준으로 이름을 고른다. 다른 팀은 다른 단어나 경계를 선택할 수 있다. 중요한 것은 자신의 코드에서 각 이름이 무엇을 뜻하는지 정하고 일관되게 적용하는 일이다. 이름이 읽기, 찾기, 검색이라는 행위를 반영하면 클래스 안에 무엇이 있는지 알려 주는 짧은 안내가 된다.