오늘은 팀 프로젝트가 막바지를 향해가는 만큼 더 집중력있는 하루를 보냈던 것 같다. 쏟은 시간과 노력에 비하면 결과가 없는 것 같아서 조금 아쉬운데 그래도 보람찬 하루였다고 생각한다.
여기에는 팀 프로젝트를 진행하면서 해본 것을 조금 정리해보았다.
1. 팀 프로젝트
팀 프로젝트에서 하고 있는 것 중 하나가 사용자는 반드시 유튜브 링크 하나를 게시글에 올려야하고, 우리는 그 유튜브 링크에서 동영상ID에 해당하는 부분만 DB에 저장하기로 정책을 정했다.
정규식을 이용해서 유튜브 링크에서 해당 유튜브 동영상 ID를 추출해내는 부분을 맡게 되어서 그 부분을 진행하게 되었다.
목표는 다음과 같다. 유튜브 링크 이외의 링크는 게시가 불가능하게 하는 것, 숏츠 링크 역시 게시 불가능하게 하는 것이다.(숏츠 링크의 경우도 일반 유튜브 주소처럼 11자리 ID가 있고 그것을 통해서 접속은 가능하다. 다만 shorts라고 링크에 들어있으면 정규식에 의해 걸러진다.)
위의 기능을 구현하기 위해 일단 가능한 유튜브 링크들을 모두 가져온 뒤 해당 유튜브 링크들만 통과되도록 정규 표현식을 작성하면 된다. 또한 그 유튜브 링크에서 동영상 ID만 추출할 수 있어야한다.
아래는 프로젝트에 코드를 직접 적용하기 전에 정규식이 제대로 작성되었는지 실험해 본 코드이다.
fun main() {
val musicUrl = listOf(
// 긴 URL
"https://www.youtube.com/watch?v=4e356mTlXVg",
// 짧은 URL
"https://youtu.be/4e356mTlXVg",
// 임베디드 URL
"https://www.youtube.com/embed/4e356mTlXVg",
// 모바일 URL
"https://m.youtube.com/watch?v=4e356mTlXVg",
// 재생 시점 포함 URL
"https://youtu.be/4e356mTlXVg?t=2",
// 플레이 리스트 포함 URL
"https://www.youtube.com/watch?v=4e356mTlXVg&list=PLUud9rWUXUuWLmZy_ykyuaqrkfTymPjpP",
// 플레이 리스트와 인덱스 포함 URL
"https://www.youtube.com/watch?v=4e356mTlXVg&list=PLUud9rWUXUuWLmZy_ykyuaqrkfTymPjpP&index=3",
// 앞부분 생략 주소
"www.youtube.com/watch?v=4e356mTlXVg",
// 쇼츠 URL (제외)
"https://youtube.com/shorts/4e356mTlXVg",
// 쇼츠 공유 URL (제외)
"https://www.youtube.com/shorts/n2DcpqDK8C0?feature=share",
// 네이버 주소 (제외)
"https://www.naver.com"
)
val regex = Regex("""(?:https?://)?(?:www.|m.)?(?:youtube.com/watch\?v=|youtu.be/|youtube.com/embed/)(?<url>[a-zA-Z0-9_-]{11})""")
// 마지막 코드가 담겨있는 11자리의 그룹에 ?<url>로 네이밍을 해서 그 부분만 가져왔다.
val youtubeId = musicUrl.map{ regex.find(it)?.groups?.get("url")?.value }
println(youtubeId)
// [4e356mTlXVg, 4e356mTlXVg, 4e356mTlXVg, 4e356mTlXVg, 4e356mTlXVg, 4e356mTlXVg, 4e356mTlXVg, 4e356mTlXVg, null, null, null]
}
이렇게 정규식을 작성한 다음에 고민해 봐야할 것은 어느 시점에 이 유효성 검사를 할 것인가 이다.
그런데 위와 같이 정규식을 작성한 이유 중 하나는 유효성 검사 뿐만 아니라 11자리 ID를 얻기 위함이었다. 따라서 서비스 단에서 변환함과 동시에 유효성 검사를 진행하는 것이 좋을 것 같았다. 그 결과 아래와 같은 코드가 작성되었다.
fun createPost(request: CreatePostRequest): PostResponse {
val regex = Regex("""(?:https?://)?(?:www.|m.)?(?:youtube.com/watch\?v=|youtu.be/|youtube.com/embed/)(?<url>[a-zA-Z0-9_-]{11})""")
val youtubeId = regex.find(request.musicUrl)?.groups?.get("url")?.value ?: throw YouTubeLinkNotValidException(request.musicUrl)
val post = Post(
title = request.title,
content = request.content,
musicUrl = youtubeId,
memberId = request.memberId,
musicType = request.musicType,
tags = "#" + request.tags.joinToString("#") + "#"
)
return postRepository.save(post).toResponse()
}
위와 같이 함으로써 원했던 결과를 얻을 수 있었다.
2. 오늘 배운 것
- 여러가지 구현에 도전했다가 실패하기도 했지만 그것 나름대로도 소득이 있는 것 같았다. 공부하고 싶은게 점점 많이 생기는 것 같다.
'오늘 배운 것' 카테고리의 다른 글
24-06-01 Spring 팀 프로젝트 (5) (0) | 2024.06.01 |
---|---|
24-05-31 Spring 팀 프로젝트 (4) (0) | 2024.05.31 |
24-05-29 Spring 팀 프로젝트 (2) (0) | 2024.05.29 |
24-05-28 Spring 팀 프로젝트 (0) | 2024.05.28 |
24-05-27 알고리즘 문제 풀이 (0) | 2024.05.27 |