Merged
Conversation
- `DiscoveryService`와 `Reflector`를 활용하여 `CommandHandler`, `ButtonHandler`, `EventListener` 자동 탐색 및 등록 방식 적용 - `@Command`, `@Button`, `@EventListener` 데코레이터 생성하여 메타데이터 기반 자동 등록 가능하도록 개선 - `discord` 및 `discord-event` 폴더를 통합하여 구조 단순화 - 불필요한 메서드 및 중복 코드 정리
- `@CatchError` 데코레이터가 기존 메서드의 메타데이터를 보존하도록 `reflect-metadata` 활용 - `Reflect.getMetadataKeys()`를 사용하여 기존 메서드의 메타데이터를 복사 후 적용
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🔗 관련 이슈
resolves #5
📝 작업 내용
CommandHandler,ButtonHandler,EventListener자동 탐색 및 등록 방식 적용(@Cron은 내부적으로 reflect-metadata를 사용하기 때문)
🍇 고민한 부분
1. 기존 구조의 문제점
핸들러 등록 방식의 일관성 부족
기존에는 명령어와 버튼을 추가할 때,
ButtonHandler와CommandHandler를 직접 수정해야 했습니다.핸들러를 등록하는 방식으로
fs.readdirSync를 활용해 특정 경로(const commandsPath = path.join(__dirname, '..', 'slash/implementations');)에서 파일을 읽어 명령어를 동적으로 로드하는 방식은 폴더 구조를 리팩토링할 경우, 해당 경로가 변경되면 핸들러가 정상적으로 등록되지 않아 계속 수정해줘야 해서 유지보수가 어렵다는 문제가 있었습니다.구조 개선을 위한 여러 접근 방식 검토
💫 선택: Discovery 기반 자동 등록
DiscoveryService를 활용하여 명령어, 버튼, 이벤트 리스너를 자동으로 탐색하고 등록하도록 변경했습니다.이제 클래스에
@Command,@Button,@EventListener등의 데코레이터를 추가하여 메타데이터 기반 자동 등록 가능하도록 개선하였습니다. 이를 통해 새로운 명령어 추가 시 변경사항의 영향범위를 줄였습니다.Function Composition + Decorator Hybrid
이 방식은 특정 시간대에만 문제 풀이 가능하도록 제한하거나, 사용자별 문제 풀이 횟수를 제한하는 등의 요구사항이 생겼을 때,
기존 코드 수정 없이 미들웨어를 추가하는 것만으로 기능을 확장할 수 있다는 장점이 있었습니다.
FP 패러다임에 대한 이해가 부족한 상황에서 이를 도입할 경우 디버깅이 어려울 것 같아 개발 속도가 느려질 것 같아 반려했습니다.
Factory 패턴 기반 등록
DI 컨테이너를 거치지 않고 독립적인 Factory를 사용하면 테스트가 용이하지만, NestJS의 의존성 주입을 활용할 수 없다는 단점이 있습니다.
EventEmitter
명령어 실행 컨텍스트를 유지하는 것이 어려워 명령어 실행 중 특정 데이터를 유지해야 하는 경우 쉽게 전달하기 어렵다는 단점이 있습니다.
Dynamic Module + Factory Provider
Dynamic Module을 활용하면 런타임에 새로운 명령어 타입을 등록하고 DI 컨테이너를 사용할 수 있지만, 모듈 초기화 후 providers 배열이 고정되어 명령어 추가 시 전체 모듈을 재초기화해야 하며, 인스턴스 생성 방식으로 인해 성능 저하 및 메모리 관리의 어려움이 있어 선택하지 않았습니다.
NestJS RouterModule
NestJS의
RouterModule은 HTTP 요청 라우팅에 최적화된 방식으로, Discord 봇의 이벤트 기반 구조와 맞지 않아 제외했습니다.