Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
85 commits
Select commit Hold shift + click to select a range
20a5ccc
[Feat] WebSocket, STOMP 설정 파일 추가
Jsnooopy Dec 8, 2025
384613b
[Docs] 클래스 설명 문구 추가
Jsnooopy Dec 8, 2025
27b6ef0
[Feat] WebSocket / STOMP 설정
Jsnooopy Dec 8, 2025
a713561
[Feat] 채팅 도메인 엔티티 생성
Jsnooopy Dec 8, 2025
7a60fde
[Feat] 채팅방 목록 조회 API 구현
Jsnooopy Dec 8, 2025
29bdd7b
[Feat] 유저 정보, SecurityConfig 설정 추가
k0081915 Dec 8, 2025
fd9716b
[Feat] 회원가입 구현
k0081915 Dec 8, 2025
a5fb723
[Feat] 실시간 메시지 전송 및 저장 구현
Jsnooopy Dec 8, 2025
30be2de
[Docs] 클래스 파일 정보 작성
Jsnooopy Dec 8, 2025
21281ad
[Feat] 로그인, JWT 발급 구현
k0081915 Dec 8, 2025
1634e3c
[Feat] 토큰 재발급 구현
k0081915 Dec 8, 2025
9f42c67
[Feat] 로그아웃 구현
k0081915 Dec 8, 2025
8f3fe96
[Feat] 채팅 도메인 세팅 + 채팅방 목록 조회 API, 메시지 전송 기능 구현
Jsnooopy Dec 8, 2025
e7c2b75
[Feat] AuthController 수정
k0081915 Dec 9, 2025
cf541ec
[Feat] AuthController 재수정
k0081915 Dec 9, 2025
656d5f5
[Feat] 게시글 Entity 및 DTO 정의
Dec 9, 2025
8a49aae
[Feat] 게시글 Repository 및 QueryDSL 조회 쿼리 구현
Dec 9, 2025
f6af958
[Feat] 게시글 CRUD 비즈니스 로직 구현
Dec 9, 2025
db8434e
[Feat] 게시글 CRUD API 엔드포인트 구현
Dec 9, 2025
65e16fb
Merge pull request #10 from MINI-Tech-Post/feat/auth-jwt
k0081915 Dec 9, 2025
70e176d
Merge branch 'main' of https://github.com/MINI-Tech-Post/Tech-Post_BE…
Dec 9, 2025
463d302
[Feat] QueryDSL 의존성 및 빌드 설정 추가
Dec 9, 2025
17b8432
[Fix] 사용자 도메인 추가에 따른 설정 통합
Jsnooopy Dec 9, 2025
f778871
[Feat] 관리자(ADMIN) 권한 검증 로직 추가
Dec 9, 2025
7c8b48c
[Feat] 소셜 회원 정보 표준화, 회원 저장 구현
k0081915 Dec 9, 2025
2b5ea5e
[Feat] QueryDSL설정 파일 추가
Dec 9, 2025
76202be
[Feat] 소셜 로그인 성공 로직 구현
k0081915 Dec 9, 2025
5bbd531
[Style] 클래스 파일 주석 추가
k0081915 Dec 9, 2025
dad0383
[Docs] 게시글(Post) API 스웨거(Swagger) 명세 어노테이션 적용
Dec 9, 2025
51a11f3
[Feat] 그룹 채팅방 생성, 채팅방 메세지 내역 불러오기 기능 구현
Jsnooopy Dec 9, 2025
e497ca6
Merge pull request #14 from MINI-Tech-Post/feat/auth-oauth2
k0081915 Dec 9, 2025
1b95332
Merge branch 'main' of https://github.com/MINI-Tech-Post/Tech-Post_BE…
Dec 9, 2025
2aa3fe9
[Docs] 문서 날짜 오타 수정
Dec 9, 2025
2a5d8ec
[Style] 불필요한 어노테이션 제거
Dec 9, 2025
cdba495
[Feat] Validation 적용 #13
bon0512 Dec 9, 2025
0b2fa32
[Feat] Validation 적용 #13
bon0512 Dec 9, 2025
55640c5
[Refactor] 게시글 등록 응답 개선 및 상태 코드 추가 정의
Dec 9, 2025
5e2c190
[Fix] 리뷰 수정 사항 반영
Jsnooopy Dec 9, 2025
08b52a4
[Fix] 웹소켓 연결 경로 인증 제외 처리
Jsnooopy Dec 9, 2025
6991e52
[Feat] 그룹 채팅방 생성, 메세지 내역 불러오기 API 구현
Jsnooopy Dec 9, 2025
4af6540
Merge branch 'main' of https://github.com/MINI-Tech-Post/Tech-Post_BE…
Dec 9, 2025
c51ffe7
Merge pull request #21 from MINI-Tech-Post/feat/member-validation
bon0512 Dec 9, 2025
99cce50
[Feat] 내가 참여한 채팅방 목록 조회 API
phonil Dec 9, 2025
05ed534
[Feat] 채팅방 입장 API
phonil Dec 9, 2025
0b58435
[Feat] 채팅방 나가기 API
phonil Dec 9, 2025
f5510a9
feat : 전역 예외 처리 추가
oohyj Dec 9, 2025
b9bda24
[Fix]: 누락된 어노테이션 추가 및 userDetails 변수명 수정
phonil Dec 9, 2025
1c42291
Merge branch 'main' of https://github.com/MINI-Tech-Post/Tech-Post_BE…
Dec 10, 2025
3fc42b9
[Refactor] 204 코드 메세지 수정
Dec 10, 2025
202b824
Merge pull request #15 from MINI-Tech-Post/feat/post-crud
ChoiSeungeon Dec 10, 2025
bc7a338
✨ [Feat] 내 채팅방 목록, 채팅방 입장/퇴장 API 구현
phonil Dec 10, 2025
3454a53
Merge pull request #25 from MINI-Tech-Post/feat/global-exception
paul0755 Dec 10, 2025
2d45522
[Feat] 댓글 및 유저 권한 관련 에러 코드(ErrorCode) 추가
Dec 10, 2025
3cad065
[Feat] 댓글(Comment) Entity 및 요청/응답 DTO 정의
Dec 10, 2025
8a62227
[Feat] 댓글 Repository 및 N+1 방지(Fetch Join) 쿼리 구현
Dec 10, 2025
8190ca1
[Feat] 댓글 CRUD 비즈니스 로직 및 작성자 검증 구현
Dec 10, 2025
7a5f74b
[Feat] 댓글 관련 API 엔드포인트 및 Swagger 명세 구현
Dec 10, 2025
a5397e8
[Feat] 게시물 조회 데이터 댓글 수(CommentCount) 집계 기능 추가
Dec 10, 2025
1e8675b
[Docs] Swagger 설명 추가
Dec 10, 2025
3eba5c5
[Refactor] 댓글 목록 조회 메서드명 변경 (findBy -> findAllBy)
Dec 10, 2025
d540c97
[FIX] : 에러 핸들러 통합, 기타 불필요한 도메인 삭제
paul0755 Dec 10, 2025
9688af8
[Refactor] 게시물(Post)와 메서드명 통일 및 DTO 클래스명 통일
Dec 10, 2025
57f6632
[Fix] SecurityConfig, JwtAuthenticationFilter 수정
k0081915 Dec 10, 2025
ae2ec5b
Merge pull request #30 from MINI-Tech-Post/feat/auth-refactoring
k0081915 Dec 10, 2025
e781ff7
Merge branch 'main' of https://github.com/MINI-Tech-Post/Tech-Post_BE…
Dec 10, 2025
7b96452
Merge pull request #26 from MINI-Tech-Post/feat/comment-crud
ChoiSeungeon Dec 10, 2025
9fb7c7d
[Refactor] 스웨거 추가, 로그아웃 로직 및 기타 리팩토링
k0081915 Dec 10, 2025
94a6155
Merge pull request #28 from paul0755/main
bon0512 Dec 10, 2025
3dabef4
Merge pull request #31 from MINI-Tech-Post/feat/auth-refactoring
k0081915 Dec 10, 2025
19a4832
[Refactor] 회원 서비스 예외처리 리팩토링 #32
bon0512 Dec 10, 2025
52ea9b0
[FIX] : 경로 수정
paul0755 Dec 10, 2025
dd0cef2
Merge pull request #33 from paul0755/main
paul0755 Dec 10, 2025
ad3fd58
Merge branch 'main' of https://github.com/MINI-Tech-Post/Tech-Post_BE…
bon0512 Dec 10, 2025
85260d8
[Refactor] 회원 서비스 예외처리 리팩토링 #32
bon0512 Dec 10, 2025
42fd108
Merge branch 'main' of https://github.com/MINI-Tech-Post/Tech-Post_BE…
bon0512 Dec 10, 2025
0c47f2a
[Refactor] 회원 서비스 예외처리 리팩토링 #32
bon0512 Dec 10, 2025
06d59a1
Merge pull request #34 from MINI-Tech-Post/feat/member-exception
bon0512 Dec 11, 2025
6e113cb
[FIX] : gitignore 수정 및 application.yml 파일 추가
paul0755 Dec 11, 2025
f59d07a
Merge branch 'main' of https://github.com/paul0755/Tech-Post_BE
paul0755 Dec 11, 2025
4e16a08
Merge branch 'MINI-Tech-Post:main' into main
paul0755 Dec 11, 2025
077f7a5
[FIX] : gitignore 수정 및 application.yml 파일 추가
paul0755 Dec 11, 2025
24894d9
[FIX] : gitignore 수정 및 application.yml 파일 추가
paul0755 Dec 11, 2025
86b04e7
[FIX] : application-prod.yml 수정
paul0755 Dec 11, 2025
927833b
Merge branch 'MINI-Tech-Post:main' into main
paul0755 Dec 11, 2025
9e380ec
[FIX] : application-prod.yml 수정
paul0755 Dec 11, 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
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ out/
.DS_Store

