자신만의 음악 플레이리스트를 만들고 공유하기 위한 서비스
- 자신만의 음악 플레이리스트를 생성하여 음악을 추가, 삭제 가능
![]() |
![]() |
- 음악 플레이리스트를 저장하여 공유 가능
## 혁오 노래 모음 🎵
- 🎵 [혁오 - Gang Gang Schiele](https://www.youtube.com/watch?v=Xjk3w7NcZAU) ▶️
- 🎵 [혁오 - 멋진헛간 Remix](https://www.youtube.com/watch?v=3DpL4UcCdWk) ▶️
- Spring Boot 3.3.4 / Kotlin
- zulu JDK 17
- Spring Data JPA
- MySQL
- Kotlin JDSL
GET /v1/members - 회원 조회
Request
{}Response
{
"userReponse" : [
{
"id" : 1,
"email" : "ppusda@naver.com"
},
{
"id" : 2,
"email" : "ppusda1234@gmail.com"
},
]
}POST /v1/members - 로그인
Request
{
"email": "string",
"password": "string"
}Response
{
"id": 1,
"email": "ppusda@naver.com"
}GET /v1/musics - 음악 조회
Request
{}Response
{
"musicResponse" : [
{
"id" : 1,
"title" : "Gang Gang Schiele",
"artist" : "혁오",
"url" : "https://www.youtube.com/watch?v=WB4547-tSJA",
},
{
"id" : 2,
"title" : "멋진헛간 Remix",
"artist" : "혁오",
"url" : "https://www.youtube.com/watch?v=3DpL4UcCdWk"
}
]
}GET /v2/musics - 음악 검색
Request
/v2/musics?keyword="혁오"
Response
{
"musicResponse" : [
{
"id" : 1,
"title" : "Gang Gang Schiele",
"artist" : "혁오",
"url" : "https://www.youtube.com/watch?v=WB4547-tSJA",
},
{
"id" : 2,
"title" : "멋진헛간 Remix",
"artist" : "혁오",
"url" : "https://www.youtube.com/watch?v=3DpL4UcCdWk"
}
]
}POST /v1/musics - 음악 등록
Request
{
"title" : "Gang Gang Schiele",
"artist" : "혁오",
"url" : "https://www.youtube.com/watch?v=WB4547-tSJA",
}Response
{
"id" : 1,
"title" : "Gang Gang Schiele",
"artist" : "혁오",
"url" : "https://www.youtube.com/watch?v=WB4547-tSJA",
}PUT /v1/musics/{n} - n번 음악 정보 수정
Request
{
"title" : "멋진헛간 Remix",
"artist" : "혁오",
"url" : "https://www.youtube.com/watch?v=3DpL4UcCdWk"
}Response
{}DELETE /v1/musics/{n} - n번 음악 삭제
Request
{}Response
{}GET /v1/playlists - 플레이리스트 조회
Request
{}Response
{
"playlistResponse" : [
{
"id" : 1,
"ownerEmail" : "ppusda@naver.com",
"name" : "내가 자주 듣는 혁오 노래 모음집"
},
{
"id" : 2,
"ownerEmail" : "ppusda1234@gmail.com",
"name" : "혁오"
}
]
}POST /v1/playlists - 플레이리스트 생성
Request
{
"name" : "내가 자주 듣는 혁오 노래 모음집"
}Response
{
"id" : 1
}PATCH /v1/playlists/{n} - n번 플레이리스트 정보 수정
Request
{
"name" : "혁오"
}Response
{}DELETE /v1/playlists/{n} - n번 플레이리스트 삭제
Request
{}Response
{}GET /v1/playlists/{n}/musics - n번 플레이리스트 조회
Request
{
"playlistMusicResponse" : {
"id" : 1,
"ownerEmail" : "ppusda@naver.com",
"musics" : [
{
"id" : 1,
"title" : "Gang Gang Schiele",
"artist" : "혁오",
"url" : "https://www.youtube.com/watch?v=WB4547-tSJA",
},
{
"id" : 2,
"title" : "멋진헛간 Remix",
"artist" : "혁오",
"url" : "https://www.youtube.com/watch?v=3DpL4UcCdWk"
}
]
}
}Response
{}POST /v1/playlists/{n}/musics - n번 플레이리스트에 음악 추가
Request
{}Response
{}DELETE /v1/playlists/{n}/musics - n번 플레이리스트에 음악 삭제
Request
{}Response
{}[미션 1] 테이블 설계하기 제출 스레드
커밋 내용 => Update README.md
[미션 2] 깃허브 리포지토리에 프로젝트 올리기
커밋 내용 => init: initialize project
[미션 3] REST API 설계하기
커밋 내용 => docs: API 설계 - 요청/응답 전체 추가
[미션 4] 조회 REST API 만들기
커밋 내용 => feat: 조회 API 테스트 코드 작성
Restful 하도록 API 수정하기
커밋 내용 => refactor: Api 수정 (자원 복수형, 버저닝), refactor: Api 수정 (PUT, PATCH)
위 내용은 이전부터 고민하고 사용했다고 생각했지만 코치님께 관련 피드백을 받게 되었다. 그렇게 자료를 좀 더 찾아보게 되었고 아래와 같은 고민과 생각을 마주치게 되었다.
수정이라는 작업을 할 때 PUT을 더 사용하는 이유가 있을까요?
그래서 PUT 이랑 PATCH 는 뭐가 다른건가요
부끄럽게도 나는 단순히 "PUT은 자원의 전체 교체", "PATCH는 자원의 일부 교체" 정도의 개념만 알고 있었기에 문제였던 것을 알게되었다.
아래와 같은 내용을 알아두려고 한다.
- 언급되는 자원은 Entity의 컬럼들과 동일 시 되지 않는다. / DTO에 명시 한 목록이 자원이 되며, 이 자원들을 모두 교체 하느냐 마느냐가 PUT, PATCH로 갈리게 된다.
- PUT은 자원의 전체 교체, 입력 받은 모든 데이터가 그대로 반영되어야 한다.
- PATCH는 자원의 일부 교체, 입력 받은 데이터 중 null이 있더라도 이전 데이터를 유지하며, 입력된 데이터만 반영한다.
- REST한 API를 항상 지키기는 힘들다. 하지만 차이를 알고 정해놓은 컨벤션에 맞춰서만 작성한다면 크게 문제되지는 않는다.
위와 같은 내용들을 생각하고 코드를 수정했으며, Music의 경우는 PUT으로 변경, Playlist의 경우는 PATCH로 동작 할 수 있도록 코드를 수정하였다.
읽기 좋은 코드로 수정하기 (주석, 메서드 네이밍 수정, 퍼사드 패턴 적용)
커밋 내용 =>
이번 자체미션에서는 한 번에 이해되지 않는 메서드 네이밍을 수정하거나 구현했던 기능들에 대해 모두 주석을 달아보게 되었다. 처음 작성할 때는 이상한 점을 느끼지 못했는데 다시 보니 이상하다고 느껴지는 메서드 네임들도 있었고, 주석을 달다 보니 누구나 이런 부분에서 벗어나더라도 더 쉽게 이해할 수 있을 것 같다고 생각하게 되었다.
물론 어려운 작업은 아니었지만 생각을 요하는 작업이었던 것 같다.
추가로 퍼사드 패턴을 적용해서 Music, Playlist 간에 발생하는 간단한 DB 로직들을 합쳐서 관리할 수 있게 하였다. 혼자서 직접 적용해보는 건 처음이었지만 어렵지는 않았고, 수정한 코드를 보니 확실히 더 깔끔해졌다고 느꼈다.
복잡한 구조라면 이러한 패턴을 적용해보는 것을 고민해봐야겠다고 생각되었고, 다른 디자인 패턴들도 적용해볼 수 있는지 좀 더 알아봐야겠다.
테스트 커버리지 100% 달성하기(단위 테스트 위주로 작성)
커밋 내용 =>
꽤 오랜시간을 투자해서 JaCoCo 테스트 커버리지 100%를 달성하게 되었다.
총 84개의 테스트와 24개의 파일을 만들었으며 코치님께서 말씀하셨던 커버리지 100%를 달성해보면 배우는 것이 있을 것이라는 말에 공감하게 되었다.
먼저 테스트 코드가 필요한 Controller, Service, Repository에 대해 테스트 작성 흐름을 알게 되었다.
이 부분이 솔직히 정말 의미있다고 생각하며, 앞으로 어렵게만 느껴졌던 테스트 코드 작성에 대한 부담감을 덜 수 있을것 같다.
두번째로는 여러 분기에 대한 처리의 중요성을 알게 되었다.
테스트 커버리지 100%를 목표로 채워나가다 보니 사용한 적 없는 조건문이나 고려해야하는 예외 상황들을 많이 보게 되었다.
이런 부분에 대한 작성을 실제로 하다 보니 예상치 못한 부분에서 발생할 수 있는 상황을 좀 더 생각해 볼 수 있었고, 불필요한 코드들을 처리할 수 있었던 것 같다.
마지막으로 테스트 코드의 중요성을 다시 한 번 깨닫게 되었다.
테스트 코드를 작성해보면서 실제로 잘못 구현한 부분도 발견했으며, 위에서 언급했던 것 처럼 불필요한 부분이나 어색한 부분들을 고칠 수 있었다.
이러한 자잘한 실수들이 실무에서는 큰 영향을 미칠 수 있으니 테스트 코드가 얼마나 중요한 지 알 수 있었던 것 같다.
일주일이 넘는 시간동안 테스트 코드를 작성해보면서 여러 생각들이 들었다.
작은 프로젝트임에도 불구하고 작성해야 할 테스트는 많았고 관련 지식도 부족했기에 생각보다 힘들었고 시간이 꽤나 소요되었다.
그래도 매일 새벽까지 테스트를 작성하며 테스트 커버리지를 올려나가는 순간들은 재밌었고 무엇보다 의미있는 작업이라는 것을 많이 느끼게 되었다.
코치님께서 추천해주셨던 영상에서도 나왔던 것 처럼 테스트 커버리지 100%를 달성한 순간에 "아 이렇게 해도 모든 상황을 검증할 수는 없겠구나" 라는 생각이 들었고 그렇기에 테스트 커버리지 100% 달성은 좋은 경험이었고 앞으로도 최대한 버그가 없도록 좋은 테스트 코드를 열심히 작성하며 개발을 해나가야겠다고 다짐하게되었다.
간단한 UI 추가하기
커밋 내용 =>
크게 어려운 작업은 아니었지만 기존 기능에 대한 화면만 구현할지 새 기능들을 추가해서 구현할지에 대해서 고민이 조금 되었다.
결과적으로는 구현하기로 마음을 먹었으며 UI 자체는 더 추가할 부분이 없을 것 같아 일단락하려고 한다.
향후 추가할 기능은 아래와 같다.
- 음악 검색 (Kotlin JDSL)
- Github 로그인
- 재생목록 템플릿 제공
새로운 프로젝트를 진행하게 되어서 당장은 힘들겠지만 차근차근 해나가보려고한다.
본 프로젝트는 인프런 워밍업 클럽 스터디 2기 - 백엔드 프로젝트 (Kotlin, Spring Boot) 의 서브 미션을 위한 프로젝트입니다.
🎯 미션 수행 사항
- [미션 1] 테이블 설계하기(~10/4 금)
- [미션 2] 깃허브 리포지토리에 프로젝트 올리기(~10/4 금)
- [미션 3] REST API 설계하기(~10/8 화)
- [미션 4] 조회 REST API 만들기(~10/15 화)
- [미션 5] 삽입, 수정, 삭제 REST API 만들기(~10/21 월)
- [자체 미션] 이후 고도화 (~ 01/12 일)
📑 고도화 계획
코드 리뷰 => 코드 리뷰 코드 리뷰 해주신 내용을 고려하여 코드를 수정하고, 고도화를 진행해보았습니다.
- Restful 하도록 API 수정하기 (10/30 수)
- 읽기 좋은 코드로 수정하기 (주석, 메서드 네이밍 수정, 퍼사드 패턴 적용) (10/31 목 ~ 11/01 금)
- 테스트 커버리지 100% 달성하기 (단위 테스트 위주로 작성) (11/02 토 ~ 11/11 월)
- 간단한 UI 추가하기 (Thymeleaf) (11/12 화 ~ 11/17 일)
- 더미 데이터 추가하기 (11/30 토)
- Swagger 적용 (11/30 토)
추가 기능 구현 계획
- 음악 검색 (Kotlin JDSL) (11/30 토)
- 재생목록 템플릿 제공 (01/12 일)





















