본문으로 바로가기

이번 시간에는 게시판의 기본적인 로직 CRUD 중 Create 에 해당하는 글쓰기 기능에 대한 서비스와 컨트롤러에 대해서

다뤄보겠습니다.

그 전에 Dto 라는 개념에 대해서 짚고 넘어 가겠습니다.

Dto는 Data Transfer Obejct의 약자로 계층간 데이터 교환을 위해 만든 파일을 뜻 합니다.

이게 무슨 뜻이냐하면 실제 데이터를 가지고 있고 DB와 직접적으로 연동되는 Entity들을 (이 게시물에선 Posts)

단순히 view 페이지에서 보여주기 위해 실제 엔티티를 넘기는건 위험하다는 소리입니다.

 

dto 객체는 View layer와 데이터를 주고받을 때 사용된다.

entity객체는 db layer와 데이터를 주고받을 때 사용된다. 

절대로 테이블과 매핑되는 Entity 클래스를 Request/ Response 클래스로 사용해서는 안됩니다
Entity 클래스는 가장 Core한 클래스라고 보시면 되는데요. 
수많은 서비스 클래스나 비지니스 로직들이 Entity 클래스를 기준으로 동작합니다. 
Entity 클래스가 변경되면 여러 클래스에 영향을 끼치게 되는 반면 Request와 Response용 DTO는 View를 위한 클래스라 정말 자주 변경이 필요합니다. 
View Layer와 DB Layer를 철저하게 역할 분리를 하는게 좋습니다.
실제로 Controller에서 결과값으로 여러 테이블을 조인해서 줘야할 경우가 빈번하기 때문에 Entity 클래스만으로 표현하기가 어려운 경우가 많습니다. 
꼭꼭 Entity 클래스와 Controller에서 쓸 DTO는 분리해서 사용하시길 바랍니다.

[출처] https://jojoldu.tistory.com/251

제가 공부하는데 도움이 됐던 기억보단 기록을 님의 블로그에서 글을 따왔습니다.

그럼 글쓰기 전용 Dto 페이지를 작성 해보겠습니다.

루트 패키지기준으로 dto - post 디렉토리를 만드시고 그 안에 PostSaveDto 라는 자바 파일을 만드시고

이와 같이 쳐주세요

여기서 있는 author title content는 실제 DB에서 값을 넣을때 필요한 변수들 입니다.

2번째 단락에 @Builder (16-21 Line) 은 나중에 설명 할 테니 지금은 그냥 넘어가주세요

마찬가지로 25-30 Line도 아래서 설명 할 예정이니 지금은 일단 넘어 가주세요.

이 PostsSaveDto는 우리가 글을 쓰면 그 양식을 받아오는 역할을 합니다.

지금 일단 이해 할 것은 사용자가 입력한 정보를 dto로 받고 entity로 저장한다 이것만 아시면 됩니다.

html의 form 태그에서 쓴 값들을 받아온다고 생각하시면 됩니다. 어떻게 받아오는지는 나중에 나오니 걱정하지마세요

 

 

루트패키지 - service -post 디렉토리를 만들고 그 안에 PostService 파일을 만들어주세요.

위의 파일이 서비스 단이라는걸 알려 주기 위해 @Service 어노테이션을 붙혀 줍시다.

그리고 서비스단에선 우리가 아까 설정했던 PostsRepository를 주입 받아주세요

@Autowired

PostsRepository postsRepository 

이렇게 해도 지장은 없지만 생성자를 통해 주입받는 것이 가장 권고되는 방식이라고 합니다

final 로 지정했으니 @RequiredArgsConstructor를 통해 주입 받아주세요

이 어노테이션은 롬복의 어노테이션으로 간단히 설명하면 final이 붙은 생성자를 만들어 줍니다.

자세한 내용은 구글에 검색 해보세요 !!

 

그리고 드디어 save 메소드가 나왔습니다.

천천히 분석해보겠습니다.

public Posts save(PostsSaveDto dto)

여기서 반환형이 Posts 인 것에 대해 알아보겠습니다.

스프링 데이터 JPA가 자동으로 생성해준 repository의 save 메소드를 실행하면

엔티티가 반환 됩니다. 

