Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
67 commits
Select commit Hold shift + click to select a range
aeb8fad
✨ Feat: quizRoomServiceImpl 작성
mingeung Nov 25, 2025
af5d30c
✨ CommentService getAllCommentsById 작성
junhyung8795 Nov 25, 2025
d3f78f4
✨Comment Dao, Controller, Service, ServiceImpl, CommentMapper.xml 개발
junhyung8795 Nov 25, 2025
a2b7c34
✨Member DAO, DTO, Service, ServiceImpl, Controller, MemberMapper개발
junhyung8795 Nov 25, 2025
79d96c0
feat : 채팅방 생성 API 성공
mingeung Nov 26, 2025
2901bbd
fix : 채팅방 생성 api 반환값 roomId로 수정
mingeung Nov 26, 2025
92d0d91
feat : 채팅방 참여 api : 채팅방 존재 검증 로직 추가
mingeung Nov 26, 2025
3dae53c
feat : getQuizRoomList, getQuizRoomMembers 테스트 완료
mingeung Nov 26, 2025
b37528c
feat : 퀴즈방 삭제 api 테스트 완료 (sql문에 CASCADE 속성 추가)
mingeung Nov 26, 2025
1062ff0
refactor : dto, responseDto, requestDto 폴더 정리
mingeung Nov 26, 2025
8b173b7
feat: getProblems API 구현, limit과 category를 RequestParam으로 전달하도록 수정
mingeung Nov 26, 2025
b82799d
feat: 오답노트 파일 생성
mingeung Nov 26, 2025
2864f17
feat: IncorrectNote dto. 수정. ProblemType enum 생성
mingeung Nov 26, 2025
04bca63
feat: IncorrectNoteMapper 작성
mingeung Nov 26, 2025
ef199a8
Merge remote-tracking branch 'origin/3-quizroom-problem-score-userpro…
junhyung8795 Nov 27, 2025
369e99f
✨ CommentUpdateRequest 생성과 Comment컨트롤러에 적용. Member, Comment Controlle…
junhyung8795 Nov 27, 2025
09cdeed
CommentUpdateRequest 생성과 Comment컨트롤러에 적용. Memeber, Comment컨트롤ë러의 수정로직…
junhyung8795 Nov 27, 2025
f2862fe
feat: 오답노트 조회 api 생성
mingeung Nov 27, 2025
719e3d2
feat: 오답노트 조회, 삭제, 등록 api 구현
mingeung Nov 27, 2025
c79d116
feat: Comment 수정
junhyung8795 Nov 27, 2025
12e838c
feat: 오답노트 API 예외처리 Service에서 체크하도록 수정
mingeung Nov 27, 2025
b52b42c
feat: 퀴즈방 예외 Service에서 처리하도록 수정
mingeung Nov 27, 2025
fd0b1ae
feat: 채팅방 멤버 중복 입장 확인 로직. 퀴즈방에 있는 멤버 조회 dto 생성
mingeung Nov 27, 2025
b67cac6
feat: 유저제작 문제, 세트 코드작성
junhyung8795 Nov 27, 2025
2f2f1a9
feat: 유저제작문제와 유저제작문제세트의 Controller, Mapper, Service, ServiceImpl완성
junhyung8795 Nov 27, 2025
920dab3
refactor : response, request dto 폴더를 dto 폴더 안으로 옮기기
mingeung Nov 28, 2025
5975404
fix : 오답노트 조회 mapper에서 resultType을 Problem에서 IncorrectNoteResponse로 수정
mingeung Nov 28, 2025
1d96d72
fix : 채팅방에 참가 중인 멤버 리스트 출력 성공 (!isEmpty) -> (isEmpty)
mingeung Nov 28, 2025
5bd570a
feat : 회원 조회, 수정, 삭제 API 완료
mingeung Nov 28, 2025
4219aa1
refactor : problem의 예외 service에서 처리하도록 수정
mingeung Nov 28, 2025
15db505
Merge branch '3-quizroom-problem-score-userproblem-mvc-development' o…
junhyung8795 Nov 29, 2025
1b88d4b
api테스트 92프로통과
junhyung8795 Nov 30, 2025
cf028d9
test: QuizRoom 삭제 로직과 UserScore 도메인 추가 후 테스트 결과
junhyung8795 Dec 2, 2025
9c9c32a
.class 등 추적되면 안되는 파일들 정리
junhyung8795 Dec 2, 2025
0c3dc6a
깃이그노어 파일 추가
junhyung8795 Dec 2, 2025
9a63e87
fix: UserScoreServiceImpl
junhyung8795 Dec 2, 2025
cdae9f0
docs: 박준형 리드미 작성
junhyung8795 Dec 2, 2025
40f7574
docs: 프로젝트 개요 수정
junhyung8795 Dec 2, 2025
dd0843c
docs: 마침표 추가
junhyung8795 Dec 2, 2025
fab477c
fix: score, quiezRoom도메인 합친 테스트 결과
junhyung8795 Dec 4, 2025
a573c6a
Merge branch 'comment' of https://github.com/BangBangCodeBoy/Backend …
junhyung8795 Dec 4, 2025
a7d599a
fix: maven 설정파일 추가
junhyung8795 Dec 5, 2025
4ad935c
fix: memberId로 유저제작문제세트 조회 테스트 통과, memberId로 해당 유저의 점수 조회 테스트 통과
junhyung8795 Dec 5, 2025
ff5cc47
refact: 모든 컨트롤러에 Swagger @Tag추가
junhyung8795 Dec 8, 2025
0854b01
feat : JWT Spring Security 구현
mingeung Dec 8, 2025
4ae6dc8
feat : sql 문서 관리하기 위한 설정
mingeung Dec 8, 2025
5055349
feat : 회원가입 시 회원 테이블에 값이 안 들어가는 문제 디버깅
mingeung Dec 8, 2025
390d189
feat: AIProblem용 Dto, 컨트로러, 서비스 + Problem류의 answer타입을 String에서 Int로 변경
junhyung8795 Dec 8, 2025
9c26bf0
Merge branch 'comment' of https://github.com/BangBangCodeBoy/Backend …
junhyung8795 Dec 8, 2025
35ecfb2
feat : dml, ddl 스키마문 분리, 회원가입 시 중복된 아이디면 예외 처리
mingeung Dec 8, 2025
82ac1a4
feat : 로그인 구현 성공
mingeung Dec 8, 2025
41e9207
fix : 문제 선지 정답 type을 String에서 int로 변경
mingeung Dec 8, 2025
f02355c
feat : 퀴즈방에서 특정 멤버 내보내기 로직 성공
mingeung Dec 8, 2025
b2ebf20
feat : controller에서 memberId 받아오는 부분 spring security에서 받아오도록 수정
mingeung Dec 8, 2025
2c07e89
fix : member controller에서 회원가입, 로그인, 로그아웃 로직 삭제하기
mingeung Dec 9, 2025
c7f8f5a
feat : 로그인 response dto 생성
mingeung Dec 9, 2025
372d0ac
fix : CORS Error 해결
mingeung Dec 9, 2025
ba25d7d
docs: DB 스키마 수정
junhyung8795 Dec 10, 2025
76ac0af
fix : 회원 정보 수정 로직 수정 (중복 검사 로직)
mingeung Dec 10, 2025
895b0da
feat : 문제조회
mingeung Dec 10, 2025
a596cef
fix: AIProblemService 패키지명 수정
junhyung8795 Dec 11, 2025
6dd075c
Merge branch 'comment' of https://github.com/BangBangCodeBoy/Backend …
mingeung Dec 11, 2025
1b78e08
Merge branch 'comment' of https://github.com/BangBangCodeBoy/Backend …
junhyung8795 Dec 11, 2025
bbcbf26
fix: UserProblem의 칼럼 변경에 따라 Mapper의 Sql문 수정
junhyung8795 Dec 11, 2025
b14d28e
feat : 회원가입 시 score 테이블에 0점으로 등록하기
mingeung Dec 12, 2025
cad1c65
fix : 스키마 수정. 문제 세트 삭제 시 자식 문제들도 cascade 되도록 추가
mingeung Dec 15, 2025
45c2cd5
fix : 유저 문제 update mapper에 쿼리 오류 있는 부분 수정
mingeung Dec 15, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
HELP.md
target/
.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/

### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache

### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr

### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/

### VS Code ###
.vscode/
/.metadata/

.class
11 changes: 0 additions & 11 deletions .project

This file was deleted.

73 changes: 72 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,72 @@
# Backend
# BangBang Codeboy (정보처리기사/SQLD 스피드 퀴즈 플랫폼)

## 1. 프로젝트 개요
- 정보처리기사와 sqld를 공부의 범위가 방대하여 공부에 어려움을 겪는 자격증 준비생 혹은 SSAFY생을 위해 제작.
- 각 자격증에서 배우는 내용을 쉽게 복습할 수 있는 시스템을 만든다.
- 반 친구들과 스피드 퀴즈 대결을 하며 재미있게 학습한다.
- 랭킹 기능을 제공하여 학습의 성취감을 얻는다.

## 2. 핵심 기능
- 정보처리기사와 sqld 관련 키워드를 활용한 4지선다 퀴즈 제공.
- 퀴즈방 생성 및 최대 20명과 실시간 대결.
- 오답노트 및 해설 제공.
- 유저 제작 문제 생성/수정/삭제.
- 리더보드 랭킹.
- 유저가 직접 문제를 제작 가능.
- 혹은 ChatGPT, Gemini로 문제를 자동으로 생성하고 해설을 제공.

## 3. Tech Stack & 아키텍처
<img width="400" height="600" alt="image" src="https://github.com/user-attachments/assets/a3324b77-93d6-4209-a023-4c01f6a7f2b6" />
<br/>

- Spring, MySQL, MyBatis, Fast API -> 백엔드 API 개발과 데이터베이스, 외부 LLM 호출 서버 제작을 맡고 있음.


## 4. 시스템 설계 문서
- [ERD]
<img width="1200" height="700" alt="관통프로젝트" src="https://github.com/user-attachments/assets/cc8fa9d8-ef1d-4ed8-a239-c5bbcad12c26" />

- [유즈케이스 다이어그램]
<img width="1200" height="700" alt="image" src="https://github.com/user-attachments/assets/28f040f0-5e32-47ef-84f7-9f59f790c8d1" />

- [기능 명세서 (구글 스프레드시트)](https://docs.google.com/spreadsheets/d/1pif1EVEQNDvyv444s-4GoqX6n816fivUlyM2uHmzNT8/edit?gid=0#gid=0)
- [WBS & 일정관리(Notion)](https://pointy-harpymimus-0cb.notion.site/2a76fbddf57780169009ed2301511ee1)
- [목업/화면 설계(Notion)](https://pointy-harpymimus-0cb.notion.site/2ab6fbddf57781839d13f9224dfa7a9c)


## 5. API 시나리오 테스트
### 테스트 시나리오
1. 모든 테이블의 데이터들만 삭제.
2. 회원가입 + 해당 유저의 점수 등록.
3. 로그인(전단계에서 회원가입한 유저의 id와 password를 이용).
4. 문제세트 전체조회.
5. 로그인한 회원이 만든 유저제작문제세트 조회.
6. 로그인한 회원이 유저제작문제 3개 추가.
7. 로그인한 회원이 유저제작문제 하나 수정.
8. 유저제작 문제의 댓글 조회.
9. 로그인한 회원이 댓글 3개 작성.
10. 로그인한 회원이 댓글 하나 수정.
11. 로그인한 회원이 댓글 삭제.
12. 로그인한 회원이 문제 세트 삭제.
13. 모든 회원들의 점수 조회.
14. 로그인한 회원 한명의 점수를 조회.
15. 로그인한 회원 한명의 점수를 수정.
16. 문제테이블(problem테이블) 에서 문제 전체 조회.
17. 문제테이블(problem테이블) 에서 문제 전체 조회.
18. 로그인한 회원의 오답노트에 문제 추가 후 로그인한 회원의 오답노트 안의 전체 문제 조회.
19. 로그인한 회원의 오답노트에 있는 문제 삭제(problem과 user_problem테이블에 있는 문제도 삭제되면 안됨).
20. 모든 퀴즈방 목록 조회.
21. 로그인한 회원이 퀴즈방을 생성하고 방장이 됨(isHost = 1).
22. 또 다른 mcp서버가 localhost:8082에서 가동되며 같은 DB 다른 회원을 가입하고 로그인 전체 퀴즈방들을 조회하여 조회된 퀴즈방에 들어가있는 회원들을 조회하고 isHost=0인 방장이 아닌 상태로 다른 방장이 만든 퀴즈방에 들어가기.
23. 방장인 회원이 퀴즈방을 삭제.

### 테스트 방법
1. html에 자바스크립트를 작성 후 axios 통신을 통해 Vite 프록시 서버에 요청을 보낸 후 응답을 console.log로 출력.
2. 테스트 결과를 testResultYYYYMMDDHH형식으로 다운로드.
<img width="2493" height="1701" alt="image" src="https://github.com/user-attachments/assets/dac14fda-938c-4e5f-8726-f9744f76e6c1" />



## 6. 향후 개선 계획
- DeepseekOCR을 활용하여 개념요약 PDF -> 텍스트 -> 문제 제작 Flow 개발 / Fast API로 외부 LLM 호출하여 문제 생성 및 해설 기능 개발.
- API 테스트 파이프라인 제작.
3 changes: 3 additions & 0 deletions codeBoy_backend/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,6 @@ build/

### VS Code ###
.vscode/
/.metadata/

.class
Empty file modified codeBoy_backend/mvnw
100644 → 100755
Empty file.
108 changes: 60 additions & 48 deletions codeBoy_backend/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -29,57 +29,69 @@
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>3.0.5</version>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter-test</artifactId>
<version>3.0.5</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<dependencies>
<dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> <scope>runtime</scope> </dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<build>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>3.0.5</version>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>

<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.12.3</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.12.3</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.12.3</version>
<scope>runtime</scope>
</dependency>

<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.3.0</version>
</dependency>

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.42</version>
</dependency>

<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
</dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-mysql</artifactId>
</dependency>

</dependencies>


<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.codeboy.mvc.config;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@MapperScan("com.codeboy.mvc.model.dao")
public class MyBatisConfig {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package com.codeboy.mvc.config;

import com.codeboy.mvc.jwt.JWTFilter;
import com.codeboy.mvc.jwt.JWTUtil;
import com.codeboy.mvc.jwt.LoginFilter;
import com.codeboy.mvc.model.service.CustomerUserDetailService;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import java.util.List;

@RequiredArgsConstructor
@EnableWebSecurity
@Configuration
public class SecurityConfig {

private final CustomerUserDetailService customerUserDetailService;
private final JWTUtil jwtUtil;
private final com.fasterxml.jackson.databind.ObjectMapper objectMapper; //


@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}

@Bean
public AuthenticationManager authenticationManager(HttpSecurity http) throws Exception {
var builder = http.getSharedObject(org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder.class);

builder
.userDetailsService(customerUserDetailService)
.passwordEncoder(bCryptPasswordEncoder());

return builder.build();
}

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http,
AuthenticationManager authenticationManager) throws Exception {

http
.formLogin(AbstractHttpConfigurer::disable)
.httpBasic(AbstractHttpConfigurer::disable)
.csrf(AbstractHttpConfigurer::disable)
.cors(cors -> cors.configurationSource(corsConfigurationSource()));


http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/", "/login", "/api/join", "/swagger-ui/**",
"/v3/api-docs/**",
"/api-docs/**",
"/swagger-resources/**").permitAll()
.requestMatchers("/admin/**").hasRole("ADMIN") // ✅ 보통 이렇게 씀
.anyRequest().authenticated()
);

http
.sessionManagement(session ->
session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
);

http.addFilterAt(
new LoginFilter(authenticationManager, jwtUtil, objectMapper),
UsernamePasswordAuthenticationFilter.class
);

http.addFilterBefore(
new JWTFilter(jwtUtil, customerUserDetailService),
UsernamePasswordAuthenticationFilter.class
);

return http.build();
}
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();

// 프론트 주소 허용
configuration.setAllowedOrigins(List.of("http://localhost:5173"));
// 모든 메서드 허용
configuration.setAllowedMethods(List.of("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"));
// 모든 헤더 허용
configuration.setAllowedHeaders(List.of("*"));
// 쿠키/Authorization 헤더 허용 (JWT 쓸 때 보통 true)
configuration.setAllowCredentials(true);

UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.codeboy.mvc.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class AdminController {

@GetMapping("/admin")
public String adminP() {
return "admin Controller";
}
}
Loading