© 2025 Sejin Cha. All rights reserved.
Built with Next.js, deployed on Vercel
요구사항 명세 기능이 작동하지 않았을 때 에러처리 어떻게 해야할지(에러 메세지 등) 빨간색으로 적어주세요.
참고용 INDEX 헤더
번호
기능명세서
1
[로고] 선택
- 메인페이지로 이동
2
[파티 찾기 버튼] 선택
- OTT 선택 모달 표시
3
[파티 만들기 버튼] 선택
- 파티 생성 페이지로 이동
4
[로그인 버튼] 선택
- 비로그인 상태에서만 표시
- 로그인 페이지로 이동
5
[마이페이지 버튼 ]선택
- 로그인 상태에서만 표시
- 개인정보 페이지로 이동
6
[OTT 선택 모달] 선택
- 파티 찾기 버튼 클릭시 표시
7
[OTT 닫기 버튼] 선택
- OTT 선택 모달 종료
8
[OTT 목록 버튼] 선택
- 해당 OTT 파티 목록 페이지
1. 네비게이션바를 통해 OTT 목록을 볼 수 있다 메인 페이지
번호
기능명세서
0
현재 화면 접근방법
- URL을 통한 접근
1
[파티 현황판 캐러셀] 클릭
- 이전 또는 다음 파티 현황판으로 전환
2
[파티 목록 자세히보기] 선택
- OTT별 파티목록 페이지 이동
3
[서비스 목록] 특정 서비스 선택
- OTT별 파티목록 페이지 이동
2. 현재 매칭 대기중인 파티들을 볼 수 있다 3. 전체 서비스(OTT) 목록을 볼 수 있다 (1. API와 동일) 4. OTT의 상세 정보를 가져올 수 있다 로그인 페이지
번호
기능 명세서
0
현재 화면 접근방법
- 로그인 버튼 클릭
- 로그인이 필요한 서비스 접근
1
[네이버로 시작하기 버튼] 클릭
- 최초 로그인시 회원가입
- 랜덤 닉네임 지정 (통보!)
5. 소셜 로그인 할 수 있다 OTT별 파티 목록 페이지
번호
기능 명세서
1
[파티만들기] 선택
- 파티 생성 페이지 이동
(해당 OTT 선택 활성)
2
[파티 개요] 선택
- dropdown으로 파티 상세 정보 표시
- 토글 기능
1) OTT 요금제
2) 파티 정원과 현재 파티원 수
3) 파티 시작까지 남은 일자
4) 파티원 미달시 진행 여부 문구
[파티 목록] 필터링
이미 정렬이 된 상태로 보여줌
- 정렬 기준 : 시작일 임박순 && 참여한 파티원 수 && 오래된 파티 순
- 파티 유지 기간 필터링?
- 같은 수준에 있는 파티에 대한 정렬은 등록일 순
3
[파티 더보기] 선택
5 개의 파티를 추가로 화면에 출력
- 프론트끼리 얘기 좀 더 해보기
4
[파티상세 정보]
- 파티개요(2번) 선택시 화면에 표시
- 파티 가입 버튼 선택시 파티 가입 진행
- 서비스 등급은 최고 등급을 가정
6. 파티 목록을 볼 수 있다 파티 상세 페이지 7. 파티목록에서 파티 상세 정보를 확인할 수 있다 파티 생성 페이지 step1
번호
기능 명세서
0
현재 화면 접근방법
- 서비스 파티 목록 페이지 [파티만들기] 버튼 클릭
- 마이페이지 [파티만들기] 버튼 클릭
1
OTT 서비스 목록
- OTT 서비스 목록에서 서비스 1개 선택
- 서비스 파티목록 페이지에서 접근시 해당 서비스가 선택된 상태로 접근
1) 라디오버튼처럼 하나의 서비스만 선택가능
2 ) 선택한 서비스 활성화 (효과 예: opacity or border 등등 디자인으로 풀수있음)
3) 목록 : 넷플릭스, 웨이브, 왓챠, 티빙, 디즈니+, 라프텔, 쿠팡플레이, 아마존프라임 (8개)
2
[다음] 클릭
- step2 파티기간설정 페이지로 이동
step2
번호
기능 명세서
0
현재 화면 접근방법
- Step1 서비스 선택에서 다음 버튼 클릭
1
2
[날짜입력 input]
- 파티 시작일 설정 input (
MUI )
1) input focus시 달력 모달 오픈
2) 모달에서 날짜 선택
3) 선택된 날짜 input에 출력
3
기간설정 Slider
- 파티 유지 기간 설정 slider (
MUI )
1) 1 ~ 12개월 중 선택 가능
4
기간설정
- 설정한 기간 숫자로 출력
5
[이전] 클릭
- step1 OTT서비스 선택페이지로 이동
6
[다음] 클릭
- step3 파티 규칙설정 페이지로 이동
step3
번호
기능 명세서
0
현재 화면 접근방법
- Step2 기간설정에서 다음 버튼 클릭
1
2
규칙 태그 목록
- 1인 1회선
- 1인 1기기
- 닉네임과 동일하게 프로필 네임 설정
- 개인사정 환불 불가
- 계정양도 불가
- 설정 임의 변경 불가
- 19세 이상
- 규칙 태그 토글 버튼
1) 규칙태그들 다중 선택 가능
2) 버튼 클릭시 토글
- 태그의 의미 → 검색? 쉬운 진입?
3
[이전] 클릭
- step2 기간설정 페이지로 이동
4
[다음] 클릭
- step4 인원설정 페이지로 이동
step4
번호
기능 명세서
0
현재 화면 접근방법
- Step3 규칙 설정에서 다음 버튼 클릭
1
2
[인원 카운트 - 버튼] 클릭
- 클릭시 모집인원 -
- 최소인원 1명
- 최소 인원일 경우 버튼 disabed
3
[인원 카운트 + 버튼] 클릭
- 클릭시 모집인원 +
- 최대 모집인원은 서비스 동시접속 인원 수 - 1(파티장 제외)
- 최대 모집인원 달성시 버튼 disabled
4
[인원 미달 파티시작 동의]
- 필수 답변요소로 미리 미리 설정해 두지 않고 사용자에게 답변 요구
- 동의할 경우 나머지 금액은 파티장 부담 (계정주인이라 자유도가 높음)
- 동의 하지 않은 경우 모집인원 미달이면 파티 삭제
5
[이전] 클릭
- step3 규칙설정 페이지로 이동
6
[다음] 클릭
- 인원 미달 파티시작 동의여부 답변이 없으면 버튼 disabled
- step5 공유계정 설정 페이지로 이동
step5
번호
기능 명세서
0
현재 화면 접근방법
- Step4 인원설정에서 다음 버튼 클릭
1
2
[공유 아이디 인풋]
3
[공유 비밀번호 인풋]
4
[공유 비밀번호 확인 인풋]
- 비밀번호 유효성 검사 비밀번호 인풋과 일치하는지 확인
- 비밀번호가 일치하지 않습니다.
5
[이전] 클릭
- step4 인원설정 페이지로 이동
6
[다음] 클릭
- 뒤 스텝이 보류된 상황이라 완료버튼으로 바뀌어야 할듯
- form 유효성 검사
1) input이 하나라도 비어있다면 버튼 비활성
2) 비밀번호가 일치하지 않는다면 버튼 비활성
- 마이 페이지로 이동
8. 파티를 만들 수 있다 파티 참여 페이지 9. 유저의 현재 포인트를 확인할 수 있다 (파티 참여하기 버튼 클릭) 10. 유저는 파티에 참여할 수 있다 (결제하기 버튼 클릭) 11. 포인트를 충전할 수 있다 (충전하기 버튼 클릭) 개인정보 페이지
번호
기능 명세서
1
[로그아웃] 선택
- 로그아웃 진행 후 메인페이지로 이동
2
[충전] 선택
- 페이지 이동
- 사용자 입력 방식
2
구독중인 [파티 이름] 선택
- 더보기 버튼
파티 상세 페이지로 이동
3
종료된 [파티 이름] 선택 불가
disabled 처리
12. 사용자 정보를 확인할 수 있다
13. 참여중인 파티 목록을 확인할 수 있다 14. 대기중인 파티 목록을 확인할 수 있다 15. 종료된 파티 목록을 확인할 수 있다 내가 가입한 파티 페이지
번호
기능 명세서
1
[파티 정보]
1) OTT 이미지
2) OTT 요금제
3) 파티장 / 파티원
4) 요금
5) 파티 유지 기간
2
[공유 계정 정보] 선택
아이디, 비밀번호
카드 뒤집기
- 아이디, 비밀번호 정보를 보여줌
3
[수정] 선택
파티장 만 수정 버튼
이 보임
- 모달 창 제공
- 수정 후 알림 보내기 ( 백둥이 분들과 추가적인 논의 필요 )
4
[비밀번호] 유효성 검사
5
[비밀번호 확인] 유효성 검사
- 첫번째로 입력한 비밀번호와 일치하는지 확인
Tooltip
- 비밀번호가 일치하지 않습니다.
6
[변경] 선택
- 유효성 검사에 성공하면 모달창이 사라지면서 메세지 상자를 띄운다.
Message Box
- 성공적으로 비밀번호가 변경되었습니다.
16. 참여한 파티 상세 정보를 확인할 수 있다 17. 공유 계정의 정보를 알 수 있다 // 요청
GET {{url}}/api/otts
// 응답
Status Code: 200
{
"ottServices" : [
{
"ottId" : 1,
"ottName" : "넷플릭스"
},
{
"ottId" : 2,
"ottName" : "디즈니 플러스"
},
{
"ottId" : 3,
"ottName" : "웨이브"
},
{
"ottId" : 4,
"ottName" : "왓챠"
}
]
}
// 요청
GET {{url}}/api/otts/waitings
// 응답
Status Code: 200
{
"waitingOtts" : [
{
"ottId" : 1,
"ottName" : "넷플릭스",
"waitingForMatch" : 10,
"monthlyFee" : 2800
},
{
"ottId" : 1,
"ottName" : "넷플릭스",
"waitingForMatch" : 20,
"monthlyFee" : 2800
},
{
"ottId" : 1,
"ottName" : "넷플릭스",
"waitingForMatch" : 40,
"monthlyFee" : 2800
},
{
"ottId" : 1,
"ottName" : "넷플릭스",
"waitingForMatch" : 10,
"monthlyFee" : 2800
}
]
}
// 요청
GET {{url}}/api/otts
// 응답
Status Code: 200
{
"ottServices" : [
{
"ottId" : 1,
"ottName" : "넷플릭스"
},
{
"ottId" : 2,
"ottName" : "디즈니 플러스"
},
{
"ottId" : 3,
"ottName" : "웨이브"
},
{
"ottId" : 4,
"ottName" : "왓챠"
}
]
}
// 요청
GET {{url}}/api/otts/{{ottId}}
// 응답
{
"ottId": 1,
"ottName": "넷플릭스",
"subscriptionFee": 10000,
"maxMemberCapacity": 4,
"grade": "프리미엄"
}
// 응답
Status Code : 200
{
"token" : "sdfsdf.sdfsdf.sdf",
"user" : {
"userId" : 1,
"username" : "유저이름",
"birthdate" : "1997-04-13",
}
}
// 요청
GET {{url}}/api/otts/{{ottId}}/parties/?size=5&lastPartyId=1
// 응답
{
"ottId": 1,
"ottName": "넷플릭스",
"parties": [
{
"partyId": 1,
"grade": "프리미엄",
"price": 2500,
"maxMemberCapacity": 4,
"currentMemberCapacity" : 2,
"startDate": "2021-12-18",
"startsIn" : 17,
"endDate": "2022-12-18",
"mustFilled": true
},
{
"partyId": 1,
"grade": "프리미엄",
"price": 2500,
"totalMember": 4,
"currentMember" : 2,
"startDate": "2021-12-19",
"startsIn" : 18,
"endDate": "2022-12-19",
"mustFilled": false
},
{
"partyId": 1,
"grade": "프리미엄",
"price": 2500,
"totalMember": 4,
"currentMember" : 2,
"startDate": "2021-12-19",
"startsIn" : 18,
"endDate": "2022-12-19",
"mustFilled": false
},
{
"partyId": 1,
"grade": "프리미엄",
"price": 2500,
"totalMember": 4,
"currentMember" : 2,
"startDate": "2021-12-19",
"startsIn" : 18,
"endDate": "2022-12-19",
"mustFilled": false
},
{
"partyId": 1,
"grade": "프리미엄",
"price": 2500,
"totalMember": 4,
"currentMember" : 2,
"startDate": "2021-12-19",
"startsIn" : 18,
"endDate": "2022-12-19",
"mustFilled": false
}
]
}
// 요청
GET {{url}}/api/parities/{{partyId}}
// 응답
{
"partyId": Number,
"grade": String,
"monthlyFee": Number,
"totalFee" : Number,
"totalMember": Number,
"currentMember" : Number,
"startDate": String,
"startsIn" : Number,
"endDate": String,
"mustFilled": Boolean,
"Members": [
"Member" : {
"userId" : 1,
"username" : "닉네임",
"isLeader" : true
}
],
"rules": [
"rule" : {
"ruleId" : 1,
"ruleName" : "1인 1회선"
},
"rule" : {
"ruleId" : 1,
"ruleName" : "1인 1회선"
}
]
}
// 요청
POST {{url}}/api/parties
{
"ottId" : 1,
"ottName" : "넷플릭스",
"grade": "프리미엄",
"maxMemberCapacity": 4,
"startDate": "2021-12-8",
"endDate": "2022-01-8",
"mustFilled": true,
"rules": [
{
"ruleId" : 1,
"ruleName" : "1인 1회선"
},
{
"ruleId" : 2,
"ruleName" : "양도 금지"
}
],
"sharedId" : "modi@gmail.com",
"sharedPassword" : "modimodi123"
}
// 응답
200 OK
{
"partyId" : 1
}
// 요청
GET users/{userId}/points
// 헤더
Authorization : 토큰
// 응답
{
"currentPoint": Number // 현재 회원이 보유한 포인트
}
// 요청
POST {{url}}/api/parties/{{partyId}}/join
{
"partiyId" : 1
}
// 응답
// 성공
200 OK
// 실패
400 Bad Request
// 요청
POST {{url}}/api/points/add
{
"points" : 100000
}
// 응답
200
{
"currentPoints": 1200000000
}
// 요청
GET /users/{userId}
Authroization :
// 응답
"user" : {
"userId" 1,
"username" : "닉네임",
"points" : 2000,
}
// 요청
GET /users/{userId}/parties?size=5&partyId=1&status=onGoing
정렬은 파티 참여일 기준
// 응답
{
"onGoingParties" : [
"party" : {
"ottId" : 1,
"ottName" : "넷플릭스",
"partyId": Number,
"startDate": String,
"endDate": String,
"isLeader": true,
"monthlyDeposit" : 10000
},
"party" : {
"ottId" : 1,
"ottName" : "넷플릭스",
"partyId": Number,
"startDate": String,
"endDate": String,
"isLeader": false,
"monthlyFee" : 2500,
"totalFee" : 10000
}
],
}
// 요청
GET /users/{userId}/parties?size=5&partyId=1&status=recruiting
정렬은 파티 참여일 기준
{
"recruitingParties" : [
"party" : {
"ottId" : 1,
"ottName" : "넷플릭스",
"partyId": Number,
"startDate": String,
"endDate": String,
"isLeader": true,
"monthlyDeposit" : 10000
},
"party" : {
"ottId" : 1,
"ottName" : "넷플릭스",
"partyId": Number,
"startDate": String,
"endDate": String,
"isLeader": false,
"monthlyFee" : 2500,
"totalFee" : 10000
}
]
}
// 요청
GET /users/{userId}/parties?size=5&partyId=1&status=recruiting
정렬은 파티 참여일 기준
{
"finishedParties" : [
"party" : {
"ottId" : 1,
"ottName" : "넷플릭스",
"partyId": Number,
"startDate": String,
"endDate": String,
"isLeader": true,
"monthlyDeposit" : 10000
},
"party" : {
"ottId" : 1,
"ottName" : "넷플릭스",
"partyId": Number,
"startDate": String,
"endDate": String,
"isLeader": false,
"monthlyFee" : 2500,
"totalFee" : 10000
}
]
}
GET /users/{userId}/parties/{partyId}
// 응답
// 파티원
200 OK
{
"ottId" : 1,
"ottName" : "넷플릭스",
"partyId": Number,
"grade": String,
"monthlyFee": Number,
"totalFee" : Number,
"totalMember": Number,
"currentMember" : Number,
"startDate": String,
"startsIn" : Number,
"endDate": String,
"mustFilled": Boolean,
"members": [
"member" : {
"userId" : 1,
"username" : "닉네임",
"isLeader" : true
}
],
"rules": [
"rule" : {
"ruleId" : 1,
"ruleName" : "1인 1회선"
},
"rule" : {
"ruleId" : 1,
"ruleName" : "1인 1회선"
}
]
}
// 파티장
200 OK
{
"ottId" : 1,
"ottName" : "넷플릭스",
"partyId": Number,
"grade": String,
"monthlyDeposit": Number,
"totalMember": Number,
"currentMember" : Number,
"startDate": String
"endDate": String,
"mustFilled": Boolean,
"members": [
"member" : {
"userId" : 1,
"username" : "닉네임",
"isLeader" : true
}
],
"rules": [
"rule" : {
"ruleId" : 1,
"ruleName" : "1인 1회선"
},
"rule" : {
"ruleId" : 1,
"ruleName" : "1인 1회선"
}
]
}
// 요청
GET parties/{partyId}/sharedAccount
Authorization
// 응답
{
"sharedId" : "modi@gmail.com",
"sharedPassword" : "modimodi123"
}