From 72120873dd451c3fe670abc21834fbdaa172e4d0 Mon Sep 17 00:00:00 2001 From: hcfinai <202500804@hufs.ac.kr> Date: Sun, 12 Apr 2026 13:45:46 +0900 Subject: [PATCH] =?UTF-8?q?=EC=84=B8=EC=85=98=20=EA=B3=BC=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- SpringCRUDSession | 1 + board/.gitignore | 15 +------- board/src/Main.java | 15 ++++++++ board/src/main/resources/application.yml | 4 +-- build.gradle | 4 ++- .../likelion/session/SessionApplication.java | 6 +++- .../session/controller/BoardController.java | 32 ++++++++--------- .../com/likelion/session/domain/Board.java | 36 +++++++++---------- .../session/dto/BoardCreateRequest.java | 14 ++++---- .../likelion/session/dto/BoardResponse.java | 12 +++---- .../session/dto/BoardUpdateRequest.java | 22 ++++++------ .../session/service/BoardService.java | 20 +++++------ src/main/resources/application.yml | 28 +++++++++++++++ .../session/SessionApplicationTests.java | 4 +-- 14 files changed, 125 insertions(+), 88 deletions(-) create mode 160000 SpringCRUDSession create mode 100644 board/src/Main.java create mode 100644 src/main/resources/application.yml diff --git a/SpringCRUDSession b/SpringCRUDSession new file mode 160000 index 0000000..a60be9f --- /dev/null +++ b/SpringCRUDSession @@ -0,0 +1 @@ +Subproject commit a60be9f25e5bbc4aed7efc88d5bfbd969cc57492 diff --git a/board/.gitignore b/board/.gitignore index 1fac4d5..13275f1 100644 --- a/board/.gitignore +++ b/board/.gitignore @@ -1,21 +1,8 @@ -.gradle -build/ -!gradle/wrapper/gradle-wrapper.jar -!**/src/main/**/build/ -!**/src/test/**/build/ -.kotlin - ### IntelliJ IDEA ### -.idea/modules.xml -.idea/jarRepositories.xml -.idea/compiler.xml -.idea/libraries/ -*.iws -*.iml -*.ipr out/ !**/src/main/**/out/ !**/src/test/**/out/ +.kotlin ### Eclipse ### .apt_generated diff --git a/board/src/Main.java b/board/src/Main.java new file mode 100644 index 0000000..24f7aa3 --- /dev/null +++ b/board/src/Main.java @@ -0,0 +1,15 @@ +//TIP 코드를 실행하려면 을(를) 누르거나 +// 에디터 여백에 있는 아이콘을 클릭하세요. +public class Main { + public static void main(String[] args) { + //TIP 캐럿을 강조 표시된 텍스트에 놓고 을(를) 누르면 + // IntelliJ IDEA이(가) 수정을 제안하는 것을 확인할 수 있습니다. + System.out.printf("Hello and welcome!"); + + for (int i = 1; i <= 5; i++) { + //TIP 을(를) 눌러 코드 디버그를 시작하세요. 1개의 중단점을 설정해 드렸습니다 + // 언제든 을(를) 눌러 중단점을 더 추가할 수 있습니다. + System.out.println("i = " + i); + } + } +} \ No newline at end of file diff --git a/board/src/main/resources/application.yml b/board/src/main/resources/application.yml index 4733b81..1ac5cf3 100644 --- a/board/src/main/resources/application.yml +++ b/board/src/main/resources/application.yml @@ -1,5 +1,5 @@ server: - port: 8080 + port: 8082 spring: application: @@ -9,7 +9,7 @@ spring: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/session?serverTimezone=Asia/Seoul&characterEncoding=UTF-8 username: root - password: yebin1448! + password: Guscjf#@4944 jpa: hibernate: diff --git a/build.gradle b/build.gradle index deca6ed..9a7e708 100644 --- a/build.gradle +++ b/build.gradle @@ -9,7 +9,7 @@ version = '0.0.1-SNAPSHOT' java { toolchain { - languageVersion = JavaLanguageVersion.of(21) + languageVersion = JavaLanguageVersion.of(26) } } @@ -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..8a26f84 100644 --- a/src/main/java/com/likelion/session/SessionApplication.java +++ b/src/main/java/com/likelion/session/SessionApplication.java @@ -1,9 +1,13 @@ package com.likelion.session; import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication;//스프링 부트 애플리케이션의 시작점(진입점) 을 나타내는 어노테이션 @SpringBootApplication +//스프링 부트 애플리케이션의 시작점(진입점) 을 나타내는 어노테이션(3개가 합쳐진 것) +//@SpringBootConfiguration 설정 클래스로 등록 (@Configuration과 동일) +//+ @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..415c919 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//REST API 컨트롤러 +@RequestMapping("/boards")//Spring MVC에서 HTTP 요청을 특정 메서드나 클래스에 매핑 +@RequiredArgsConstructor//final 또는 @NonNull 필드를 매개변수로 받는 생성자를 자동으로 생성 public class BoardController { - private final ; + private final BoardService boardService; /* 게시글 생성 @@ -32,44 +32,44 @@ public class BoardController { -> 결과 반환 -> JSON 응답 */ - @Operation( + @Operation(//API 문서에서 엔드포인트에 대한 설명을 작성할 때 사용 summary = "게시글 생성", description = "새로운 게시글을 생성합니다." ) - @ + @PostMapping//Spring MVC에서 HTTP POST 요청을 특정 메서드에 매핑 @RequestMapping의 축약형 public ResponseEntity create(@RequestBody BoardCreateRequest request) { BoardResponse response = boardService.create(request); return ResponseEntity.ok(response); } // 게시글 전체 조회 - @Operation( + @Operation(//API 문서에서 엔드포인트에 대한 설명을 작성할 때 사용 summary = "게시글 전체 조회", description = "등록된 모든 게시글을 조회합니다." ) - @ + @GetMapping//GET 요청 매핑 public ResponseEntity> findAll() { List response = boardService.findAll(); return ResponseEntity.ok(response); } // 게시글 단건 조회 - @Operation( + @Operation(//API 문서에서 엔드포인트에 대한 설명을 작성할 때 사용 summary = "게시글 단건 조회", description = "id로 특정 게시글을 조회합니다." ) - @GetMapping("/{id}") - public ResponseEntity findById(@PathVariable Long id) { + @GetMapping("/{id}")//GET 요청 매핑 + public ResponseEntity findById(@PathVariable Long id) {//URL 경로의 변수 값을 메서드 파라미터로 추출 BoardResponse response = boardService.findById(id); return ResponseEntity.ok(response); } // 게시글 수정 - @Operation( + @Operation(//API 문서에서 엔드포인트에 대한 설명을 작성할 때 사용 summary = "게시글 수정", description = "id로 특정 게시글의 제목과 내용을 수정합니다." ) - @("/{id}") + @PutMapping("/{id}")//HTTP PUT 요청을 매핑하며, 리소스를 전체 교체할 때 사용 public ResponseEntity update(@PathVariable Long id, @RequestBody BoardUpdateRequest request) { BoardResponse response = boardService.update(id, request); @@ -77,13 +77,13 @@ public ResponseEntity update(@PathVariable Long id, } // 게시글 삭제 - @Operation( + @Operation(//API 문서에서 엔드포인트에 대한 설명을 작성할 때 사용 summary = "게시글 삭제", description = "id로 특정 게시글을 삭제합니다." ) - @("/{id}") + @DeleteMapping("/{id}")//HTTP DELETE 요청을 매핑하며, 리소스를 삭제할 때 사용 public ResponseEntity delete(@PathVariable Long id) { boardService.delete(id); return ResponseEntity.noContent().build(); } -} \ No newline at end of file +} diff --git a/src/main/java/com/likelion/session/domain/Board.java b/src/main/java/com/likelion/session/domain/Board.java index cb873de..924b0be 100644 --- a/src/main/java/com/likelion/session/domain/Board.java +++ b/src/main/java/com/likelion/session/domain/Board.java @@ -10,34 +10,34 @@ @Getter // getter 메서드 자동 생성 @Entity // 해당 클래스 DB 테이블로 인식하고 관리 -@Table(name = "boards") -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@AllArgsConstructor +@Table(name = "boards")//JPA(Java Persistence API) 에서 엔티티 클래스와 데이터베이스 테이블을 매핑할 때 사용 +@NoArgsConstructor(access = AccessLevel.PROTECTED)//기본 생성자(파라미터 없는 생성자)를 자동 생성 +@AllArgsConstructor//모든 필드를 매개변수로 받는 생성자를 자동 생성 public class Board { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long ; + @Id//JPA에서 엔티티의 기본 키(Primary Key) 를 지정하는 어노테이션 + @GeneratedValue(strategy = GenerationType.IDENTITY)//JPA에서 기본 키(PK) 값을 자동으로 생성하는 전략을 지정 + private Long id; // 게시글 제목 - @Column(nullable = false, length = 100) - private String ; + @Column(nullable = false, length = 100)//JPA에서 엔티티 필드와 DB 컬럼을 매핑하고 세부 속성을 설정 + private String title; // 게시글 내용 - @Column(nullable = false, columnDefinition = "TEXT") - private String ; + @Column(nullable = false, columnDefinition = "TEXT")//JPA에서 엔티티 필드와 DB 컬럼을 매핑하고 세부 속성을 설정 + private String content; // 작성자 - @Column(nullable = false, length = 30) - private String ; + @Column(nullable = false, length = 30)//JPA에서 엔티티 필드와 DB 컬럼을 매핑하고 세부 속성을 설정 + private String writer; // 생성 시간 - @Column(nullable = false) - private LocalDateTime ; + @Column(nullable = false)//JPA에서 엔티티 필드와 DB 컬럼을 매핑하고 세부 속성을 설정 + private LocalDateTime createdAt; // 수정 시간 - @Column(nullable = false) - private LocalDateTime ; + @Column(nullable = false)//JPA에서 엔티티 필드와 DB 컬럼을 매핑하고 세부 속성을 설정 + 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 //JPA에서 엔티티가 최초로 저장(INSERT)되기 직전에 자동으로 실행되는 메서드를 지정 public void prePersist() { this.createdAt = LocalDateTime.now(); this.updatedAt = LocalDateTime.now(); } - @PreUpdate + @PreUpdate //엔티티가 수정(UPDATE)되기 직전에 자동으로 실행되는 메서드를 지정 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..7792401 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 //모든 필드의 get 메서드 자동 생성 +@Setter //모든 필드의 set 메서드 자동 생성 +@NoArgsConstructor //기본 생성자 자동 생성 +@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..b0266a9 100644 --- a/src/main/java/com/likelion/session/dto/BoardResponse.java +++ b/src/main/java/com/likelion/session/dto/BoardResponse.java @@ -1,14 +1,14 @@ package com.likelion.session.dto; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; +import lombok.AllArgsConstructor;//모든 필드를 매개변수로 받는 생성자 자동 생성 +import lombok.Builder;//빌더 패턴으로 객체 생성 가능하게 해주는 Lombok 어노테이션 +import lombok.Getter;//모든 필드의 get 메서드 자동 생성 import java.time.LocalDateTime; -@Getter -@AllArgsConstructor -@Builder +@Getter//모든 필드의 get 메서드 자동 생성 +@AllArgsConstructor//모든 필드를 매개변수로 받는 생성자 자동 생성 +@Builder//빌더 패턴으로 객체 생성 가능하게 해주는 Lombok 어노테이션 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..122df35 100644 --- a/src/main/java/com/likelion/session/dto/BoardUpdateRequest.java +++ b/src/main/java/com/likelion/session/dto/BoardUpdateRequest.java @@ -1,21 +1,21 @@ package com.likelion.session.dto; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; +import lombok.Getter;//모든 필드의 get 메서드 자동 생성 +import lombok.NoArgsConstructor;//기본 생성자 자동 생성 +import lombok.Setter;//모든 필드의 set 메서드 자동 생성 -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.Size; +import jakarta.validation.constraints.NotBlank;//null, 빈 문자열, 공백 문자열 모두 허용하지 않는 유효성 검사 어노테이션 +import jakarta.validation.constraints.Size;//문자열 길이 또는 컬렉션 크기의 범위를 제한 -@Getter -@Setter -@NoArgsConstructor +@Getter//모든 필드의 get 메서드 자동 생성 +@Setter//모든 필드의 set 메서드 자동 생성 +@NoArgsConstructor//기본 생성자 자동 생성 public class BoardUpdateRequest { - @NotBlank(message = "제목은 필수입니다.") - @Size(max = 100, message = "제목은 100자 이하로 입력해주세요.") + @NotBlank(message = "제목은 필수입니다.")//null, 빈 문자열, 공백 문자열 모두 허용하지 않는 유효성 검사 어노테이션 + @Size(max = 100, message = "제목은 100자 이하로 입력해주세요.")//문자열 길이 또는 컬렉션 크기의 범위를 제한 private String title; - @NotBlank(message = "내용은 필수입니다.") + @NotBlank(message = "내용은 필수입니다.")//null, 빈 문자열, 공백 문자열 모두 허용하지 않는 유효성 검사 어노테이션 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..01ecf86 100644 --- a/src/main/java/com/likelion/session/service/BoardService.java +++ b/src/main/java/com/likelion/session/service/BoardService.java @@ -5,20 +5,20 @@ import com.likelion.session.dto.BoardResponse; import com.likelion.session.dto.BoardUpdateRequest; import com.likelion.session.repository.BoardRepository; -import org.springframework.transaction.annotation.Transactional; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional;//메서드 또는 클래스에 트랜잭션을 적용하는 어노테이션 +import lombok.RequiredArgsConstructor;//final 필드만 매개변수로 받는 생성자를 자동 생성하는 Lombok 어노테이션 +import lombok.extern.slf4j.Slf4j;//로그를 출력하기 위한 Lombok 어노테이션 +import org.springframework.stereotype.Service;//해당 클래스가 비즈니스 로직을 처리하는 서비스 계층임을 선언하는 어노테이션 import java.util.List; -@Slf4j -@Service -@RequiredArgsConstructor -@Transactional +@Slf4j//로그를 출력하기 위한 Lombok 어노테이션 +@Service//해당 클래스가 비즈니스 로직을 처리하는 서비스 계층임을 선언하는 어노테이션 +@RequiredArgsConstructor//final 필드만 매개변수로 받는 생성자를 자동 생성하는 Lombok 어노테이션 +@Transactional//메서드 또는 클래스에 트랜잭션을 적용하는 어노테이션 public class BoardService { - private final ; + private final BoardRepository boardRepository; /* 게시글 생성 @@ -71,7 +71,7 @@ public List findAll() { - id로 게시글 조회 - 없으면 예외 발생 */ - @Transactional(readOnly = true) + @Transactional(readOnly = true)//메서드 또는 클래스에 트랜잭션을 적용하는 어노테이션 public BoardResponse findById(Long id) { Board board = boardRepository.findById(id) .orElseThrow(() -> new IllegalArgumentException("해당 게시글이 없습니다. id=" + id)); diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 0000000..1ac5cf3 --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,28 @@ +server: + port: 8082 + +spring: + application: + name: session + + datasource: + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://localhost:3306/session?serverTimezone=Asia/Seoul&characterEncoding=UTF-8 + username: root + password: Guscjf#@4944 + + jpa: + hibernate: + ddl-auto: update + show-sql: true + properties: + hibernate: + format_sql: true + + jackson: + serialization: + fail-on-empty-beans: false + +logging: + level: + org.hibernate.SQL: debug \ No newline at end of file diff --git a/src/test/java/com/likelion/session/SessionApplicationTests.java b/src/test/java/com/likelion/session/SessionApplicationTests.java index b65f4a0..7416b06 100644 --- a/src/test/java/com/likelion/session/SessionApplicationTests.java +++ b/src/test/java/com/likelion/session/SessionApplicationTests.java @@ -3,10 +3,10 @@ import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; -@SpringBootTest +@SpringBootTest//스프링 부트 애플리케이션의 시작점(진입점) 을 나타내는 어노테이션 class SessionApplicationTests { - @Test + @Test//JUnit에서 테스트 메서드임을 선언하는 어노테이션 void contextLoads() { }