Korea_sleep_Tech_springBoot/src/main/java/com/example/korea_sleepTech_springboot at main · seoyoonchoi/Korea_sleep_Tech_springB
Contribute to seoyoonchoi/Korea_sleep_Tech_springBoot development by creating an account on GitHub.
github.com
실제 코드를 더 확인하고 싶다면 위 링크를 통해서 확인할 수 있다.
📁 프로젝트 구조
korea_sleepTech_springboot/
├── common/
│ └── ApiMappingPattern.java
├── controller/
│ └── BookController.java
├── dto/
│ ├── request/
│ │ ├── BookCreateRequestDto.java
│ │ └── BookUpdateRequestDto.java
│ └── response/
│ └── BookResponseDto.java
├── entity/
│ ├── C_Book.java
│ └── C_Category.java
├── repository/
│ └── BookRepository.java
├── service/
│ └── BookService.java
Entity 구성 - C_Book & C_Category
@Entity
@Table(name = "book")
public class C_Book {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false, length = 50)
private String writer;
@Column(nullable = false, length = 100)
private String title;
@Column(nullable = false, length = 500)
private String content;
@Enumerated(EnumType.STRING)
@Column(nullable = false)
private C_Category category;
}
public enum C_Category {
NOVEL, ESSAY, POEM, MAGAZINE
}
ENUM 사용 이유
- 고정된 선택지를 코드 수준에서 제한 가능 (컴파일 타임에서 오류 감지)
- DB에 저장될 땐 VARCHAR, Java 코드에선 타입 안정성 보장
- 프리미티브 String 필드로 처리할 경우 오타나 정합성 오류 위험이 높음 → ENUM은 이를 예방
DTO 계층 - 요청과 응답 분리
public class BookCreateRequestDto {
private String writer;
private String title;
private String content;
private C_Category category;
}
DTO를 통해 외부 요청에 대한 유효성 처리, 내부 도메인 객체와의 결합 최소화, 역직렬화/직렬화의 명확한 경계 설정이 가능하다.
- CreateRequestDto: 클라이언트가 책을 등록할 때 사용하는 요청 데이터
- UpdateRequestDto: 책 수정 시 사용. 전체 데이터가 아닌 수정 가능한 항목만 분리
- ResponseDto: 클라이언트에게 반환할 데이터. 민감하거나 불필요한 정보는 제외
Service 계층 - 핵심 비즈니스 로직
public ResponseDto<BookResponseDto> createBook(BookCreateRequestDto requestDto) {
C_Book newBook = new C_Book(null, ..., ...);
...
return ResponseDto.setSuccess("책 등록 완료", bookDto);
}
중요한 설계 포인트
- C_Book 객체 생성 시 null ID → JPA가 자동으로 ID 부여
- DTO → Entity → Repository.save() → Entity → DTO → Response 구조
- Service 계층에서는 Controller와 Repository의 중간 다리 역할을 하며, 핵심 도메인 처리 로직을 담당
검색 기능 예시
public ResponseDto<List<BookResponseDto>> getBooksByTitleContaining(String keyword) {
List<C_Book> result = bookRepository.findByTitleContaining(keyword);
...
}
- findByTitleContaining: Spring Data JPA가 제공하는 메서드 이름 기반 쿼리 생성 기능
- Stream + map(): Entity 리스트 → ResponseDto 리스트 변환
Controller - RESTful API 설계
@RequestMapping("/api/v1/user/books")
@RestController
public class BookController {
...
}
HTTP Method 매핑 구조
- POST /books: 책 등록
- GET /books: 전체 책 목록 조회
- GET /books/{id}: 단일 책 조회
- PUT /books/{id}: 책 내용 + 카테고리 수정
- DELETE /books/{id}: 책 삭제
🔍 검색 API
- GET /books/search/title?keyword=키워드
- GET /books/category/{category}
- GET /books/search/category-writer?writer=xxx&category=yyy
@RequestParam vs @PathVariable 구분의 기준
| 유형 | 목적 | 예시 |
| @PathVariable | 고정된 리소스를 식별 | /category/NOVEL |
| @RequestParam | 필터링/검색 조건 | /search/title?keyword=자바 |
'웹개발 > SpringBoot' 카테고리의 다른 글
| 보안 인증과 권한 시스템 - 1. Entity (1) | 2025.06.02 |
|---|---|
| Springboot로 게시판(Post&Comment)만들기 - 두 테이블 연결 (0) | 2025.06.01 |
| Spring Boot + MySQL로 구현한 Student CRUD (1) | 2025.05.30 |
| Email 인증 구현 JavaMailSender 오류 해결 (0) | 2025.05.29 |
| Spring WebFlux의 개념과 구조적 특징 (1) | 2025.05.29 |