
2026 월드컵: Android에서 토너먼트 대진표를 보는 가장 좋은 방법을 만들었습니다
요약
Android 환경에서 가변 깊이의 토너먼트 대진표를 효율적으로 렌더링할 수 있는 오픈소스 라이브러리 TournamentBracketLib을 소개합니다. 복잡한 트리 구조와 경기 연결선을 자동으로 처리하며, 팀 이미지와 경기 라벨 기능을 포함합니다.
핵심 포인트
- 가변 깊이 트리 구조와 경기 연결선을 자동으로 처리하는 Android 라이브러리
- CompetitorData, MatchData, ColomnData의 세 가지 모델로 간편한 데이터 구성
- 팀 이미지, 경기 라벨, 애니메이션 등 풍부한 시각적 요소 지원
- 최소한의 코드로 복잡한 대진표 레이아웃 구현 가능
모바일에서 토너먼트 대진표 (Tournament Bracket)를 표시하는 것은 놀라울 정도로 어렵습니다. 가변 깊이의 트리 (Variable-depth trees)를 처리해야 하고, 선으로 경기를 연결해야 하며, 모든 것을 화면 크기에 맞춰 조절하고 스크롤이 가능하게 만들어야 합니다. 저는 적절한 Android 네이티브 솔루션을 찾을 수 없어서 직접 만들었습니다.
**TournamentBracketLib**를 소개합니다 — 구조화된 경기 데이터를 가져와 커넥터 (Connectors), 애니메이션 (Animations), 그리고 이제는 **팀 이미지 (Team images)**와 **경기 라벨 (Match labels)**까지 포함된 전체 토너먼트 대진표를 렌더링하는 가벼운 Android 라이브러리입니다.
어떤 모습인가요?
여기 실제 사례가 있습니다 — 실시간 API 데이터로 완전히 렌더링된 **FIFA World Cup 2026 토너먼트 단계 (Knockout stage)**입니다:
32강의 16개 경기부터 단 하나의 결승전까지 이어집니다. 각 셀 (Cell)에는 팀 국기, 점수 (또는 경기가 치러지지 않은 경우 "-"), 그리고 경기 식별자가 표시됩니다.
핵심 아이디어: 3가지 간단한 모델
API 인터페이스는 의도적으로 최소화되었습니다. 세 가지 객체로 토너먼트를 설명하면 됩니다:
1. CompetitorData — 팀 또는 선수
CompetitorData brazil = new CompetitorData("Brazil", "2");
brazil.setImageUrl("https://flagcdn.com/w80/br.png");
이름, 점수, 그리고 선택 사항인 이미지 URL만 있으면 됩니다. 그게 전부입니다.
2. MatchData — 단일 경기
MatchData match = new MatchData(brazil, argentina);
match.setMatchName("QF - Match 97");
두 명의 경쟁자가 맞붙습니다. 대진표에서 경기를 식별할 수 있도록 라벨을 추가하세요.
3. ColomnData — 라운드 (Round)
ColomnData quarterFinals = new ColomnData(Arrays.asList(qf1, qf2, qf3, qf4));
ColomnData semiFinals = new ColomnData(Arrays.asList(sf1, sf2));
ColomnData finals = new ColomnData(Arrays.asList(finalMatch));
각 컬럼 (Column)은 하나의 라운드를 나타냅니다. 라이브러리는 인접한 컬럼 사이에 커넥터를 자동으로 그립니다.
렌더링하기
bracketsView.setBracketsData(Arrays.asList(quarterFinals, semiFinals, finals));
한 줄이면 충분합니다. 라이브러리가 레이아웃 (Layout), 스크롤링 (Scrolling), 커넥터 라인 (Connector lines), 그리고 애니메이션 (Animations)을 모두 처리합니다.
XML 설정
사용자 정의가 가능한 색상과 함께 레이아웃에 BracketsView를 추가하세요:
<com.ventura.bracketslib.BracketsView
android:id="@+id/bracket_view"
android:layout_width="match_parent"
...
다크 모드 (Dark mode), 라이트 모드 (Light mode), 팀 색상 등 원하는 대로 스타일을 지정할 수 있습니다.
실제 활용 사례: 2026 월드컵 앱
이 라이브러리를 시연하기 위해, 2026 월드컵 라이브 데이터를 가져와 다음과 같이 표시하는 전체 앱을 제작했습니다:
- 토너먼트 대진표 (Knockout brackets) — 32강(R32)부터 결승전까지, 국가 국기와 경기 명칭 포함
- 조별 순위 (Group standings) — MP/W/D/L/GF/GA/GD/PTS 테이블이 포함된 12개 조 전체
- 당겨서 새로고침 (Pull-to-refresh) — 스와이프하여 실시간 순위 새로고침
| 홈 (Home) | 대진표 (Brackets) | 조별 순위 (Group Standings) |
|---|---|---|
![]() | ![]() | ![]() |
대진표 데이터는 공개 API로부터 동적으로 가져옵니다. 경기는 유형(r32, r16, qf, sf, final)별로 그룹화되고 ID 순으로 정렬되어 렌더링됩니다 — 하드코딩된 경기 ID는 전혀 없습니다.
// 동적 대진표 구축 — 어떤 토너먼트 구조에도 적응함
Map<String, List<WorldCupGame>> gamesByType = new HashMap<>();
for (WorldCupGame game : games) {
...
내일 API에서 경기를 추가하거나 삭제하더라도, 앱은 자동으로 이에 적응합니다.
프로젝트에 추가하는 방법
1단계: 리포지토리 (Repositories)에 JitPack을 추가합니다:
allprojects {
repositories {
google()
...
2단계: 의존성 (Dependency)을 추가합니다:
dependencies {
implementation 'com.github.emil-ep:TournamentBracketLib:1.1.4'
}
3단계: XML에 BracketsView를 추가하고, 데이터를 구축한 뒤, setBracketsData()를 호출합니다. 끝입니다.
활용 사례
이 라이브러리는 축구만을 위한 것이 아닙니다. 토너먼트 방식의 경쟁이 있는 곳이라면 어디든 사용할 수 있습니다:
- ⚽ 스포츠 앱 (축구, 농구, 테니스, 크리켓)
- 🎮 e스포츠 (Esports) 토너먼트 트래커
- 🏈 판타지 리그 (Fantasy league) 플레이오프 디스플레이
- 💻 해커톤 (Hackathon) 경쟁 대진표
- 🎯 모든 싱글/더블 엘리미네이션 (single/double elimination) 방식
Tech Stack (데모 앱)
| 라이브러리 (Library) | 용도 (Purpose) |
|---|---|
| TournamentBracketLib | 대진표 렌더링 (Bracket rendering) |
| ... |
What's Next (향후 계획)
- 탭하여 경기 상세 정보 확장 (Tap-to-expand match details)
- 패자 부활전 (Losers bracket, 더블 엘리미네이션) 지원
- Jetpack Compose 버전
⭐ 이 내용이 도움이 되었다면...
별(Star)을 눌러주시면 정말 감사하겠습니다 — 다른 개발자들이 이 프로젝트를 발견하는 데 큰 도움이 됩니다:
👉 Star TournamentBracketLib — 라이브러리
👉 Star TournamentBrackets — 2026 월드컵 데모 앱
Links (링크)
- 📦 TournamentBracketLib — 라이브러리 저장소 (repo)
- 📱 TournamentBrackets — 데모 앱 저장소 (repo)
- 🌐 worldcup26.ir — 공개 API (인증 불필요)
대진표 라이브러리에 어떤 기능이 추가되길 원하시나요? 댓글을 남겨주세요 — 저는 이 프로젝트를 활발히 개발 중이며 여러분의 의견을 환영합니다! 🙌
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기
