프로젝트에 참고한 책: '스프링 부트와 AWS로 혼자 구현하는 웹 서비스'

1. API를 만들기 위한 3개의 클래스들

API를 만들기 위한 3개의 클래스는 다음과 같다 

 

-Request 데이터를 받을 Dto

-API 요청을 받을 Controller

-트랜잭션,도메인 기능 간의 순서를 보장하는 Service

 

Spring web Layer의 구성요소: Web Layer, Service Layer, Repository Layer, Dtos, Domain Model

실제로 비즈니스 로직을 처리하는 곳은 Service 클래스가 아니라 Domain이다. 

 

2. 등록/수정/조회 기능 만들기 

먼저 web package를 만들고 controller와 dto를 생성한다. 

 

web package PostsApiController.class
web.dto package PostsSaveRequestDto.class

 

PostsApiController: 해당 api를 통해 requestDto를 받아 service 클래스로 넘긴다.

PostsSaveRequestDto

: 클라이언트에서 request한 정보를 포함하고 있다. 

 

Entity 클래스를 response/request 클래스로 사용하면 안되고, 반드시 dto를 따로 생성해야한다. 

이유는 다음과 같다.

 

-Entity 클래스는 데이터베이스와 맞닿은 핵심 클래스(이걸 기준으로 테이블이 생성되고, 스키마가 변경됨)이기 때문에 

쉽게 변경하면 안된다. 

-그런데 response/request 클래스는 view와 맞닿은 클래스이므로 수시로 변경될 가능성이 있기 때문에 만약 entity가 dto로 사용된다면 잘못될 가능성이 높다. 

 

따라서 reponse/request dto는 entity class와는 별도로 따로 생성하자. 

 

 

자세한 코드는 다음 주소에서 확인하면 된다. 

https://github.com/heyazoo1007/bookproject/tree/master/src/main/java/com/heyazoo1007/book/web

 

 

두번째로 service.posts package를 만들고 service class를 생성한다

 

services.posts package PostsService.class

 

자세한 코드는 다음 주소에서 확인할 수 있다. 

https://github.com/heyazoo1007/bookproject/blob/master/src/main/java/com/heyazoo1007/book/service/posts/PostsService.java

 

 

3. 스프링에서 Bean을 주입하는 방법 3가지

- @Autowired

- setter

- 생성자(constructor) 

 

책에서는 @Autowired 로 주입하는 것보다, 생성자로 주입하는 것을 더 추천한다.

 

생성자로 Bean 객체를 받도록 하면 @Autowired와 동일한 효과를 볼 수 있다. 

final이 선언된 모든 필드를 인자값으로 하는 생성자를 @RequiredArgsConstructor가 생성해준다. 

 

생성자를 직접 안 쓰고 @RequiredArgsConstructor(롬복 어노테이션)을 사용한 이유

: 해당 클래스의 의존성 관계가 변경될 때마다 생성자 코드를 계속해서 수정하는 번거로움을 해결하기 위함이다. 

 

 

4. PostsApiControllerTest

 

코드는 다음 주소로 가면 확인할 수 있다. 

https://github.com/heyazoo1007/bookproject/tree/master/src/test/java/com/heyazoo1007/book/web

 

Test 관련 공부한 내용

 

//given part 

-ControllerTest에서는 따로 url을 설정해서 테스트를 수행해야한다.

그러기 위해서는 임의의 port 번호를

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)

@LocalServerPort \ private int port; 를 이용해서 생성한다. 

 

//when part 

-TestRestTemplate 사용 

//when 파트를 보면 responseEntity= restTemplate.postForEntity();를 생성한다. 

 

자세한 내용은 다음 페이지를 참고하면 된다. 

https://heyazoo1007.tistory.com/212

//then part

-assertThat(responseEntity.getStatusCode()).isEqualTo(HttpsStatus.OK);

-assertThat(responseEntity.getBody()).isGreaterThan(0L);

 

상태가 200인지 확인하고, Body의 길이가 0 이상인지 확인 한다. 

 

 

프로젝트에 참고한 책: '스프링 부트와 AWS로 혼자 구현하는 웹 서비스'

1. build.gradle에 dependencies 추가하기

 

2. domain 패키지 만들기 

 

도메인: 게시글,댓글,회원,정산,결제 등 소프트웨어에 대한 요구사항 혹은 문제영역이라고 보면 된다.

본 프로젝트에서는 도메인이 게시글이므로, Posts 클래스와 PostsRepository 인터페이스를 생성했다.

Entity class와 Repository Interface는 밀접한 관계이므로 같은 domain package에 있어야한다. 

 

3.Posts Class

Posts클래스는 실제 DB의 테이블과 매칭될 클래스이므로 @Entity(JPA 어노테이션, 테이블과 링크될 클래스임을 나타내는 어노테이션)가 클래스 명과 가장 가까워야 한다. 

나머지는 롬복 어노테이션이다. 

 

코드 상세는 다음 주소로 들어가면 볼 수 있다. 

https://github.com/heyazoo1007/bookproject/blob/master/src/main/java/com/heyazoo1007/book/domain/posts/Posts.java

 

4.PostsRepository Interface 

ibatis,Mybatis에서 DB Layer 접근자는 Dao라고 부르고, JPA에서는 Repository라고 부르며 인터페이스로 생성한다. 

JpaRepository<Entity class, Pk type>를 상속하면 기본적인 CRUD 메소드가 자동으로 생성된다. 

 

 

Post와 PostsRepository 코드는 다음 깃헙에 가면 볼 수 있다.

https://github.com/heyazoo1007/bookproject/tree/master/src/main/java/com/heyazoo1007/book/domain/posts/PostsRepository.java

 

