9.1 KiB
9.1 KiB
🤝 기여 가이드
Video URL Analyzer 프로젝트에 기여해주셔서 감사합니다!
🚀 시작하기
1. Repository Fork & Clone
git clone https://github.com/your-username/video-url-analyzer.git
cd video-url-analyzer
2. 개발 환경 설정
요구사항
- Java: 17 이상
- Gradle: 7.0 이상
의존성 설치
./gradlew build
🔧 빌드 및 테스트
빌드
./gradlew clean build
테스트 실행
./gradlew test
Fat JAR 생성 (의존성 포함)
./gradlew fatJar
테스트 커버리지 확인
./gradlew test jacocoTestReport
# 결과: build/reports/jacoco/test/html/index.html
🏗️ 프로젝트 구조
video-url-analyzer/
├── src/
│ ├── main/java/com/caliverse/
│ │ ├── analyzer/
│ │ │ ├── VideoAnalyzer.java # 메인 클래스
│ │ │ ├── entity/
│ │ │ │ └── UrlType.java # URL 타입 Enum
│ │ │ ├── model/
│ │ │ │ └── VideoAnalysisResult.java # 결과 모델
│ │ │ ├── platform/ # 플랫폼별 분석기
│ │ │ │ ├── PlatformAnalyzer.java
│ │ │ │ ├── PlatformAnalyzerFactory.java
│ │ │ │ └── impl/
│ │ │ │ ├── HttpBasedPlatformAnalyzer.java # HTTP 기반 추상 클래스
│ │ │ │ ├── NaverTvPlatformAnalyzer.java
│ │ │ │ ├── KakaoTvPlatformAnalyzer.java
│ │ │ │ ├── YouTubePlatformAnalyzer.java
│ │ │ │ ├── VimeoPlatformAnalyzer.java
│ │ │ │ ├── TikTokPlatformAnalyzer.java
│ │ │ │ ├── TwitterPlatformAnalyzer.java
│ │ │ │ ├── WeiboPlatformAnalyzer.java
│ │ │ │ └── DirectUrlPlatformAnalyzer.java
│ │ │ └── service/
│ │ │ └── VideoAnalyzerService.java # 비디오 분석 로직
│ │ └── global/
│ │ ├── common/
│ │ │ ├── CommonConstants.java # 상수 (도메인, API URL, 정규식)
│ │ │ └── Messages.java # 메시지 관리
│ │ └── util/ # 유틸리티
│ │ ├── HttpUtils.java # HTTP 요청 유틸
│ │ └── UrlParser.java # URL 파싱 유틸
│ └── test/java/com/caliverse/analyzer/ # 테스트 코드
│ └── VideoAnalyzerTest.java
├── build.gradle # 빌드 설정
├── README.md # 사용자 문서
└── CONTRIBUTING.md # 이 파일
주요 컴포넌트
1. VideoAnalyzer (메인 API)
- 비디오 URL 분석의 진입점
- 플랫폼별 분석기 또는 일반 비디오 분석 선택
2. PlatformAnalyzer 인터페이스
- 플랫폼별 특화 로직 구현을 위한 인터페이스
- 새로운 플랫폼 추가 시 이 인터페이스를 구현하거나 HttpBasedPlatformAnalyzer 상속
3. HttpBasedPlatformAnalyzer (추상 클래스)
- HTTP 요청 기반 플랫폼 분석기의 공통 로직
- oEmbed API 호출 및 응답 처리
- 각 플랫폼은
parseResponse()메서드만 구현
4. VideoAnalyzerService
- 일반 비디오 URL 분석 로직
- 보호 검사, 3D 검사, AVPlayer 재생 가능 여부 검사
5. CommonConstants & Messages
CommonConstants: 도메인, API URL, 정규식 패턴 등Messages: 모든 메시지 문자열 (국제화 준비)
🧪 테스트 예제
기본 테스트 구조
import org.junit.Test;
import static org.junit.Assert.*;
public class VideoAnalyzerTest {
@Test
public void testNaverTvUrl() {
VideoAnalyzer analyzer = new VideoAnalyzer();
VideoAnalysisResult result = analyzer.analyzeUrl("https://tv.naver.com/v/84373511");
assertNotNull(result);
assertNotNull(result.isSuccess());
assertNotNull(result.getReason());
}
@Test
public void testDrmProtectedUrl() {
VideoAnalyzer analyzer = new VideoAnalyzer();
String drmUrl = "https://example.com/video.m3u8?drm=widevine";
VideoAnalysisResult result = analyzer.analyzeUrl(drmUrl);
assertFalse(result.isSuccess());
assertTrue(result.getReason().contains("DRM"));
}
}
🌟 새로운 플랫폼 추가하기
방법 1: HttpBasedPlatformAnalyzer 상속 (권장 - oEmbed 지원 플랫폼)
public class InstagramPlatformAnalyzer extends HttpBasedPlatformAnalyzer {
private static final String PLATFORM_NAME = "Instagram";
private static final String PLATFORM_DOMAIN = "instagram.com";
private static final String API_ENDPOINT = "https://api.instagram.com/oembed";
private final ObjectMapper objectMapper;
public InstagramPlatformAnalyzer() {
this.objectMapper = new ObjectMapper();
}
@Override
protected String getApiEndpoint() {
return API_ENDPOINT;
}
@Override
protected String getPlatformDomain() {
return PLATFORM_DOMAIN;
}
@Override
public String getPlatformName() {
return PLATFORM_NAME;
}
@Override
public boolean canHandle(String url) {
if (url == null) return false;
return url.toLowerCase().contains(PLATFORM_DOMAIN);
}
@Override
protected VideoAnalysisResult parseResponse(String response, String originalUrl) throws IOException {
try {
JsonNode rootNode = objectMapper.readTree(response);
// 필수 필드 추출
String type = getStringValue(rootNode, "type");
String title = getStringValue(rootNode, "title");
if (type == null || title == null) {
return VideoAnalysisResult.failure("Instagram oEmbed 응답이 유효하지 않습니다");
}
logger.debug("Instagram 검증 성공: {}", title);
return VideoAnalysisResult.success();
} catch (Exception e) {
throw new IOException("Instagram 응답 파싱 실패: " + e.getMessage(), e);
}
}
}
방법 2: PlatformAnalyzer 직접 구현 (HTML 파싱이 필요한 경우)
public class CustomPlatformAnalyzer implements PlatformAnalyzer {
@Override
public String getPlatformName() {
return "CustomPlatform";
}
@Override
public boolean canHandle(String url) {
return url != null && url.contains("custom.com");
}
@Override
public VideoAnalysisResult analyze(String url) {
try {
// 커스텀 분석 로직 (HTML 파싱 등)
String htmlContent = fetchHtmlContent(url);
String videoUrl = extractVideoUrl(htmlContent);
if (videoUrl != null) {
return VideoAnalysisResult.success();
} else {
return VideoAnalysisResult.failure("비디오 URL을 찾을 수 없습니다");
}
} catch (Exception e) {
return VideoAnalysisResult.failure("분석 실패: " + e.getMessage());
}
}
private String fetchHtmlContent(String url) throws IOException {
// HTTP 요청 구현
}
private String extractVideoUrl(String html) {
// HTML 파싱 구현
}
}
3. Factory에 등록
public class PlatformAnalyzerFactory {
public PlatformAnalyzerFactory() {
this.analyzers = new ArrayList<>();
// HTTP 기반 플랫폼 분석기들을 등록
analyzers.add(new NaverTvPlatformAnalyzer());
analyzers.add(new KakaoTvPlatformAnalyzer());
analyzers.add(new YouTubePlatformAnalyzer());
analyzers.add(new VimeoPlatformAnalyzer());
analyzers.add(new TikTokPlatformAnalyzer());
analyzers.add(new TwitterPlatformAnalyzer());
analyzers.add(new WeiboPlatformAnalyzer());
// 새로운 분석기 추가
analyzers.add(new InstagramPlatformAnalyzer());
// 직접 URL 분석기는 가장 마지막에 등록 (fallback)
analyzers.add(new DirectUrlPlatformAnalyzer());
}
}
4. 테스트 작성
@Test
public void testInstagramUrl() {
VideoAnalyzer analyzer = new VideoAnalyzer();
VideoAnalysisResult result = analyzer.analyzeUrl("https://www.instagram.com/p/ABC123/");
assertNotNull("결과가 null이 아니어야 합니다", result);
assertTrue("Instagram URL은 재생 가능해야 합니다", result.isSuccess());
System.out.println("Instagram: " + result);
}
5. 실제 예제: 웨이보 플랫폼
웨이보는 oEmbed를 지원하지 않아 HTML 파싱 방식으로 구현되었습니다.
자세한 구현은 WeiboPlatformAnalyzer.java를 참고하세요.
주요 특징:
- HTML에서
og:video,og:title,og:image메타태그 추출 $render_data스크립트에서 JSON 데이터 파싱- 여러 URL 패턴 지원 (tv/show, video/show, m.weibo.cn)
다시 한번 기여해주셔서 감사드립니다! 🎉