Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
b2f24ee
feat: 게시물 조회 예외 처리 추가
Soundbar91 Jun 16, 2024
9db00f1
feat: 게시판 조회 예외 처리 추가
Soundbar91 Jun 16, 2024
a1286bc
feat: 사용자 조회 예외 처리 추가
Soundbar91 Jun 16, 2024
4c61209
feat: 사용자 수정 예외 처리 추가
Soundbar91 Jun 16, 2024
c14562b
feat: 게시물 수정 예외 처리 추가
Soundbar91 Jun 16, 2024
48743a0
feat: 게시물/게시판/사용자 생성 null 예외 처리 추가
Soundbar91 Jun 16, 2024
9faed4e
feat: 게시물 생성 예외 처리 추가
Soundbar91 Jun 16, 2024
57ba800
feat: 사용자 삭제 예외 처리 추가
Soundbar91 Jun 16, 2024
e3af0d3
feat: 게시판 삭제 예외 처리 추가
Soundbar91 Jun 16, 2024
e15f15f
refactor: 게시물 조회 예외 처리 수정
Soundbar91 Jun 16, 2024
71156f5
refactor: 게시판 조회 예외 처리 수정
Soundbar91 Jun 16, 2024
c51d743
refactor: 회원 조회 예외 처리 수정
Soundbar91 Jun 16, 2024
9f4c138
style: 라인 포멧팅 및 static import
Soundbar91 Jun 16, 2024
02800bb
refactor: application.yml 수정
Soundbar91 Jun 16, 2024
de1db1e
chore: JPA 의존성 추가
Soundbar91 Jun 19, 2024
27c74e5
chore: Lombok 의존성 추가
Soundbar91 Jun 19, 2024
8856214
chore: Validation 의존성 추가
Soundbar91 Jun 19, 2024
da4c91d
build: jpa 설정 정보 추가
Soundbar91 Jun 23, 2024
1807914
refactor: Article 리펙터링
Soundbar91 Jun 23, 2024
25b516d
refactor: ArticleRepositoryJpa 교체
Soundbar91 Jun 23, 2024
2187c91
refactor: Board 리펙터링
Soundbar91 Jun 23, 2024
5826784
refactor: BoardRepository Jpa 교체
Soundbar91 Jun 23, 2024
fd80235
refactor: Member 리펙터링
Soundbar91 Jun 23, 2024
c6965ad
refactor: MemberRepository Jpa 교체
Soundbar91 Jun 23, 2024
e227a2e
chore: 미사용 import 제거
Soundbar91 Jun 23, 2024
48864b1
refactor: entity 컬럼 어노테이션 추가
Soundbar91 Jun 24, 2024
461422f
refactor: EntityTransaction 삭제
Soundbar91 Jun 24, 2024
a3015bb
feat: 회원/게시판 삭제 예외 임시 작성
Soundbar91 Jun 25, 2024
811f597
refactor: Domain 리펙터링
Soundbar91 Jun 29, 2024
40513f8
refactor: build 패턴 추가
Soundbar91 Jun 29, 2024
2d87235
refactor: Service 리펙터링
Soundbar91 Jun 29, 2024
e4a3f4a
refactor: Repository 리펙터링
Soundbar91 Jun 29, 2024
12201a3
style: build.gradle 정리
Soundbar91 Jun 29, 2024
eb0afbf
refactor: 사용자/게시물/게시판 생성 예외 처리 수정
Soundbar91 Jun 29, 2024
afa3ce9
refactor: Repository 구현체 주석 처리
Soundbar91 Jun 30, 2024
989fbe3
refactor: Member 예외 처리 수정
Soundbar91 Jun 30, 2024
266f23a
refactor: Board 예외 처리 수정
Soundbar91 Jun 30, 2024
175404d
refactor: Article 예외 처리 수정
Soundbar91 Jun 30, 2024
84ecd97
refactor: ErrorCode 수정
Soundbar91 Jun 30, 2024
b5a9a86
refactor: Spring Data JPA 적용
Soundbar91 Jun 30, 2024
996fff8
refactor: 영속성 전의 및 고아 객체 적용
Soundbar91 Jun 30, 2024
452b487
build: dataSource 변경
Soundbar91 Jun 30, 2024
1eb19a3
refactor: builder 패턴 변경
Soundbar91 Jun 30, 2024
520dcec
refactor: 예외 처리 코드 변경
Soundbar91 Jun 30, 2024
1e7596e
refactor: 미 사용 import 제거
Soundbar91 Jun 30, 2024
3206275
refactor: Article 연관관계 수정
Soundbar91 Jun 30, 2024
bf2ecb1
refactor: Builder 패턴 수정
Soundbar91 Jul 1, 2024
4a5f493
과제 제출
Soundbar91 Jul 2, 2024
1248456
refactor: 10주차 피드백 반영
Soundbar91 Jul 5, 2024
ac02295
build: Spring Security 의존성 추가
Soundbar91 Jul 7, 2024
14574b6
feat: 회원가입 기능 추가
Soundbar91 Jul 7, 2024
41b53df
feat: 로그인 기능 추가
Soundbar91 Jul 7, 2024
8f41770
feat: 쿠키 전달 기능 추가
Soundbar91 Jul 7, 2024
28d85d0
feat: 쿠키 검증 로직 추가
Soundbar91 Jul 7, 2024
4c751e5
refactor: 로그인 기능 수정
Soundbar91 Jul 7, 2024
7301e71
refactor: 회원가입 기능 수정
Soundbar91 Jul 7, 2024
f80d614
refactor: 미사용 코드 제거
Soundbar91 Jul 7, 2024
82a7c51
feat: /index 경로 추가
Soundbar91 Jul 7, 2024
0b43b71
build: 의존성 수정
Soundbar91 Jul 8, 2024
ec6e866
refactor: 로그인 로직 수정
Soundbar91 Jul 9, 2024
f17f522
refactor: 미사용 import 제거
Soundbar91 Jul 9, 2024
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
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ http://localhost:8080
| DELETE | /members/{id} | 특정 회원을 삭제합니다. | `id` (path): 회원 ID | - | - |
| POST | /members | 새 회원을 생성합니다. | - | Content-Type: application/json | `{ "name": "", "email": "", "password": "" }` |
| PUT | /members/{id} | 기존 회원을 업데이트합니다. | `id` (path): 회원 ID | Content-Type: application/json | `{ "name": "", "email": "" }` |
| GET | /register | 회원 가입 페이지를 가져옵니다. | - | - |
| GET | /login | 로그인 페이지를 가져옵니다. | - | - |

