Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 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
8068509
feat : Controller에 swaggger를 위한 Tag 어노테이션 붙이기
mingeung Dec 1, 2025
ddbec75
fix : 요청 필드 값이 null인 경우 예외처리 삭제(회원수정 요청은 patch이므로 필드 값이 nulL이 될 수 있다.)
mingeung Dec 1, 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
44 changes: 44 additions & 0 deletions .classpath
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
<attributes>
<attribute name="maven.pomderived" value="true"/>
<attribute name="optional" value="true"/>
</attributes>
</classpathentry>
<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources">
<attributes>
<attribute name="maven.pomderived" value="true"/>
<attribute name="test" value="true"/>
<attribute name="optional" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" path="target/generated-sources/annotations">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
<attribute name="ignore_optional_problems" value="true"/>
<attribute name="m2e-apt" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/test-classes" path="target/generated-test-sources/test-annotations">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
<attribute name="ignore_optional_problems" value="true"/>
<attribute name="m2e-apt" value="true"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="target/classes"/>
</classpath>
23 changes: 23 additions & 0 deletions .project
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,30 @@
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.wst.common.project.facet.core.builder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.springframework.ide.eclipse.boot.validation.springbootbuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>
2 changes: 2 additions & 0 deletions .settings/org.eclipse.jdt.apt.core.prefs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
eclipse.preferences.version=1
org.eclipse.jdt.apt.aptEnabled=false
12 changes: 12 additions & 0 deletions .settings/org.eclipse.jdt.core.prefs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
org.eclipse.jdt.core.compiler.compliance=17
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
org.eclipse.jdt.core.compiler.processAnnotations=disabled
org.eclipse.jdt.core.compiler.release=enabled
org.eclipse.jdt.core.compiler.source=17
4 changes: 4 additions & 0 deletions .settings/org.eclipse.m2e.core.prefs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
activeProfiles=
eclipse.preferences.version=1
resolveWorkspaceProjects=true
version=1
4 changes: 4 additions & 0 deletions .settings/org.eclipse.wst.common.project.facet.core.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<faceted-project>
<installed facet="java" version="17"/>
</faceted-project>
2 changes: 2 additions & 0 deletions .settings/org.springframework.ide.eclipse.prefs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
boot.validation.initialized=true
eclipse.preferences.version=1
Binary file added bin/com/codeboy/CodeBoyBackendApplication.class
Binary file not shown.
Binary file added bin/com/codeboy/CodeBoyBackendApplicationTests.class
Binary file not shown.
Binary file added bin/com/codeboy/common/Category.class
Binary file not shown.
Binary file added bin/com/codeboy/common/Status.class
Binary file not shown.
Binary file added bin/com/codeboy/mvc/config/SwaggerConfig.class
Binary file not shown.
Binary file not shown.
Binary file added bin/com/codeboy/mvc/model/dao/CommentDao.class
Binary file not shown.
Binary file added bin/com/codeboy/mvc/model/dao/IncorrectNoteDao.class
Binary file not shown.
Binary file added bin/com/codeboy/mvc/model/dao/MemberDao.class
Binary file not shown.
Binary file added bin/com/codeboy/mvc/model/dao/ProblemDao.class
Binary file not shown.
Binary file added bin/com/codeboy/mvc/model/dao/QuizRoomDao.class
Binary file not shown.
Binary file added bin/com/codeboy/mvc/model/dao/ScoreDao.class
Binary file not shown.
Binary file not shown.
Binary file added bin/com/codeboy/mvc/model/dao/UserProblemDao.class
Binary file not shown.
Binary file added bin/com/codeboy/mvc/model/dto/Comment.class
Binary file not shown.
Binary file added bin/com/codeboy/mvc/model/dto/IncorrectNote.class
Binary file not shown.
Binary file added bin/com/codeboy/mvc/model/dto/Member.class
Binary file not shown.
Binary file not shown.
Binary file added bin/com/codeboy/mvc/model/dto/Problem.class
Binary file not shown.
Binary file added bin/com/codeboy/mvc/model/dto/QuizRoom.class
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added bin/com/codeboy/mvc/model/dto/UserProblem.class
Binary file not shown.
Binary file added bin/com/codeboy/mvc/model/dto/UserProblemSet.class
Binary file not shown.
Binary file added bin/com/codeboy/mvc/model/dto/UserScore.class
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added bin/com/codeboy/mvc/model/service/ScoreService.class
Binary file not shown.
Binary file not shown.
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
35 changes: 13 additions & 22 deletions codeBoy_backend/pom.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
Expand Down Expand Up @@ -30,6 +30,7 @@
<java.version>17</java.version>
</properties>
<dependencies>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
Expand Down Expand Up @@ -63,20 +64,22 @@
<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.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>
<version>1.18.42</version>
<scope>provided</scope>
</dependency>

</dependencies>

<build>
Expand All @@ -85,27 +88,15 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>

</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</path>
</annotationProcessorPaths>
</configuration>

</plugin>
</plugins>
</build>

</project>
</project>
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,166 @@
package com.codeboy.mvc.controller;

import java.util.ArrayList;
import java.util.List;

import com.codeboy.mvc.model.dto.request.CommentUpdateRequest;
import com.codeboy.mvc.model.dto.response.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.codeboy.mvc.model.dto.Comment;
import com.codeboy.mvc.model.service.CommentService;

