Skip to content

cbu-manage/backend

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

425 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

씨뢀엉 λ°±μ—”λ“œ API μ„œλ²„

ν•œκ΅­κ³΅ν•™λŒ€ν•™κ΅ ν”„λ‘œκ·Έλž˜λ° 동아리 씨뢀엉(CBU Manage) ν™ˆνŽ˜μ΄μ§€ λ°±μ—”λ“œ

Java Spring Boot MySQL Redis AWS S3 Docker


λͺ©μ°¨


ν”„λ‘œμ νŠΈ μ†Œκ°œ

씨뢀엉 동아리 ν™ˆνŽ˜μ΄μ§€μ˜ λ°±μ—”λ“œ API μ„œλ²„μž…λ‹ˆλ‹€.
νšŒμ› 인증, μŠ€ν„°λ””/ν”„λ‘œμ νŠΈ λͺ¨μ§‘, ν™œλ™ λ³΄κ³ μ„œ, μ½”λ”©ν…ŒμŠ€νŠΈ 문제 관리, μžλ£Œμ‹€ λ“± 동아리 μš΄μ˜μ— ν•„μš”ν•œ κΈ°λŠ₯을 μ œκ³΅ν•©λ‹ˆλ‹€.


기술 μŠ€νƒ

λΆ„λ₯˜ 기술
Language Java 17
Framework Spring Boot 3.3.5
ORM Spring Data JPA (Hibernate)
Auth Spring Security + JWT (jjwt 0.12.6)
DB MySQL (AWS RDS)
Cache / Token Store Redis
Storage AWS S3
API Docs SpringDoc OpenAPI (Swagger UI)
Build Gradle
Deploy Docker

μ•„ν‚€ν…μ²˜

ν”„λ‘ νŠΈμ—”λ“œ (Next.js)
        β”‚
        β”‚  HTTP (μΏ ν‚€ 기반 JWT)
        β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚       Spring Boot API       β”‚
β”‚  JwtFilter β†’ Controller     β”‚
β”‚       β†’ Service β†’ JPA       β”‚
β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
       β”‚            β”‚
   MySQL(RDS)     Redis
                   (RefreshToken)
                   
       └──── AWS S3 (이미지)

인증 흐름

  1. 둜그인 μ‹œ accessToken / refreshToken μΏ ν‚€ λ°œκΈ‰ (HttpOnly)
  2. 이후 λͺ¨λ“  μš”μ²­μ—μ„œ JwtFilterκ°€ μΏ ν‚€λ₯Ό 검증해 SecurityContext에 μ‚¬μš©μž 정보 등둝
  3. accessToken 만료 μ‹œ /api/v1/login/refresh둜 μž¬λ°œκΈ‰

νŒ¨ν‚€μ§€ ꡬ쑰

src/main/java/com/example/cbumanage/
β”œβ”€β”€ global/
β”‚   β”œβ”€β”€ common/         # JwtFilter, JwtProvider, ApiResponse
β”‚   β”œβ”€β”€ config/         # SecurityConfig, RedisConfig, S3Config
β”‚   └── error/          # 곡톡 μ˜ˆμ™Έ 처리 (BaseException, ErrorCode)
β”‚
β”œβ”€β”€ user/               # 둜그인/νšŒμ›κ°€μž…/λ‚΄ 정보
β”œβ”€β”€ member/             # 동아리 멀버(CbuMember) 관리
β”œβ”€β”€ candidate/          # κ°€μž… ν›„λ³΄μž 관리 (ꡬ글 μ‹œνŠΈ 연동)
β”‚
β”œβ”€β”€ group/              # κ·Έλ£Ή μƒμ„±Β·κ°€μž…Β·μŠΉμΈ 관리
β”œβ”€β”€ post/               # κ²Œμ‹œκΈ€ 곡톡 (Post 메인 ν…Œμ΄λΈ”)
β”œβ”€β”€ study/              # μŠ€ν„°λ”” λͺ¨μ§‘ κ²Œμ‹œκΈ€
β”œβ”€β”€ project/            # ν”„λ‘œμ νŠΈ λͺ¨μ§‘ κ²Œμ‹œκΈ€
β”œβ”€β”€ report/             # ν™œλ™ λ³΄κ³ μ„œ κ²Œμ‹œκΈ€
β”œβ”€β”€ problem/            # μ½”λ”©ν…ŒμŠ€νŠΈ 문제
β”œβ”€β”€ resource/           # μžλ£Œμ‹€
β”‚
β”œβ”€β”€ comment/            # λŒ“κΈ€ / λ‹΅κΈ€
β”œβ”€β”€ image/              # 이미지 μ—…λ‘œλ“œ (AWS S3)
β”œβ”€β”€ email/              # 이메일 인증
β”œβ”€β”€ dues/               # νšŒλΉ„ 관리
└── log/                # ν™œλ™ 둜그