즉 return postsRepository.save(dto.toEntity()) 를 하면 Entity 객체가 반환이 된다는 뜻 입니다 여기서 Entity는 Posts 겠죠?

 

그리고 PostsSaveDto dto에 대해서 설명 드리겠습니다 이 save 함수의 매개변수 PostsSaveDto는 사용자가 폼태그를 이용해 작성한 내용을 받아옵니다.

그리고 또 하나 알아야 할 것이 있는데 JPA로 구현한 repository의 save에는 매개변수로 엔티티타입이 들어가야 합니다.

즉 postsRepository.save(Posts형) save 메소드 안에는 Posts형태가 들어가야 한다는 것이죠.

아까 Dto 설명 할 때 넘어갔던 것 기억하시죠? 

Dto안에 있는 toEntity 메소드는 그냥 일반적인 Dto를 Entity 형태로 바꿔준다고 생각하시면 되겠습니다.

 

@Transactinal 

트랜잭션은 간단히 설명하자면 오류가 났을때 롤백 하기 위함입니다.

예를들어 금융 거래를 한다고 치고 당신이 홍길동이라는 사람에게 돈을 보내야 합니다.

당신이 홍길동에게 돈을 보낼때 오류가 발생 했다고 칩시다.

그럼 당신의 계좌에서 빠져나갔던 돈이 다시 돌아와야 하고

홍길동 계좌에서 들어가야 할 돈이 들어가지 않아야 합니다.

이러한 일련의 처리과정을 처리해주는 트랜잭션에 대해서 간단히 설명해 보았고

더 궁금하신 분들은 구글링을 해보시고 따라와주시길 바랍니다.

 

다음은 컨트롤러를 작성해보겠습니다.

 

위와 마찬가지로 컨트롤러에서는 service를 @RequiredArgsConstructor로 주입 받습니다.

그리고 Rest APi로 구현하기 위해 Http 통신의 GET, POST, PUT, DELETE 법칙을 지켜서

Post방식의 요청이 들어 올 때 글쓰기를 하도록 하겠습니다.

Q: 어 그런데 들어오는 요청이 Post이거나 PUT 요청인지 아나요?? 제가 이런건 어떻게 구현 하는거죠?

A: Resttemplate를 이용하거나 기능 구현을 다 끝내고 뒤에서 나올 ajax로 요청을 처리합니다.

레스트 템플릿에 대해서는 추후, 테스트 코드를 짤 때 다뤄보도록 하겠습니다.

 

자 그럼 값이 제대로 들어가는지 확인 해보겠습니다.

해당 폴더에 만들어주세요

만약 @Runwith 어노테이션이 활성화 되지 않는다면

pom.xml에 들어가셔서 <exclusion>부분이 있다면 다 지워주세요

그 후 변경사항을 순서에 맞게 반영해주시면 됩니다.

 

자 첫번째 테스트는 postRepository.save의 반환형이 Posts 형인지 테스트 해본것 입니다.

dto의 빌더가 나왔네요. 위에서 설명한다고 하고 넘어갔던 빌더는 사실 테스트코드에서 쓰기 위함이였습니다.

사실 테스트코드를 위한 코드 작성하는 것은 너무 좋지 않은 행위입니다. 하지만 지금은 이해를 위해 작성을 한 것입니다.

 

기본적인 스프링부트의 지식이 있다고 전제하고 하므로 테스트코드에 대한 따른 설명은 안하겠습니다.

다만 단위테스트를 하지 않고 통합테스트를 한 이유는 update, delete 할 때는 실제로 resttemplate을 이용해서 요청을 해 보겠습니다. 이 이유는 나중에 다루도록 하겠습니다.

 

 

빨간부분이 아닌 위에부분은 이미 테스트를 한 것이고

이 빨간색 부분은 실제로 값이 잘 저장 되었나 확인해보는 절차입니다.

postsRepository에는 findAll()이라는 메소드 또한 있는데 이는 DB에 들어있는 모든 데이터를 꺼내오는 매소드 입니다.

역시 잘 돌아가는것을 알 수 있습니다.

 

이것으로 저장하는 과정까지 마치도록 하겠습니다.