티스토리 뷰
1. 프로젝트 세팅
build.gradle
plugins {
id 'java'
id 'org.springframework.boot' version '3.0.2'
id 'io.spring.dependency-management' version '1.1.3'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
java {
sourceCompatibility = '17'
}
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
runtimeOnly 'com.h2database:h2'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
test {
useJUnitPlatform()
}
application.yml
spring:
jpa:
show-sql: true
properties:
hibernate:
format_sql: true
defer-datasource-initialization: true
datasource:
url: jdbc:h2:mem:testdb
h2:
console:
enabled: true
data.sql
INSERT INTO article (title, content) VALUES ('제목1', '내용1')
INSERT INTO article (title, content) VALUES ('제목2', '내용2')
INSERT INTO article (title, content) VALUES ('제목3', '내용3')
엔티티 구성
domain.Article
@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED) // 기본 생성자 protected로 만들기
public class Article {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", updatable = false)
private Long id;
@Column(name = "title", nullable = false)
private String title;
@Column(name = "content", nullable = false)
private String content;
@Builder // 빌더 패턴 객체 생성
public Article(String title, String content) {
this.title = title;
this.content = content;
}
}
# 빌더 패턴의 장점
- 어느 필드에 어느 값이 매칭되는지 바로 보인다 => 코드의 가독성 증가.
@Builder 에노테이션을 사용하면 빌더 패턴을 사용하기 위한 코드를 자동으로 생성하므로 간편하게 빌더 패턴을 사용하여 객체를 만들 수 있다.
리포지토리 만들기
repository.BlogRepository
public interface BlogRepository extends JpaRepository<Article, Long> {
}
2. 블로그 글 생성 API 만들기
흐름
서비스, DTO 코드 작성
- DTO(Data Transfer Object)
dto.AddArticleRequest
- toEntity()는 빌더 패턴을 사용하여 DTO를 엔티티로 만들어주는 메서드
- 이것은 추후에 블로그에 글 추가할 때 저장할 엔티티로 변환하는 용도로 사용한다.
@Getter
@NoArgsConstructor
@AllArgsConstructor
public class AddArticleRequest {
private String title;
private String content;
public Article toEntity() {
return Article.builder()
.title(title)
.content(content)
.build();
}
/*
이 메서드는 주로 DTO(Data Transfer Object)를
엔티티로 변환하기 위한 유틸리티 메서드로 사용됩니다.
주로 데이터를 전송하거나 저장하기 위한 데이터 객체와
데이터베이스나 비즈니스 로직에서 사용되는 엔티티 객체 간의 변환을 단순화하는 데 사용됩니다.
여기서 toEntity() 메서드는 아마도 어떤 데이터 전송 객체(DTO)의 메서드
*/
}
service.BlogService
@RequiredArgsConstructor // final이 붙거나 @NotNull이 붙은 필드의 생성자 추가
@Service
public class BlogService {
private final BlogRepository blogRepository;
// AddArticleRequest를 사용하여 새 게시물을 생성하고,
// 지정된 사용자 이름으로 게시물을 저장
public Article save(AddArticleRequest request, String username) {
return blogRepository.save(request.toEntity(username));
}
}
컨트롤러 코드 작성
여기에서는 /api/articles에 POST 요청이 오면 @PostMapping을 이용해 요청을 매핑한 뒤,블로그 글을 생성하는 BlogService의 save() 메서드를 호출한 뒤,생성된 블로그 글을 반환하는 작업을 할 addArticleO 메서드를 작성할 예정.
BlogApiController
@RequiredArgsConstructor
@RestController // HTTP Response Body에 객체 데이터를 JSON 형식으로 반환하는 컨트롤러
public class BlogApiController {
private final BlogService blogService;
@PostMapping("/api/articles")
//요청 본문 값 매핑
// HTTP POST 요청을 처리하여 블로그 글을 추가.
public ResponseEntity<Article> addArticle(@RequestBody AddArticleRequest request, Principal principal) {
Article savedArticle = blogService.save(request, principal.getName());
// 요청한 자원이 성공적으로 생성되었으며 저장된 블로그 글 정보를 응답 객체에 담아 전송
return ResponseEntity.status(HttpStatus.CREATED)
.body(savedArticle);
}
}
Postman으로 테스트
테스트 코드 작성
BlogApiControllerTest.java
addArticle() 메서드 테스트 개요
@SpringBootTest
@AutoConfigureMockMvc
class BlogApiControllerTest {
@Autowired
protected MockMvc mockMvc;
@Autowired
protected ObjectMapper objectMapper;
@Autowired
private WebApplicationContext context;
@Autowired
BlogRepository blogRepository;
@BeforeEach
public void mockMvcSetUp() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(context)
.build();
blogRepository.deleteAll();
}
@DisplayName("블로그 글 추가에 성공한다.")
@Test
public void addArticle() throws Exception {
// given
final String url = "/api/articles";
final String title = "title";
final String content = "content";
final AddArticleRequest userRequest = new AddArticleRequest(title, content);
// 객체 JSON으로 직럴화
final String requestBody = objectMapper.writeValueAsString(userRequest);
// when
// 설정한 내용을 바탕으로 요청 전송
ResultActions result = mockMvc.perform(post(url)
.contentType(MediaType.APPLICATION_JSON_VALUE)
.content(requestBody));
// then
result.andExpect(status().isCreated());
List<Article> articles = blogRepository.findAll();
assertThat(articles.size()).isEqualTo(1); // 크기가 1 인지 검증
assertThat(articles.get(0).getTitle()).isEqualTo(title);
assertThat(articles.get(0).getContent()).isEqualTo(content);
}
}
assertThat 메서드 예시
코드 | 의미 |
assertThat(articles5ize()).isEqualTo(1); | 블로그 글 크기가 1이어야 한다. |
assertThat(articles.size()).isGreaterThan(2); | 블로그 글 크기가 2보다 커야 한다. |
assertThat(articles.size()).isLessThan(5); | 블로그 글 크기가 5보다 작아야 한다. |
assertThat(articles.size( )).isZero(); | 블로그 글 크기가 0이어야 한다. |
assertThat(article.title()).isEqualTo("제목"); | 블로그 글의 title 값이 "제목"이어야 한다. |
assertThat(article.title()).isNotEmpty(); | 블로그 글의 title값이 비어 있지 않아야 한다. |
assertThat(article.title()).contains("제"); | 블로그 글의 title 값이 "제"를 포함해야 한다. |
# 직렬화와 역직렬화
728x90
반응형
'[개발] - Spring > [개발예제] - SpringBoot - 블로그 만들기' 카테고리의 다른 글
[사전 지식] 타임리프 (0) | 2023.10.14 |
---|---|
블로그 글 삭제 API (1) | 2023.10.14 |
블로그 글 수정 API (0) | 2023.10.13 |
블로그 글 (목록/단일) 조회 API (0) | 2023.10.13 |
API와 REST API (0) | 2023.10.11 |
Comments