### application ###
/src/main/resources/application.yml
/src/main/resources/application-dev.yml
/src/main/resources/application-prod.yml

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
# Tech-Post_BE
# Tech-Post_BE.
17 changes: 13 additions & 4 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,14 @@ dependencies {
// Spring 기본
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
//implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-validation'

//WebSocket
implementation 'org.springframework.boot:spring-boot-starter-websocket'

// DB & Redis
runtimeOnly 'com.h2database:h2'
implementation 'com.mysql:mysql-connector-j'
implementation 'org.springframework.boot:spring-boot-starter-data-redis'

Expand All @@ -42,9 +46,9 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'

// JWT
// implementation 'io.jsonwebtoken:jjwt-api:0.11.5'
// runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.11.5'
// runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.11.5'
implementation 'io.jsonwebtoken:jjwt-api:0.13.0'
implementation 'io.jsonwebtoken:jjwt-impl:0.13.0'
implementation 'io.jsonwebtoken:jjwt-jackson:0.13.0' // JSON 처리 라이브러리

// Lombok
compileOnly 'org.projectlombok:lombok'
Expand All @@ -55,6 +59,11 @@ dependencies {
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
testImplementation 'com.h2database:h2'

// QueryDSL
implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta'
annotationProcessor "com.querydsl:querydsl-apt:5.0.0:jakarta"
annotationProcessor "jakarta.annotation:jakarta.annotation-api"
annotationProcessor "jakarta.persistence:jakarta.persistence-api"
}

tasks.named('test') {
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/com/ureka/techpost/TechpostApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;

@EnableJpaAuditing
@SpringBootApplication
public class TechpostApplication {

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package com.ureka.techpost.domain.auth.controller;

import com.ureka.techpost.domain.auth.dto.LoginDto;
import com.ureka.techpost.domain.auth.dto.SignupDto;
import com.ureka.techpost.domain.auth.service.AuthService;
import com.ureka.techpost.global.apiPayload.ApiResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

/**
* @file AuthController.java
@author 김동혁, 구본문
@version 1.0
@since 2025-12-08
@description 이 파일은 사용자 인증과 관련된 HTTP 요청을 받아 처리하는 REST 컨트롤러 클래스입니다.
*/
@Tag(name = "Authentication", description = "인증 관련 API")
@RestController
@RequestMapping("/api/auth")
@RequiredArgsConstructor
public class AuthController {

private final AuthService authService;

@Operation(summary = "회원가입", description = "새로운 사용자를 등록합니다.")
@PostMapping("/signup")
public ApiResponse<String> signup(
@Parameter(description = "회원가입 요청 데이터 (아이디, 비밀번호, 이름)", required = true)
@Valid @RequestBody SignupDto signupDto) {
authService.signup(signupDto);
return ApiResponse.onSuccess("회원가입 성공");
}

@Operation(summary = "토큰 재발급", description = "Refresh Token을 사용하여 만료된 Access Token을 재발급합니다. Refresh Token은 쿠키에서, 만료된 Access Token은 헤더에서 가져옵니다.")
@PostMapping("/reissue")
public ApiResponse<?> reissue(
@Parameter(hidden = true) HttpServletRequest request,
@Parameter(hidden = true) HttpServletResponse response) {
return ApiResponse.onSuccess(authService.reissue(request, response));
}

@Operation(summary = "로그인", description = "사용자 이름과 비밀번호로 로그인하여 Access Token 및 Refresh Token을 발급받습니다.")
@PostMapping("/login")
public ApiResponse<String> login(
@Parameter(description = "로그인 요청 데이터 (아이디, 비밀번호)", required = true)
@Valid @RequestBody LoginDto loginDto,
@Parameter(hidden = true) HttpServletResponse response) {
authService.login(loginDto, response);
return ApiResponse.onSuccess("로그인 성공");
}

@Operation(summary = "로그아웃", description = "Refresh Token을 삭제하고 로그아웃 처리합니다.")
@PostMapping("/logout")
public ResponseEntity<String> logout(
@Parameter(hidden = true) HttpServletRequest request,
@Parameter(hidden = true) HttpServletResponse response) {
authService.logout(request, response);
return ResponseEntity.ok("로그아웃 성공");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package com.ureka.techpost.domain.auth.dto;

import com.ureka.techpost.domain.user.entity.User;
import lombok.Getter;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.oauth2.core.user.OAuth2User;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;

/**
* @file CustomUserDetails.java
@author 김동혁, 구본문
@version 1.0
@since 2025-12-08
@description 이 파일은 Spring Security의 UserDetails와 OAuth2User 인터페이스를 구현한 커스텀 클래스입니다.
*/
@Getter
public class CustomUserDetails implements UserDetails, OAuth2User {

private final User user;
private Map<String, Object> attributes;

// 일반 로그인 생성자
public CustomUserDetails(User user) {
this.user = user;
}

// OAuth2 로그인 생성자
public CustomUserDetails(User user, Map<String, Object> attributes) {
this.user = user;
this.attributes = attributes;
}


// === UserDetails 구현 ===
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {

Collection<GrantedAuthority> collection = new ArrayList<>();
collection.add(new GrantedAuthority() {
@Override
public String getAuthority() {
return user.getRoleName();
}
});

return collection;
}

@Override
public String getPassword() {
return user.getPassword();
}

@Override
public String getUsername() {
return user.getUsername();
}

// === OAuth2User 구현 ===
@Override
public Map<String, Object> getAttributes() {
return attributes;
}

@Override
public String getName() {
return user.getProviderId();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.ureka.techpost.domain.auth.dto;

import lombok.Builder;
import lombok.Getter;
import org.springframework.http.ResponseEntity;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

/**
* @file ErrorResponseDto.java
@author 김동혁, 구본문
@version 1.0
@since 2025-12-08
@description 이 파일은 예외 발생 시 클라이언트에게 반환되는 표준 오류 응답 DTO 클래스입니다.
*/
@Getter
@Builder
public class ErrorResponseDto {

private final String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
private final int status;
private final String error;
private final String message;

public static ResponseEntity<ErrorResponseDto> toResponseEntity(int status, String error, String message) {
return ResponseEntity
.status(status)
.body(ErrorResponseDto.builder()
.status(status)
.error(error)
.message(message)
.build());
}
}
20 changes: 20 additions & 0 deletions src/main/java/com/ureka/techpost/domain/auth/dto/LoginDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.ureka.techpost.domain.auth.dto;

import jakarta.validation.constraints.NotBlank;
import lombok.Data;

/**
* @file LoginDto.java
@author 김동혁, 구본문
@version 1.0
@since 2025-12-08
@description 이 파일은 로그인 요청에 사용되는 DTO 클래스입니다.
*/
@Data
public class LoginDto {

@NotBlank(message = "아이디는 필수입니다.")
private String username;
@NotBlank(message = "비밀번호는 필수입니다.")
private String password;
}
44 changes: 44 additions & 0 deletions src/main/java/com/ureka/techpost/domain/auth/dto/SignupDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.ureka.techpost.domain.auth.dto;

import com.ureka.techpost.domain.user.entity.User;
import com.ureka.techpost.domain.user.enums.Role;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Pattern;
import jakarta.validation.constraints.Size;
import lombok.Data;

/**
* @file SignupDto.java
@author 김동혁, 구본문
@version 1.0
@since 2025-12-08
@description 이 파일은 회원가입 요청에 사용되는 DTO 클래스입니다.
*/
@Data
public class SignupDto {


@NotBlank(message = "아이디는 필수입니다.")
@Size(min = 4, max = 20, message = "아이디는 4~20자여야 합니다.")
@Pattern( regexp = "^[a-zA-Z0-9]+$", message = "아이디는 영문과 숫자만 사용할 수 있습니다." )
private String username;

@NotBlank(message = "비밀번호는 필수입니다.")
@Size(min = 8, max = 20, message = "비밀번호는 8~20자여야 합니다.")
@Pattern( regexp = "^(?=.*[A-Za-z])(?=.*\\d).*$", message = "비밀번호는 영문과 숫자를 포함해야 합니다." )
private String password;

@NotBlank(message = "이름은 필수입니다.")
@Size(max = 30, message = "이름은 30자를 초과할 수 없습니다.")
private String name;

public User toEntity(String encodedPassword) {
return User.builder()
.username(username)
.password(encodedPassword)
.name(name)
.provider("NONE")
.role(Role.ROLE_USER)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.ureka.techpost.domain.auth.entity;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import org.springframework.data.annotation.Id;
import org.springframework.data.redis.core.RedisHash;
import org.springframework.data.redis.core.index.Indexed;

/**
* @file RefreshToken.java
@author 김동혁, 구본문
@version 1.0
@since 2025-12-08
@description 이 파일은 리프레시 토큰 정보를 담는 Redis Entity 클래스입니다.
*/
@Getter
@Builder
@AllArgsConstructor
@RedisHash(value = "refreshToken", timeToLive = 1209600)
public class RefreshToken {

@Id
private String id; // Redis Key (일반적으로 username이나 userId 사용)

@Indexed
private String tokenValue; // 리프레시 토큰 값 (조회용 인덱스)

private String username; // 사용자 식별자

public void updateToken(String tokenValue) {
this.tokenValue = tokenValue;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.ureka.techpost.domain.auth.exception;

/**
* @file InvalidTokenException.java
@author 김동혁, 구본문
@version 1.0
@since 2025-12-08
@description 이 파일은 유효하지 않은 토큰과 관련된 오류 상황에서 발생하는 사용자 정의 런타임 예외(Custom Exception) 클래스입니다.
*/
public class InvalidTokenException extends RuntimeException {
public InvalidTokenException(String message) {
super(message);
}
}
Loading