์ค๋์ ์ด์ธ๋ฐ๋ผ (FortuneBara)
โ์ค๋์ ์ด์ธ๋ฐ๋ผโ ์๋น์ค๋ ๊ท์ฝ๊ณ ์นํ๋ ฅ ์ข์ ์นดํผ๋ฐ๋ผ ๋์๊ฐ ๋งค์ผ๋งค์ผ ๋น์ ์ ์ด์ธ๋ฅผ ์ ์ณ์ฃผ๋ ์จ๋ผ์ธ ํ๋ก ์ด์ธ ํ๋ซํผ์ ๋๋ค. ๋จ์ํ ์ฌ๋ฏธ๋ฅผ ๋์ด, ์ ๊ตํ ํ๋ก ๋ถ์์ ๊ธฐ๋ฐ์ผ๋ก ๋ณด๋ค ์ ๋ขฐํ ์ ์๋ ์ด์ธ ํด์๊ณผ ์ฌ์ธต์ ์ธ ์๋ด ๊ฒฝํ์ ์ ๊ณตํ ์์ ์ ๋๋ค.
์นดํผ๋ฐ๋ผ ๋์์ ํต์ฐฐ๋ ฅ์ผ๋ก ๋น์ ์ ํ๋ฃจ ์ด์ธ์ ํ์ด์ ํฌ์ฐฉํด๋๋ฆฝ๋๋ค. ๊ฐ๋จํ ์ด๋ฆ, ์๋ ์์ผ๋ง ์ ๋ ฅํ๋ฉด, ๊ท์ฝ๊ณ ๋ ์ ํํ ์ด์ธ ๋ฉ์์ง๋ฅผ ๋ฐ์๋ณผ ์ ์์ต๋๋ค.
- JDK: 17
- Spring Boot: 3.4.1
- Spring Boot ๊ด๋ จ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ฒ์ :
- Spring Security 6.4.2
- Spring Web 6.2.1
- Spring Data JPA 3.4.1
- Database ๊ด๋ จ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ฒ์ :
- Jakarta Persistence 3.1.0
- MySQL Connector 9.1.0
- H2 Database: 2.3.232
- Jackson ๊ด๋ จ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ฒ์ :
- Jackson Core: 2.18.2
- Jackson Datatype Hibernate5: 2.18.2
- ํ
์คํธ ๊ด๋ จ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ฒ์ :
- JUnit Jupiter: 5.11.4
- Mockito Core: 5.14.2
- Spring Data JPA
- Spring Security
- Google OAuth2
- MySQL
- Redis
- Docker
- AWS EC2
- GitHub Actions
- Endpoint:
/user/sign-up - Request Body:
{ "userId": 123, "name": "ํ๊ธธ๋", "email": "test@example.com", "nickname": "testuser", "birth": "1995-07-30", "provider": "google", "providerUid": "google-12345", "accessToken": "access-token-example", "refreshToken": "refresh-token-example" } - Response:
{ "userId": 123, "name": "ํ๊ธธ๋", "email": "test@example.com", "nickname": "testuser", "birth": "1995-07-30", "provider": "google", "providerUid": "google-12345", "accessToken": "access-token-example", "refreshToken": "refresh-token-example", "isRegistered": true, "createdAt": "2025-01-28 12:00:00", "updatedAt": "2025-01-28 12:00:00", "createdBy": 101, "updatedBy": 101 } - Status Codes:
201 Created: ํ์๊ฐ์ ์ฑ๊ณต400 Bad Request: ์์ฒญ ๋ฐ์ดํฐ ์ค๋ฅ
- Endpoint:
/user/{userId} - Path Parameter:
userId(Long) : ์กฐํํ ์ฌ์ฉ์ ID
- Response:
{ "userId": 123, "name": "ํ๊ธธ๋", "email": "test@example.com", "nickname": "testuser", "birth": "1995-07-30", "provider": "google", "providerUid": "google-12345", "accessToken": "access-token-example", "refreshToken": "refresh-token-example", "isRegistered": true, "createdAt": "2025-01-28 12:00:00", "updatedAt": "2025-01-28 12:00:00", "createdBy": 101, "updatedBy": 101 } - Status Codes:
200 OK: ์กฐํ ์ฑ๊ณต404 Not Found: ํด๋น ์ฌ์ฉ์๊ฐ ์์
- Endpoint:
/user/{userId} - Path Parameter:
userId(Long) : ์์ ํ ์ฌ์ฉ์ ID
- Request Body:
{ "name": "๊น์ฒ ์", "nickname": "newnickname", "birth": "2000-01-01" } - Response:
{ "userId": 123, "name": "๊น์ฒ ์", "email": "test@example.com", "nickname": "newnickname", "birth": "2000-01-01", "provider": "google", "providerUid": "google-12345", "accessToken": "access-token-example", "refreshToken": "refresh-token-example", "isRegistered": true, "createdAt": "2025-01-28 12:00:00", "updatedAt": "2025-01-28 13:00:00", "createdBy": 101, "updatedBy": 103 } - Status Codes:
200 OK: ์์ ์ฑ๊ณต400 Bad Request: ์์ฒญ ๋ฐ์ดํฐ ์ค๋ฅ404 Not Found: ํด๋น ์ฌ์ฉ์๊ฐ ์์
- Endpoint:
/user/{userId} - Path Parameter:
userId(Long) : ์ญ์ ํ ์ฌ์ฉ์ ID
- Response:
- Status Code:
204 No Content(์ญ์ ์ฑ๊ณต) - Status Code:
404 Not Found(ํด๋น ์ฌ์ฉ์๊ฐ ์์)
- Status Code:
- Endpoint:
/user - Response:
[ { "userId": 123, "name": "ํ๊ธธ๋", "email": "test@example.com", "nickname": "testuser", "birth": "1995-07-30", "provider": "google", "providerUid": "google-12345", "accessToken": "access-token-example", "refreshToken": "refresh-token-example", "isRegistered": true, "createdAt": "2025-01-28 12:00:00", "updatedAt": "2025-01-28 12:00:00", "createdBy": 101, "updatedBy": 101 }, { "userId": 456, "name": "์ด์ํฌ", "email": "another@example.com", "nickname": "anotheruser", "birth": "2000-12-15", "provider": "kakao", "providerUid": "kakao-67890", "accessToken": "access-token-example-2", "refreshToken": "refresh-token-example-2", "isRegistered": false, "createdAt": "2025-01-28 12:30:00", "updatedAt": "2025-01-28 12:45:00", "createdBy": 102, "updatedBy": 103 } ] - Status Codes:
200 OK: ์กฐํ ์ฑ๊ณต
- Endpoint:
/card - Request Body:
{ "name": "The Fool", "orientation": "UPRIGHT" } - Response:
{ "cardId": 1, "name": "The Fool", "orientation": "UPRIGHT", "createdAt": "2025-01-28T12:00:00", "updatedAt": "2025-01-28T12:00:00", "createdBy": 101, "updatedBy": 101 } - Status Codes:
201 Created: ์นด๋ ์์ฑ ์ฑ๊ณต400 Bad Request: ์์ฒญ ๋ฐ์ดํฐ ์ค๋ฅ
- Endpoint:
/card/{cardId} - Path Parameter:
cardId(Long) : ์กฐํํ ์นด๋ ID
- Response:
{ "cardId": 1, "name": "The Magician", "orientation": "REVERSED", "createdAt": "2025-01-28T12:00:00", "updatedAt": "2025-01-28T12:30:00", "createdBy": 101, "updatedBy": 102 } - Status Codes:
200 OK: ์กฐํ ์ฑ๊ณต404 Not Found: ํด๋น ์นด๋๊ฐ ์์
- Endpoint:
/card/{cardId} - Path Parameter:
cardId(Long) : ์์ ํ ์นด๋ ID
- Request Body:
{ "name": "The High Priestess", "orientation": "UPRIGHT" } - Response:
{ "cardId": 1, "name": "The High Priestess", "orientation": "UPRIGHT", "createdAt": "2025-01-28T12:00:00", "updatedAt": "2025-01-28T13:00:00", "createdBy": 101, "updatedBy": 103 } - Status Codes:
200 OK: ์์ ์ฑ๊ณต400 Bad Request: ์์ฒญ ๋ฐ์ดํฐ ์ค๋ฅ404 Not Found: ํด๋น ์นด๋๊ฐ ์์
- Endpoint:
/card/{cardId} - Path Parameter:
cardId(Long) : ์ญ์ ํ ์นด๋ ID
- Response:
- Status Code:
204 No Content(์ญ์ ์ฑ๊ณต) - Status Code:
404 Not Found(ํด๋น ์นด๋๊ฐ ์์)
- Status Code:
- Endpoint:
/card - Response:
[ { "cardId": 1, "name": "The Fool", "orientation": "UPRIGHT", "createdAt": "2025-01-28T12:00:00", "updatedAt": "2025-01-28T12:00:00", "createdBy": 101, "updatedBy": 101 }, { "cardId": 2, "name": "The Magician", "orientation": "REVERSED", "createdAt": "2025-01-28T12:15:00", "updatedAt": "2025-01-28T12:45:00", "createdBy": 102, "updatedBy": 103 } ] - Status Codes:
200 OK: ์กฐํ ์ฑ๊ณต