5. PostsRepositoryTest 

오류를 줄이기 위해서는 기능 구현을 완성하면 해당 단위 기능을 테스트 하는 테스트 코드를 작성해서 정상 작동하는지 확인하는 버릇을 들여야한다. TDD도 추후에 공부 해야한다.

 

테스트 코드는 다음 페이지로 가면 볼 수 있다.(게시글저장_불러오기 test)

https://github.com/heyazoo1007/bookproject/blob/master/src/test/java/domain/posts/PostsRepositoryTest.java

 

 

앞선 게시글에서 대략적인 UI를 만들어봤지만, 프로젝트 진행과정에서 지금으로썬 구현하기 어려운 것들이 있어서 변동사항이 있어서 그것을 기록하려한다. 

 

1. 메인 

이전에는 회원가입과 로그인 기능을 자체적으로 개발하려했으나, 배보다 배꼽이 더 커질 수 있는 상황이 있어 이번 프로젝트에서는 google naver에서 로그인 정보 불러오는 방식으로 변경했다. 

 

왼쪽: 처음에 기획한 메인페이지. 오른쪽: 최종 메인페이지 

2.Bookshelf

 

변동 부분 

-왼쪽 상단에는 (사용자이름)’s bookshelf 구현하려고 했으나, 아직 사용자의 이름을 가져와서 화면에 출력을 하지 못해서 기능은 구현하지 않았다. 

 

-글 삭제 눌러서 삭제하기. ‘-‘버튼을 누르면 삭제항목을 선택하는 체크박스를 이름 왼쪽에 구현하고 싶었는데 또한 아직 기술 부족으로 구현하지 못했다. 

 

-또한 책의 완독 여부를 확인할 있는 ‘read’, ‘unread’ 아직 기술이 부족해 구현하지 못했다. 

 

 

 

3. Register 

 

 

변동 부분 

-‘+’버튼을 누르면 책을 등록하는 페이지로 이동하는데, 여기서는 이름,저자,출판사,카테고리, 후기를 입력할 있도록 했다.

-책 정보를 입력하고 ‘register’버튼을 누르면 책이 등록된다.

-후기는 다른 페이지에서 등록하려고 했으나, 개발이 복잡해져서 처음 책을 등록할 때 후기까지 등록하는 것으로 만들었다.

 

 

 

 

4. Book Review

 

책을 등록한 이름을 선택하면 책의 후기를 있는 페이지를 있다. 

 

초기 UI에 수정하는 버튼은 없지만, 책 정보를 잘못 입력했거나 변경되었을 경우에 대비해 수정 버튼도 만들었다.

update 버튼을 누르면 책을 수정할 수 있는 페이지로 이동할 수 있다.

 

 

5. Update

 

- bookshelf페이지에서 책 삭제를 못한 대신 책의 정보를 수정할 때 삭제할 수 있게 만들었다.

 

 

 

1. 기획

notion으로 읽은 것을 기록하고 있는데, 이를 참고하여 읽은 책의 정보를 기록하는 페이지를 만들기로 하였다.

-기능

  1. 로그인/회원가입
  2.  등록하기(Create)
  3.  조회(Read)
  4.  수정하기(Update)
  5.  삭제하기(Delete)

 

-API 설정

이거는 추후에 정리할 예정이다 

 

-ERD,테이블 설정 

  • User(원래는 직접 로그인 시스템 구현하려고 했으나, 구글 api 를 이용해서 로그인을 구현할 예정이다)
  • Id: 유저 아이디
  • nickName : 페이지에서 사용될 이름
  • pw: 비밀번호
  • bookShelf: 사용자의 책정보 

 

  • Book(나중에 Post로 이름 바꿈)
  • Id: 책 구별하는 id
  • author/publisher/bookTitle: 책의 기본정보
  • category: 책의 카테고리 분류하기 위해서 
  • check: 책 완독 여부 확인
  • review: 사용자가 작성하는 책 후기 
  • startDate/endDate:  책 읽기 시작한 날짜와 끝낸 날짜 

 

 

  • 한 명의 사용자는 여러권의 책을 등록 할 수 있으므로 user와 book의 관계는 1:N 관계이다 
  • 변수명은 camelCase로 작성할 예정

 

2. UI 구현

-사용툴 : adobe xd 

 

    1.  메인페이지  

도메인을 입력해 들어가면 메인페이지가 보이는데, 여기서 기능으로는 정보를 가지고 있는 bookshelf 페이지로 이동하는 버튼과, 회원가입하고 로그인이 있다. 

 

 

2. 회원가입 페이지 

사용자 아이디와 비밀번호, 닉네임을 입력하는 것을 생각하고 만들었다.

 

3. 로그인 페이지 

아이디와 비밀번호를 입력한다

 

4.  user's Bookshelf

로그인 메인에서 bookshelf 클릭하면 나오는 페이지이다. 

 

5. Register

bookshelf에서 오른쪽 '+' 버튼 눌렀을 때 나오는 페이지이다. 책의 정보인 책 이름,저자,출판사,카테고리를 입력할 수 있고, 완독여부에 따라 'Read','Unread'를 선택할 수 있다.

 

 

 

6. 특정 책 눌렀을 때 Book Review 페이지로 이동하기 

책 등록 후 책의 이름을 누르면 책의 후기를 볼 수 있는 페이지로 이동할 수 있고, 여기서 후기를 등록할 수 있다.

 

 

7. 책 후기 등록 완료 

책 후기를 작성하고 오른쪽 하단에 등록 버튼을 누르면 후기 등록이 완료되고, 작성한 후기를 볼 수 있다. 

+ Recent posts