### 사용 예시

Expand Down
10 changes: 10 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,18 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-jdbc'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-validation'
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

개인적인 의견이긴 한데, 같은 dependencies들은 묶고, 나머지는 띄어쓰기 하는 게 조금 더 보기 좋더라구요

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

따로 생각을 안 하고 추가만 했었는데, 말씀해 주신 것처럼 가독성 좋게 바꿔보겠습니다.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

굿 반영 잘 되었네요

implementation 'org.springframework.security:spring-security-crypto'

runtimeOnly 'com.mysql:mysql-connector-j'
testImplementation 'org.springframework.boot:spring-boot-starter-test'

compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'

testCompileOnly 'org.projectlombok:lombok'
testAnnotationProcessor 'org.projectlombok:lombok'
}

tasks.named('test') {
Expand Down
16 changes: 16 additions & 0 deletions src/main/java/com/example/demo/config/SecurityConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.example.demo.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
public class SecurityConfig {

@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}

}
18 changes: 18 additions & 0 deletions src/main/java/com/example/demo/config/WebConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.example.demo.config;

import com.example.demo.interceptor.LoginCheckInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfig implements WebMvcConfigurer {

@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginCheckInterceptor())
.order(1)
.addPathPatterns("/**")
.excludePathPatterns("/login", "/register", "/");
}
}
45 changes: 19 additions & 26 deletions src/main/java/com/example/demo/controller/ArticleController.java
Original file line number Diff line number Diff line change
@@ -1,22 +1,15 @@
package com.example.demo.controller;

import java.net.URI;
import java.util.List;

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.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.example.demo.controller.dto.request.ArticleCreateRequest;
import com.example.demo.controller.dto.response.ArticleResponse;
import com.example.demo.controller.dto.request.ArticleUpdateRequest;
import com.example.demo.controller.dto.response.ArticleResponse;
import com.example.demo.service.ArticleService;
import jakarta.validation.Valid;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.net.URI;
import java.util.List;