μ‹œμž‘ν•˜κΈ°

사전 μš”κ΅¬μ‚¬ν•­

  • Java 17
  • Docker & Docker Compose (ꢌμž₯)
  • MySQL 8.x
  • Redis 7.x

둜컬 μ‹€ν–‰

1. μ €μž₯μ†Œ 클둠

git clone https://github.com/cbu-manage/backend.git
cd backend

2. ν™˜κ²½λ³€μˆ˜ μ„€μ •

src/main/resources/application.properties λ˜λŠ” ν™˜κ²½λ³€μˆ˜λ‘œ μ•„λž˜ ν•­λͺ©μ„ μ„€μ •ν•©λ‹ˆλ‹€.
(상세 ν•­λͺ©μ€ ν™˜κ²½λ³€μˆ˜ μ„€μ • μ°Έκ³ )

3. Gradle λΉŒλ“œ & μ‹€ν–‰

./gradlew clean build -x test
java -jar build/libs/*.jar

4. Docker둜 μ‹€ν–‰

docker build -t cbu-backend .
docker run -p 8080:8080 --env-file .env cbu-backend

μ„œλ²„ 기동 ν›„ Swagger UI: http://localhost:8080/swagger-ui/index.html


API λͺ…μ„Έ

전체 APIλŠ” Swagger UIμ—μ„œ 확인할 수 μžˆμŠ΅λ‹ˆλ‹€.
μ•„λž˜λŠ” μ£Όμš” 도메인별 μ—”λ“œν¬μΈνŠΈ μš”μ•½μž…λ‹ˆλ‹€.

인증 /api/v1/login

Method Path 인증 ν•„μš” μ„€λͺ…
POST /api/v1/login ❌ 둜그인 (쿠킀에 토큰 λ°œκΈ‰)
POST /api/v1/login/signup ❌ νšŒμ›κ°€μž…
POST /api/v1/login/refresh ❌ AccessToken μž¬λ°œκΈ‰
GET /api/v1/login/me βœ… λ‚΄ 정보 쑰회
PATCH /api/v1/login/password βœ… λΉ„λ°€λ²ˆν˜Έ λ³€κ²½
POST /api/v1/login/password/reset ❌ 이메일 μΈμ¦μ½”λ“œ 기반 λΉ„λ°€λ²ˆν˜Έ μ΄ˆκΈ°ν™”
DELETE /api/v1/login βœ… λ‘œκ·Έμ•„μ›ƒ
DELETE /api/v1/login/account βœ… νšŒμ› νƒˆν‡΄

κ²Œμ‹œκΈ€ 곡톡 /api/v1/post

Method Path 인증 ν•„μš” μ„€λͺ…
GET /api/v1/post ❌ μΉ΄ν…Œκ³ λ¦¬λ³„ κ²Œμ‹œκΈ€ λͺ©λ‘ (νŽ˜μ΄μ§•)
GET /api/v1/post/my βœ… λ‚΄κ°€ μž‘μ„±ν•œ κ²Œμ‹œκΈ€ λͺ©λ‘
GET /api/v1/post/{postId}/post ❌ κ²Œμ‹œκΈ€ 단건 쑰회
DELETE /api/v1/post/{postId} βœ… κ²Œμ‹œκΈ€ μ‚­μ œ (soft delete)

category κ°’: 1 μŠ€ν„°λ”” Β· 2 ν”„λ‘œμ νŠΈ Β· 5 μ½”λ”©ν…ŒμŠ€νŠΈ Β· 6 μžλ£Œμ‹€ Β· 7 ν™œλ™λ³΄κ³ μ„œ

μŠ€ν„°λ”” /api/v1/post/study

Method Path 인증 ν•„μš” μ„€λͺ…
POST /api/v1/post/study βœ… μŠ€ν„°λ”” κ²Œμ‹œκΈ€ 생성
GET /api/v1/post/study ❌ μŠ€ν„°λ”” λͺ©λ‘ 쑰회
GET /api/v1/post/study/{postId} ❌ μŠ€ν„°λ”” 상세 쑰회
PATCH /api/v1/post/study/{postId} βœ… μŠ€ν„°λ”” μˆ˜μ • (μž‘μ„±μž)
DELETE /api/v1/post/study/{postId} βœ… μŠ€ν„°λ”” μ‚­μ œ (μž‘μ„±μž)
GET /api/v1/post/study/filter ❌ νƒœκ·Έλ³„ μŠ€ν„°λ”” 검색
POST /api/v1/post/study/{postId}/apply βœ… μŠ€ν„°λ”” μ°Έκ°€ μ‹ μ²­
GET /api/v1/post/study/{postId}/apply βœ… μ‹ μ²­μž λͺ©λ‘ 쑰회 (νŒ€μž₯)
PATCH /api/v1/post/study/{postId}/apply/{applyId} βœ… μ‹ μ²­ 수락/거절 (νŒ€μž₯)
POST /api/v1/post/study/{postId}/close βœ… λͺ¨μ§‘ 마감 + κ·Έλ£Ή 생성 (νŒ€μž₯)

ν”„λ‘œμ νŠΈ /api/v1/post/project

Method Path 인증 ν•„μš” μ„€λͺ…
POST /api/v1/post/project βœ… ν”„λ‘œμ νŠΈ κ²Œμ‹œκΈ€ 생성
GET /api/v1/post/project ❌ ν”„λ‘œμ νŠΈ λͺ©λ‘ 쑰회
GET /api/v1/post/project/{postId} ❌ ν”„λ‘œμ νŠΈ 상세 쑰회
PATCH /api/v1/post/project/{postId} βœ… ν”„λ‘œμ νŠΈ μˆ˜μ • (μž‘μ„±μž)
DELETE /api/v1/post/project/{postId} βœ… ν”„λ‘œμ νŠΈ μ‚­μ œ (μž‘μ„±μž)
GET /api/v1/post/project/filter ❌ λͺ¨μ§‘뢄야별 ν•„ν„° 쑰회
GET /api/v1/post/project/me βœ… λ‚΄κ°€ μž‘μ„±ν•œ ν”„λ‘œμ νŠΈ λͺ©λ‘

κ·Έλ£Ή /api/v1/groups

Method Path 인증 ν•„μš” κΆŒν•œ μ„€λͺ…
POST /api/v1/groups/{groupId}/members βœ… 일반 κ·Έλ£Ή κ°€μž… μ‹ μ²­
DELETE /api/v1/groups/{groupId}/members/me βœ… 일반 κ°€μž… μ‹ μ²­ μ·¨μ†Œ
GET /api/v1/groups/my βœ… 일반 λ‚΄κ°€ κ°€μž…ν•œ κ·Έλ£Ή λͺ©λ‘
GET /api/v1/groups/my/applications βœ… 일반 λ‚΄ μ‹ μ²­ λͺ©λ‘
GET /api/v1/groups/{groupId} βœ… 일반 κ·Έλ£Ή 상세 쑰회
GET /api/v1/groups/{groupId}/applicants βœ… νŒ€μž₯ κ°€μž… λŒ€κΈ° λͺ©λ‘
PATCH /api/v1/groups/members/{groupMemberId}/applicant βœ… νŒ€μž₯ κ°€μž… 수락/거절
PATCH /api/v1/groups/{groupId}/recruitment βœ… νŒ€μž₯ λͺ¨μ§‘ μƒνƒœ λ³€κ²½
GET /api/v1/groups/admin βœ… κ΄€λ¦¬μž 전체 κ·Έλ£Ή 쑰회
PATCH /api/v1/groups/{groupId}/admin/status βœ… κ΄€λ¦¬μž κ·Έλ£Ή 승인/거절

ν™œλ™ λ³΄κ³ μ„œ /api/v1/report

Method Path 인증 ν•„μš” μ„€λͺ…
POST /api/v1/report βœ… λ³΄κ³ μ„œ 생성
GET /api/v1/report βœ… λ³΄κ³ μ„œ λͺ©λ‘ 쑰회 (νŽ˜μ΄μ§•)
GET /api/v1/report/{postId} βœ… λ³΄κ³ μ„œ 단건 쑰회
PATCH /api/v1/report/{postId} βœ… λ³΄κ³ μ„œ μˆ˜μ • (μž‘μ„±μž)
PATCH /api/v1/report/{postId}/accept βœ… λ³΄κ³ μ„œ 승인 (κ΄€λ¦¬μž)

μ½”λ”©ν…ŒμŠ€νŠΈ 문제 /api/v1/post/problems

Method Path 인증 ν•„μš” μ„€λͺ…
POST /api/v1/post/problems βœ… 문제 등둝
GET /api/v1/post/problems ❌ 문제 λͺ©λ‘ 쑰회
GET /api/v1/post/problems/{id} ❌ 문제 상세 쑰회
PATCH /api/v1/post/problems/{id} βœ… 문제 μˆ˜μ • (μž‘μ„±μž)
DELETE /api/v1/post/problems/{id} βœ… 문제 μ‚­μ œ (μž‘μ„±μž)

μžλ£Œμ‹€ /api/v1/resources

Method Path 인증 ν•„μš” μ„€λͺ…
POST /api/v1/resources βœ… 자료 등둝
GET /api/v1/resources ❌ 자료 λͺ©λ‘ 쑰회
GET /api/v1/resources/my βœ… λ‚΄ 자료 λͺ©λ‘
DELETE /api/v1/resources/{id} βœ… 자료 μ‚­μ œ (μž‘μ„±μž)

λŒ“κΈ€ /api/v1/

Method Path 인증 ν•„μš” μ„€λͺ…
POST /api/v1/post/{postId}/comment βœ… λŒ“κΈ€ μž‘μ„±
GET /api/v1/post/{postId}/comment ❌ λŒ“κΈ€ λͺ©λ‘ 쑰회
POST /api/v1/comment/{commentId}/reply βœ… λ‹΅κΈ€ μž‘μ„±
PATCH /api/v1/comment/{commentId} βœ… λŒ“κΈ€ μˆ˜μ •
DELETE /api/v1/comment/{commentId} βœ… λŒ“κΈ€ μ‚­μ œ

이미지 μ—…λ‘œλ“œ /api/image

Method Path 인증 ν•„μš” μ„€λͺ…
POST /api/image/upload βœ… 이미지 μ—…λ‘œλ“œ (S3) β†’ URL λ°˜ν™˜

지원 ν˜•μ‹: jpg, jpeg, png, gif, webp, heif
μ΅œλŒ€ 파일 크기: 10MB

이메일 인증 /api/v1/mail

Method Path 인증 ν•„μš” μ„€λͺ…
POST /api/v1/mail/send ❌ 인증 메일 λ°œμ†‘
POST /api/v1/mail/verify ❌ 인증 μ½”λ“œ 확인

인증 방식

토큰 λ°œκΈ‰

둜그인 성곡 μ‹œ 응닡 헀더 Set-Cookie둜 두 개의 μΏ ν‚€κ°€ λ‚΄λ €μ˜΅λ‹ˆλ‹€.

μΏ ν‚€λͺ… μ„€λͺ… μœ νš¨μ‹œκ°„
accessToken API μš”μ²­ 인증용 JWT 10λΆ„
refreshToken accessToken μž¬λ°œκΈ‰μš© 10일

두 μΏ ν‚€ λͺ¨λ‘ HttpOnly μ„€μ •μœΌλ‘œ JavaScriptμ—μ„œ 직접 μ ‘κ·Ό λΆˆκ°€ν•©λ‹ˆλ‹€.

토큰 κ°±μ‹ 

POST /api/v1/login/refresh

refreshToken μΏ ν‚€κ°€ μœ νš¨ν•˜λ©΄ μƒˆ accessTokenκ³Ό refreshToken을 μž¬λ°œκΈ‰ν•©λ‹ˆλ‹€.

ν”„λ‘ νŠΈμ—”λ“œ 연동 μ£Όμ˜μ‚¬ν•­

ν”„λ‘ νŠΈμ—”λ“œμ™€ λ°±μ—”λ“œμ˜ 도메인/ν¬νŠΈκ°€ λ‹€λ₯Έ 경우(Cross-Origin):

  • μš”μ²­ μ‹œ λ°˜λ“œμ‹œ credentials: 'include' μ˜΅μ…˜μ„ μ„€μ •ν•΄μ•Ό μΏ ν‚€κ°€ μ „μ†‘λ©λ‹ˆλ‹€.
  • μΏ ν‚€ 섀정은 SameSite=None / Secure=false(개발) λ˜λŠ” Secure=true(HTTPS 운영) 둜 κ΅¬μ„±λ©λ‹ˆλ‹€.
// fetch μ˜ˆμ‹œ
fetch('http://localhost:8080/api/v1/login/me', {
  credentials: 'include',
});

// axios μ˜ˆμ‹œ
axios.get('/api/v1/login/me', { withCredentials: true });

ν™˜κ²½λ³€μˆ˜ μ„€μ •

src/main/resources/application.properties μ—μ„œ κ΄€λ¦¬ν•©λ‹ˆλ‹€.
운영 배포 μ‹œμ—λŠ” ν™˜κ²½λ³€μˆ˜ λ˜λŠ” μ™ΈλΆ€ μ„€μ •μœΌλ‘œ μ£Όμž…ν•˜μ„Έμš”.

ν‚€ μ„€λͺ… μ˜ˆμ‹œ
spring.datasource.url MySQL 접속 URL jdbc:mysql://host:3306/db
spring.datasource.username DB μ‚¬μš©μžλͺ… admin
spring.datasource.password DB λΉ„λ°€λ²ˆν˜Έ password
spring.data.redis.host Redis 호슀트 localhost
spring.data.redis.port Redis 포트 6379
cbu.jwt.secret JWT μ„œλͺ… ν‚€ (32자 이상 ꢌμž₯) your-secret-key
cbu.jwt.expireTime accessToken λ§Œλ£Œμ‹œκ°„ (ms) 600000 (10λΆ„)
cbu.jwt.refreshExpireTime refreshToken λ§Œλ£Œμ‹œκ°„ (ms) 864000000 (10일)
cbu.jwt.secureCookie μΏ ν‚€ Secure ν”Œλž˜κ·Έ false(개발) / true(운영)
cbu.login.salt λΉ„λ°€λ²ˆν˜Έ ν•΄μ‹± salt your-salt
aws.access.key.id AWS μ•‘μ„ΈμŠ€ ν‚€ -
aws.secret.access.key AWS μ‹œν¬λ¦Ώ ν‚€ -
aws.region.static AWS 리전 ap-northeast-2
aws_bucket S3 버킷λͺ… your-bucket
spring.mail.username Gmail λ°œμ‹  계정 example@gmail.com
spring.mail.password Gmail μ•± λΉ„λ°€λ²ˆν˜Έ -
google.spreadSheet.id ꡬ글 μ‹œνŠΈ ID (멀버 κ΄€λ¦¬μš©) -

Made with ❀️ by CBU Manage Β· ν•œκ΅­κ³΅ν•™λŒ€ν•™κ΅ ν”„λ‘œκ·Έλž˜λ° 동아리 씨뢀엉

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors