From 16642a0b24424895c9ead466eedaa7d38e171286 Mon Sep 17 00:00:00 2001 From: kjw Date: Wed, 8 Apr 2026 23:19:10 +0900 Subject: [PATCH] =?UTF-8?q?[=EC=A3=BC=EC=84=9D=20=EC=B6=94=EA=B0=80]=20?= =?UTF-8?q?=EC=96=B4=EB=85=B8=ED=85=8C=EC=9D=B4=EC=85=98=20=EC=97=AD?= =?UTF-8?q?=ED=95=A0=20=EC=84=A4=EB=AA=85=20=EC=A3=BC=EC=84=9D=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 2 + .../likelion/session/SessionApplication.java | 2 +- .../session/controller/BoardController.java | 38 +++++++++---------- .../com/likelion/session/domain/Board.java | 32 ++++++++-------- .../session/dto/BoardCreateRequest.java | 14 +++---- .../likelion/session/dto/BoardResponse.java | 6 +-- .../session/dto/BoardUpdateRequest.java | 12 +++--- .../session/service/BoardService.java | 14 +++---- 8 files changed, 61 insertions(+), 59 deletions(-) diff --git a/build.gradle b/build.gradle index deca6ed..915fb01 100644 --- a/build.gradle +++ b/build.gradle @@ -26,6 +26,8 @@ repositories { dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-webmvc' + implementation 'org.springframework.boot:spring-boot-starter-validation' + implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.5.0' compileOnly 'org.projectlombok:lombok' developmentOnly 'org.springframework.boot:spring-boot-devtools' diff --git a/src/main/java/com/likelion/session/SessionApplication.java b/src/main/java/com/likelion/session/SessionApplication.java index 658e562..ee8845d 100644 --- a/src/main/java/com/likelion/session/SessionApplication.java +++ b/src/main/java/com/likelion/session/SessionApplication.java @@ -3,7 +3,7 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -@SpringBootApplication +@SpringBootApplication // @SpringBootApplication: 자동 설정을 해주기 위한 어노테이션(@SpringBootConfiguration, @EnableAutoConfiguration, @ComponentScan 포함) public class SessionApplication { public static void main(String[] args) { diff --git a/src/main/java/com/likelion/session/controller/BoardController.java b/src/main/java/com/likelion/session/controller/BoardController.java index 2af74e7..a20f2e8 100644 --- a/src/main/java/com/likelion/session/controller/BoardController.java +++ b/src/main/java/com/likelion/session/controller/BoardController.java @@ -11,12 +11,12 @@ import java.util.List; -@RestController -@RequestMapping("/boards") -@RequiredArgsConstructor +@RestController // @RestController: RESTful API를 위한 컨트롤러(HTTP 요청에 대한 응답을 직접 본문에 담아 전달) +@RequestMapping("/boards") // @RequestMapping: 클라이언트의 요청 URL을 컨트롤러의 클래스나 메서드에 매핑(/boards로 시작하는 주소로 매핑) +@RequiredArgsConstructor // @RequiredArgsConstructor: 필수 인자를 가진 생성자를 자동 생성 public class BoardController { - private final ; + private final BoardService boardService; /* 게시글 생성 @@ -32,57 +32,57 @@ public class BoardController { -> 결과 반환 -> JSON 응답 */ - @Operation( + @Operation( // @Operation: API 엔드포인트의 작업에 대한 설명을 추가하고 세부 정보를 제공 summary = "게시글 생성", description = "새로운 게시글을 생성합니다." ) - @ - public ResponseEntity create(@RequestBody BoardCreateRequest request) { + @PostMapping // @PostMapping: 클라이언트가 POST(데이터 생성) 요청을 보내면 이 코드가 실행 + public ResponseEntity create(@RequestBody BoardCreateRequest request) { // @RequestBody: 클라이언트에서 보낸 HTTP 요청 Body를 자바 객체로 변경 BoardResponse response = boardService.create(request); return ResponseEntity.ok(response); } // 게시글 전체 조회 - @Operation( + @Operation( // @Operation: API 엔드포인트의 작업에 대한 설명을 추가하고 세부 정보를 제공 summary = "게시글 전체 조회", description = "등록된 모든 게시글을 조회합니다." ) - @ + @GetMapping // @GetMapping: 클라이언트가 GET(데이터 조회) 요청을 보내면 이 코드가 실행 public ResponseEntity> findAll() { List response = boardService.findAll(); return ResponseEntity.ok(response); } // 게시글 단건 조회 - @Operation( + @Operation( // @Operation: API 엔드포인트의 작업에 대한 설명을 추가하고 세부 정보를 제공 summary = "게시글 단건 조회", description = "id로 특정 게시글을 조회합니다." ) - @GetMapping("/{id}") - public ResponseEntity findById(@PathVariable Long id) { + @GetMapping("/{id}") // @GetMapping: 클라이언트가 GET(데이터 조회) 요청을 보내면 이 코드가 실행(주소 맨 마지막 / 뒤에 오는 수를 id로 설정) + public ResponseEntity findById(@PathVariable Long id) { // @PathVariable: 리소스 경로에 식별자를 넣어서 동적으로 URL에 정보 담기 가능 BoardResponse response = boardService.findById(id); return ResponseEntity.ok(response); } // 게시글 수정 - @Operation( + @Operation( // @Operation: API 엔드포인트의 작업에 대한 설명을 추가하고 세부 정보를 제공 summary = "게시글 수정", description = "id로 특정 게시글의 제목과 내용을 수정합니다." ) - @("/{id}") - public ResponseEntity update(@PathVariable Long id, - @RequestBody BoardUpdateRequest request) { + @PutMapping("/{id}") // @PutMapping: 클라이언트가 PUT(데이터 수정) 요청을 보내면 이 코드가 실행(주소 맨 마지막 / 뒤에 오는 수를 id로 설정) + public ResponseEntity update(@PathVariable Long id, // @PathVariable: 리소스 경로에 식별자를 넣어서 동적으로 URL에 정보 담기 가능 + @RequestBody BoardUpdateRequest request) { // @RequestBody: 클라이언트에서 보낸 HTTP 요청 Body를 자바 객체로 변경 BoardResponse response = boardService.update(id, request); return ResponseEntity.ok(response); } // 게시글 삭제 - @Operation( + @Operation( // @Operation: API 엔드포인트의 작업에 대한 설명을 추가하고 세부 정보를 제공 summary = "게시글 삭제", description = "id로 특정 게시글을 삭제합니다." ) - @("/{id}") - public ResponseEntity delete(@PathVariable Long id) { + @DeleteMapping("/{id}") // @DeleteMapping: 클라이언트가 DELETE(데이터 삭제) 요청을 보내면 이 코드가 실행(주소 맨 마지막 / 뒤에 오는 수를 id로 설정) + public ResponseEntity delete(@PathVariable Long id) { // @PathVariable: 리소스 경로에 식별자를 넣어서 동적으로 URL에 정보 담기 가능 boardService.delete(id); return ResponseEntity.noContent().build(); } diff --git a/src/main/java/com/likelion/session/domain/Board.java b/src/main/java/com/likelion/session/domain/Board.java index cb873de..0952338 100644 --- a/src/main/java/com/likelion/session/domain/Board.java +++ b/src/main/java/com/likelion/session/domain/Board.java @@ -8,36 +8,36 @@ import java.time.LocalDateTime; -@Getter // getter 메서드 자동 생성 -@Entity // 해당 클래스 DB 테이블로 인식하고 관리 -@Table(name = "boards") -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@AllArgsConstructor +@Getter // @Getter: 접근자(getter 메서드 자동 생성) +@Entity // @Entity: 객체 매핑(해당 클래스 DB 테이블로 인식하고 관리) +@Table(name = "boards") // @Table: 엔티티와 매핑할 테이블을 지정("boards"로 설정) +@NoArgsConstructor(access = AccessLevel.PROTECTED) // @NoArgsConstructor: 파라미터가 없는 디폴트 생성자 생성(접근 권한: protected) +@AllArgsConstructor // @AllArgsConstructor: 모든 변수 값을 파라미터로 받는 생성자를 생성 public class Board { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long ; + @Id // @Id: 데이터베이스 테이블의 기본 키 매핑 + @GeneratedValue(strategy = GenerationType.IDENTITY) // @GeneratedValue: 기본 키를 애플리케이션에 직접 할당 + private Long id; // 게시글 제목 - @Column(nullable = false, length = 100) - private String ; + @Column(nullable = false, length = 100) // @Column: 객체 필드(변수)를 테이블(데이터베이스)의 컬럼(열)에 매핑 + private String title; // 게시글 내용 @Column(nullable = false, columnDefinition = "TEXT") - private String ; + private String content; // 작성자 @Column(nullable = false, length = 30) - private String ; + private String writer; // 생성 시간 @Column(nullable = false) - private LocalDateTime ; + private LocalDateTime createdAt; // 수정 시간 @Column(nullable = false) - private LocalDateTime ; + private LocalDateTime updatedAt; public Board(String title, String content, String writer) { @@ -46,13 +46,13 @@ public Board(String title, String content, String writer) { this.writer = writer; } - @PrePersist + @PrePersist // @PrePersist: 객체가 저장되기 전에 필요한 초기화 작업을 수행 public void prePersist() { this.createdAt = LocalDateTime.now(); this.updatedAt = LocalDateTime.now(); } - @PreUpdate + @PreUpdate // @PreUpdate: 객체의 상태가 업데이트 되기 전에 실행되는 메소드(함수) public void preUpdate() { this.updatedAt = LocalDateTime.now(); } diff --git a/src/main/java/com/likelion/session/dto/BoardCreateRequest.java b/src/main/java/com/likelion/session/dto/BoardCreateRequest.java index 62b1821..1f99d7f 100644 --- a/src/main/java/com/likelion/session/dto/BoardCreateRequest.java +++ b/src/main/java/com/likelion/session/dto/BoardCreateRequest.java @@ -5,13 +5,13 @@ import lombok.NoArgsConstructor; import lombok.Setter; -@Getter -@Setter -@NoArgsConstructor -@AllArgsConstructor +@Getter // @Getter: 접근자(getter 메서드 자동 생성) +@Setter // @Setter: 설정자(setter 메서드 자동 생성) +@NoArgsConstructor // @NoArgsConstructor: 파라미터가 없는 디폴트 생성자 생성(접근 권한: protected) +@AllArgsConstructor // @AllArgsConstructor: 모든 변수 값을 파라미터로 받는 생성자를 생성 public class BoardCreateRequest { // 넘겨주고 싶은 정보: 제목(title), 내용(content), 작성자(writer) - private String ; - private String ; - private String ; + private String title; + private String content; + private String writer; } \ No newline at end of file diff --git a/src/main/java/com/likelion/session/dto/BoardResponse.java b/src/main/java/com/likelion/session/dto/BoardResponse.java index dc6e74f..cb9688d 100644 --- a/src/main/java/com/likelion/session/dto/BoardResponse.java +++ b/src/main/java/com/likelion/session/dto/BoardResponse.java @@ -6,9 +6,9 @@ import java.time.LocalDateTime; -@Getter -@AllArgsConstructor -@Builder +@Getter // @Getter: 접근자(getter 메서드 자동 생성) +@AllArgsConstructor // @AllArgsConstructor: 모든 변수 값을 파라미터로 받는 생성자를 생성 +@Builder // @Builder: 생성자 인자를 메서드 체인을 통해 명시적으로 대입하여 생성자를 호출할 수 있게 클래스 생성 public class BoardResponse { // 돌려주고 싶은 응답: id, title, content, writer, createdAt, updatedAt diff --git a/src/main/java/com/likelion/session/dto/BoardUpdateRequest.java b/src/main/java/com/likelion/session/dto/BoardUpdateRequest.java index d1e98e4..5c9e658 100644 --- a/src/main/java/com/likelion/session/dto/BoardUpdateRequest.java +++ b/src/main/java/com/likelion/session/dto/BoardUpdateRequest.java @@ -7,15 +7,15 @@ import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.Size; -@Getter -@Setter -@NoArgsConstructor +@Getter // @Getter: 접근자(getter 메서드 자동 생성) +@Setter // @Setter: 설정자(setter 메서드 자동 생성) +@NoArgsConstructor // @NoArgsConstructor: 파라미터가 없는 디폴트 생성자 생성(접근 권한: protected) public class BoardUpdateRequest { - @NotBlank(message = "제목은 필수입니다.") - @Size(max = 100, message = "제목은 100자 이하로 입력해주세요.") + @NotBlank(message = "제목은 필수입니다.") // @NotBlank: null과 초기화된 String, 공백 모두 허용 X + @Size(max = 100, message = "제목은 100자 이하로 입력해주세요.") // @Size: 필드 크기가 min과 max 사이여야 값을 저장할 수 있도록 유효성 검사 private String title; - @NotBlank(message = "내용은 필수입니다.") + @NotBlank(message = "내용은 필수입니다.") // @NotBlank: null과 초기화된 String, 공백 모두 허용 X private String content; } diff --git a/src/main/java/com/likelion/session/service/BoardService.java b/src/main/java/com/likelion/session/service/BoardService.java index 1bc58af..2c22b96 100644 --- a/src/main/java/com/likelion/session/service/BoardService.java +++ b/src/main/java/com/likelion/session/service/BoardService.java @@ -12,13 +12,13 @@ import java.util.List; -@Slf4j -@Service -@RequiredArgsConstructor -@Transactional +@Slf4j // @Slf4j: 다양한 로깅 프레임 워크에 대한 추상화(인터페이스) 역할을 하는 라이브러리 +@Service // @Service: 비즈니스 로직을 처리하는 클래스를 표시 +@RequiredArgsConstructor // @RequiredArgsConstructor: 필수 인자를 가진 생성자를 자동 생성 +@Transactional // @Transactional: 특정 메서드 또는 클래스에서 수행되는 ‘트랜잭션’과 관련되어 관리를 위해서 사용(트랜잭션: 데이터베이스 작업이 모두 성공하거나 모두 실패할 때까지 어떤 작업도 부분적으로 적용하지 않고 묶어서 처리) public class BoardService { - private final ; + private final BoardRepository boardRepository; /* 게시글 생성 @@ -51,7 +51,7 @@ public BoardResponse create(BoardCreateRequest request) { - DB에 있는 모든 게시글을 가져옴 - Entity 리스트를 Response DTO 리스트로 변환 */ - @Transactional(readOnly = true) + @Transactional(readOnly = true) // @Transactional: 특정 메서드 또는 클래스에서 수행되는 ‘트랜잭션’과 관련되어 관리를 위해서 사용(읽기 전용) public List findAll() { return boardRepository.findAll() .stream() @@ -71,7 +71,7 @@ public List findAll() { - id로 게시글 조회 - 없으면 예외 발생 */ - @Transactional(readOnly = true) + @Transactional(readOnly = true) // @Transactional: 특정 메서드 또는 클래스에서 수행되는 ‘트랜잭션’과 관련되어 관리를 위해서 사용(읽기 전용) public BoardResponse findById(Long id) { Board board = boardRepository.findById(id) .orElseThrow(() -> new IllegalArgumentException("해당 게시글이 없습니다. id=" + id));