@RestController
public class ArticleController {
Expand All @@ -29,42 +22,42 @@ public ArticleController(ArticleService articleService) {

@GetMapping("/articles")
public ResponseEntity<List<ArticleResponse>> getArticles(
@RequestParam Long boardId
@RequestParam Long boardId
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

들여쓰신 이유가 있나용?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

인텔리제이 코드 정렬 기능(?)을 사용하니 들여쓰기가 들어간거 같습니다.

) {
List<ArticleResponse> response = articleService.getByBoardId(boardId);
return ResponseEntity.ok(response);
}

@GetMapping("/articles/{id}")
public ResponseEntity<ArticleResponse> getArticle(
@PathVariable Long id
@PathVariable Long id
) {
ArticleResponse response = articleService.getById(id);
ArticleResponse response = articleService.getByArticleId(id);
return ResponseEntity.ok(response);
}

@PostMapping("/articles")
public ResponseEntity<ArticleResponse> crateArticle(
@RequestBody ArticleCreateRequest request
public ResponseEntity<ArticleResponse> createArticle(
@Valid @RequestBody ArticleCreateRequest request
) {
ArticleResponse response = articleService.create(request);
ArticleResponse response = articleService.createArticle(request);
return ResponseEntity.created(URI.create("/articles/" + response.id())).body(response);
}

@PutMapping("/articles/{id}")
public ResponseEntity<ArticleResponse> updateArticle(
@PathVariable Long id,
@RequestBody ArticleUpdateRequest request
@PathVariable Long id,
@RequestBody ArticleUpdateRequest request
) {
ArticleResponse response = articleService.update(id, request);
ArticleResponse response = articleService.updateArticle(id, request);
return ResponseEntity.ok(response);
}

@DeleteMapping("/articles/{id}")
public ResponseEntity<Void> updateArticle(
@PathVariable Long id
public ResponseEntity<Void> deleteArticle(
@PathVariable Long id
) {
articleService.delete(id);
articleService.deleteArticle(id);
return ResponseEntity.noContent().build();
}
}
13 changes: 7 additions & 6 deletions src/main/java/com/example/demo/controller/BoardController.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import java.util.List;

import jakarta.validation.Valid;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
Expand Down Expand Up @@ -32,29 +33,29 @@ public List<BoardResponse> getBoards() {

@GetMapping("/boards/{id}")
public BoardResponse getBoard(
@PathVariable Long id
@PathVariable Long id
) {
return boardService.getBoardById(id);
}

@PostMapping("/boards")
public BoardResponse createBoard(
@RequestBody BoardCreateRequest request
@Valid @RequestBody BoardCreateRequest request
) {
return boardService.createBoard(request);
}

@PutMapping("/boards/{id}")
public BoardResponse updateBoard(
@PathVariable Long id,
@RequestBody BoardUpdateRequest updateRequest
@PathVariable Long id,
@RequestBody BoardUpdateRequest updateRequest
) {
return boardService.update(id, updateRequest);
return boardService.updateBoard(id, updateRequest);
}

@DeleteMapping("/boards/{id}")
public ResponseEntity<Void> deleteBoard(
@PathVariable Long id
@PathVariable Long id
) {
boardService.deleteBoard(id);
return ResponseEntity.noContent().build();
Expand Down
46 changes: 46 additions & 0 deletions src/main/java/com/example/demo/controller/LoginController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.example.demo.controller;

import com.example.demo.controller.dto.request.LoginRequest;
import com.example.demo.controller.dto.response.MemberResponse;
import com.example.demo.service.LoginService;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;

import java.io.IOException;

@Controller
public class LoginController {

private final LoginService loginService;

public LoginController(LoginService loginService) {
this.loginService = loginService;
}

@PostMapping("/login")
public ResponseEntity<MemberResponse> login(
@Valid @ModelAttribute LoginRequest loginRequest,
HttpServletResponse response,
HttpServletRequest request
) throws IOException {
MemberResponse member = loginService.login(loginRequest);
if (member == null) {
response.sendRedirect(request.getContextPath());
return ResponseEntity.badRequest().build();
}

Cookie cookie = new Cookie("memberId", String.valueOf(member.id()));
cookie.setHttpOnly(true);
cookie.setSecure(true);

response.addCookie(cookie);
response.sendRedirect(request.getContextPath() + "/main");
return ResponseEntity.ok(member);
}
}
38 changes: 16 additions & 22 deletions src/main/java/com/example/demo/controller/MemberController.java
Original file line number Diff line number Diff line change
@@ -1,20 +1,14 @@
package com.example.demo.controller;

import java.util.List;

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.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import com.example.demo.controller.dto.request.MemberCreateRequest;
import com.example.demo.controller.dto.request.MemberUpdateRequest;
import com.example.demo.controller.dto.response.MemberResponse;
import com.example.demo.service.MemberService;
import jakarta.validation.Valid;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
public class MemberController {
Expand All @@ -27,40 +21,40 @@ public MemberController(MemberService memberService) {

@GetMapping("/members")
public ResponseEntity<List<MemberResponse>> getMembers() {
List<MemberResponse> response = memberService.getAll();
List<MemberResponse> response = memberService.getMembers();
return ResponseEntity.ok(response);
}

@GetMapping("/members/{id}")
public ResponseEntity<MemberResponse> getMember(
@PathVariable Long id
@PathVariable Long id
) {
MemberResponse response = memberService.getById(id);
MemberResponse response = memberService.getByMemberId(id);
return ResponseEntity.ok(response);
}

@PostMapping("/members")
public ResponseEntity<MemberResponse> create(
@RequestBody MemberCreateRequest request
public ResponseEntity<MemberResponse> createMember(
@Valid @ModelAttribute MemberCreateRequest request
) {
MemberResponse response = memberService.create(request);
MemberResponse response = memberService.createMember(request);
return ResponseEntity.ok(response);
}

@PutMapping("/members/{id}")
public ResponseEntity<MemberResponse> updateMember(
@PathVariable Long id,
@RequestBody MemberUpdateRequest request
@PathVariable Long id,
@RequestBody MemberUpdateRequest request
) {
MemberResponse response = memberService.update(id, request);
MemberResponse response = memberService.updateMember(id, request);
return ResponseEntity.ok(response);
}

@DeleteMapping("/members/{id}")
public ResponseEntity<Void> deleteMember(
@PathVariable Long id
@PathVariable Long id
) {
memberService.delete(id);
memberService.deleteMember(id);
return ResponseEntity.noContent().build();
}
}
18 changes: 18 additions & 0 deletions src/main/java/com/example/demo/controller/PageController.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.example.demo.controller;

import com.example.demo.controller.dto.request.LoginRequest;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;


Expand All @@ -23,4 +25,20 @@ public String getArticlesPage() {
public String getArticleDetailPage() {
return "article";
}

@GetMapping("/register")
public String getRegisterPage() {
return "register";
}

@GetMapping("/login")
public String getLoginPage() {
return "login";
}

@GetMapping("/index")
public String getIndexPage() {
return "index";
}

}
Original file line number Diff line number Diff line change
@@ -1,10 +1,22 @@
package com.example.demo.controller.dto.request;

import com.example.demo.domain.Article;
import com.example.demo.domain.Board;
import com.example.demo.domain.Member;
import jakarta.validation.constraints.NotNull;

public record ArticleCreateRequest(
Long authorId,
Long boardId,
String title,
String description
@NotNull(message = "회원 아이디는 필수로 입력해야 합니다.") Long authorId,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

어노테이션의 적극적인 사용..!

@NotNull(message = "게시판 아이디는 필수로 입력해야 합니다.") Long boardId,
@NotNull(message = "제목은 필수로 입력해야 합니다.") String title,
@NotNull(message = "게시물 내용은 필수로 입력해야 합니다.") String description
) {

public Article toEntity(Board board, Member member) {
return Article.builder()
.member(member)
.board(board)
.title(this.title)
.content(this.description)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
package com.example.demo.controller.dto.request;

import com.example.demo.domain.Board;
import jakarta.validation.constraints.NotNull;

public record BoardCreateRequest(
String name
@NotNull(message = "게시판 이름은 필수로 입력해야 합니다.") String name
) {

public Board toEntity() {
return new Board(name);
}
}
Loading