@RestController
@RequestMapping("/api/comments")
@Tag(name="Comment RESTful API", description = "Comment CRUD를 할 수 있는 REST API")
public class CommentController {
private final CommentService commentService;


@Autowired
public CommentController(CommentService commentService) {
this.commentService = commentService;
}


@GetMapping("{userProblemSetId}")
//숫자가 아닌 값이 userProblemSetId에 오면 스프링이 컨트롤러에 도달하기전에 400BAD_REQUEST를 보내줌
public ResponseEntity<ApiResponse<List<Comment>>> getAllCommentsById(@PathVariable("userProblemSetId") long userProblemSetId){
List<Comment> comments = commentService.getAllCommentsById(userProblemSetId);

if (comments.isEmpty()) {
//댓글이 달리지 않은 경우
return ResponseEntity.status(HttpStatus.OK)
.body(ApiResponse.success(HttpStatus.OK, "댓글이 없습니다.", new ArrayList<Comment>()));
}
//댓글 조회에 성공한 경우
return ResponseEntity.status(HttpStatus.OK).body(ApiResponse.success(HttpStatus.OK, "댓글 조회 성공", comments));

}

@PostMapping("{userProblemSetId}")
public ResponseEntity<ApiResponse<Void>> addComment(@PathVariable long userProblemSetId,
@RequestBody Comment comment, HttpSession session) {
if (comment.getContent() == null || comment.getContent().isBlank()) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
.body(ApiResponse.failure(HttpStatus.BAD_REQUEST, "댓글 내용은 비어 있을 수 없습니다."));
}
Long memberId = (Long) session.getAttribute("memberId");
if (memberId == null) {
// 인증 안 됨
return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
.body(ApiResponse.failure(HttpStatus.UNAUTHORIZED, "로그인이 필요합니다."));
}
comment.setMemberId(memberId);
int result = commentService.addComment(userProblemSetId, comment);

if (result == 0) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
.body(ApiResponse.failure(HttpStatus.BAD_REQUEST, "잘못된 요청. 댓글 추가 실패"));
}

return ResponseEntity.status(HttpStatus.CREATED)
.body(ApiResponse.success(HttpStatus.CREATED, "댓글 추가 성공", null));
}


//리소스의 일부(content)만 수정하므로 패치매핑
@PatchMapping("{userProblemSetId}/{commentId}")
public ResponseEntity<ApiResponse<Void>> updateComment(
@PathVariable long userProblemSetId,
@PathVariable long commentId,
@RequestBody CommentUpdateRequest commentUpdateRequest,
HttpSession session) {

Long memberId = (Long) session.getAttribute("memberId");
if (memberId == null) {
// 인증 안 됨
return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
.body(ApiResponse.failure(HttpStatus.UNAUTHORIZED, "로그인이 필요합니다."));
}

if (!memberId.equals(commentUpdateRequest.getMemberId())) {
// 인가 실패
// 로그인 중인 회원이 자신이 작성한 댓글이 아닌 것을 수정하려할 때
return ResponseEntity.status(HttpStatus.FORBIDDEN)
.body(ApiResponse.failure(HttpStatus.FORBIDDEN, "본인의 댓글만 수정할 수 있습니다."));
}

//댓글이 비어있을 때
if (commentUpdateRequest.getContent() == null || commentUpdateRequest.getContent().isBlank()) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
.body(ApiResponse.failure(HttpStatus.BAD_REQUEST, "수정할 댓글 내용을 입력해주세요."));
}

Comment comment = new Comment();
comment.setContent(commentUpdateRequest.getContent());

int result = commentService.updateComment(commentId, comment);

if (result == 0) {
return ResponseEntity.status(HttpStatus.NOT_FOUND)
.body(ApiResponse.failure(HttpStatus.NOT_FOUND, "존재하지 않는 댓글입니다."));

}

return ResponseEntity.status(HttpStatus.OK)
.body(ApiResponse.success(HttpStatus.OK, "댓글 수정 성공", null));
}


@DeleteMapping("{userProblemSetId}/{commentId}")
public ResponseEntity<ApiResponse<Void>> deleteComment(@PathVariable long userProblemSetId,
@PathVariable long commentId,
HttpSession session) {

Long memberId = (Long) session.getAttribute("memberId");

// 로그인 안한 상태
if (memberId == null) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
.body(ApiResponse.failure(HttpStatus.UNAUTHORIZED, "로그인이 필요합니다."));
}

// DB에서 댓글 작성자 ID 조회
Long ownerId = commentService.getCommentOwnerId(commentId);

// 댓글ID가 존재하지 않는 경우
if (ownerId == null) {
return ResponseEntity.status(HttpStatus.NOT_FOUND)
.body(ApiResponse.failure(HttpStatus.NOT_FOUND, "존재하지 않는 댓글입니다."));
}

// 권한 없음 (본인 댓글 아님)
if (!memberId.equals(ownerId)) {
return ResponseEntity.status(HttpStatus.FORBIDDEN)
.body(ApiResponse.failure(HttpStatus.FORBIDDEN, "본인이 작성한 댓글만 삭제할 수 있습니다."));
}

// 삭제 실행
int result = commentService.deleteComment(commentId);

if (result == 0) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(ApiResponse.failure(HttpStatus.INTERNAL_SERVER_ERROR, "댓글 삭제에 실패했습니다."));
}

// 삭제 실패 (DB 오류 등의 상황)

return ResponseEntity.status(HttpStatus.OK)
.body(ApiResponse.success(HttpStatus.OK, "댓글 삭제 성공", null));
}


}
Loading