Spring boot

[toyProject] 게시물 사이트 Part 1

코앤미 2023. 1. 10. 22:25

http://13.125.105.236/

위 사이트 개발에 대한 정리글입니다. (AWS 배포가 중단되면 접속이 제한될 수 있습니다)

 

https://github.com/shyswy/Community-Site

 

GitHub - shyswy/Community-Site: Simple community Site

Simple community Site. Contribute to shyswy/Community-Site development by creating an account on GitHub.

github.com

위 링크는 프로젝트 리포지토리입니다. README를 자세히 작성했으니 참고하시면 됩니다.

 

 

DTO: 각 계층간 정보 전달시 필요한 정보만 담아 전달. 

Ex: BoardDTO: 게시물(Board)에서 필요한 정보 모음. ( 게시물 내용+ 작성자 정보+ replyCount) 

 

Html: 컨트롤러에게 어떠한 정보를 전달받을 때, DTO로 받는다. ( 엔티티를 주는건 너무 무겁다. 

필요한 정보만 담은 DTO 타입으로 전받받는다.) 

 

Controller: 

- front가 요청한, 또는 필요한 정보를 DTO로 전송 

- Htmlfront에서 받은 정보기반 적정한 Service의 메소드 사용 

 

Service : Serviceimpl의 기본적인 틀( 메소드, 변수 선언 등)  

+ 가끔 Dto TO Entity 메소드를 작성하기도  

( default 리턴 타입 func() {} ; >> 이렇게 default 통해 interface에서도 함수 정의 가능해졌다. 

ServiceImpl: 실제 Service 기능 구현됨.  여기서 직접적으로 Repositorysave() 등을 수행하려면, 

DTO 타입이 아닌, Entity로 다시 변경해줘야하기에 DtoToEntity 메소드를 사용해서 바꿔줘야한다. 

Service 인터페이스를 사용? >> 불변성을 위해. 대략적인 틀이 바뀌지 않는 기점을 세운다. 

해당 틀만 유지한채, 자유롭게 변경해서 사용할 수 도 있다. 

Ex: 굼바 인터페이스 >>  가시 굼바, 일반 굼바, 굼바  …. 다양한 인스턴스 형성하되, 

굼바라는 공통된 특성은 유지한다. 

 

 

 

Repository: 정보를 영속적으로 저장. 보통 JPARepository 상속받는데,  

여기서 기본적인 Query 메소드들을 사용가능하고, @Query로 새롭게 쿼리 생성가능 

 >> DB에서 어떠한 정보를 찾아오기  

 

Or 상위 계층에 선언된 save, delete등을 사용해서 DB Modify 가능 

Save: repository.save(Entity) >> 해당 Entity 해당 Repository( DB 테이블) 저장. 

update 

Entity.changeTitle(~~~~~)     // 해당 Entity의 특정 파트를 변경. (seter과 유사하게, ) 

Repository.save(Entity) // 변경사항 저장. 

Delete 

Repository.deletebyId(Id); 등으로 특정 entity 제거 가능. 

보통 특정 엔티티를 db에 저장하는 register의 경우,  

Html> 특정 입력정보 DTO 전송 > ControllerDTO 받아서 Service 

ServiceImpl: ServiceDTO to Entity 함수를 통해 엔티티로 변환 후, save. 

 

 

P3 : 다대일 관계 : Board  

 

 

Member   :   board   :     replay 

1 : :  

 

@ManytoOne을 통해   다수 쪽이  One 쪽의 객체를 가지지만,  

@OnetoMany  

List<>~~~ 이런식으로 One 쪽이 Many에 대한 객체를 생성 x 하여 구현함을 가정. 

>> 그럼 One쪽에서 Many의 객체를 참조하고 싶다면? 

>>JPQL ( @Query ) 에서 

*주의   Board 엔티티 객체를 생성시, bno,memberemail은 필수 조건 

(bno= 자신의 PK,  member(writer) email: F.K 조건. >> 생성시 해당 field값으로 적절한 member객체와 join 

 

BoardRepository 영역에서 만약 자신과 

Board : reply 

 1   대    

관계인 reply 가져오고 싶다면 

Join on 을 통해서. 

 

 

 

 

사용예시. 

 

 

 

 

Lazy: 그때그때 필요한 것만 join (권장) 

Eager: 완벽하게 모든 연관 관계에 대하여 join, 통째로 가져온다. 

 

Lazy는 테이블을 1개씩 뽑아올 때 좋다. 복잡한 연관관계가 잡혀 있다면, Eager한번에 쭉 가져오는 것이 좋은 경우도 존재한다.  

>> 기본적으론 Lazy, 특수한 상황에서 적절히 Eager  

 

Ex: 

@ManyToOne(fetch=FetchType.LAZY)//Lazy" private Member writer; 

>> @ManyToOne ( fetch 타입) 

Private Member writer >>> Many 쪽에서 One의 인스턴스를 보유하고, 이 인스턴스를 통해 join 한다.  

 

주의 사항! >> 내가 필요한 정보가 제대 fetch 안될 수 도 있다. 

 

 

WriterBoard에 존재하는 Member의 객체. 

BoardMembermany To one 구조로, board(게시글) writer(작성자) 정보를 가져오려 하지만, 

Lazy로 인해 아직 fetch 되지 않는 문제점 발생 >> @Transactional 을 사용해서 한 덩어리로! 

 

 

 

JavaObject 타입: 모든 클래스의 부모가 되는 자바의 최상위 부모 클래스. 모든 클래스를 사용할 수 있다. 

 

Ex:  getBoardWithWriter가 해당하는 모든 엔티티 객체들을 리턴 할 때. 

 

Select Board , Writer(member 클래스) 

>> board, member의 모든 원소들 리턴. 

일단 Object 타입으로 받고 

 

 

Object 배열로 타입 변환( 모든 타입 사용가능)  

>> Object 배열안Object들에 Arrays.toString() 을 통해 Object > string으로 바꿔주자. 

 

 

Board, Member 클래스에 @ToString 으로 모든 정보들을 Arrays.toString() 을 통해 변경가능하게 설정했다. 

Member < Board < Reply 구조에서, Board( 게시글) 이 연관된 정보 가져오게 만들기 

 

Ex: 어떠한 board(게시글) 목록을 만드는데, 각 게시글 마다 그 게시글을 작성한 

Writer(Member) 와 그 게시물에 달린 reply 수를 구해서 목록에 저장할 때. 

목록>> Pageable 사용! 

 

목표: 

각 게시물마다 b(해당하는 게시물) writer, 그리고 객체 b 보유한 Reply 객체들의 수를 리턴. 

>> Board가 중심, Board 통해 연관된 writer( 객체 보유)  Reply(객체 미 보유) 가져와야 한다. 

>> writer는 보유한 객체를 가져오면 되고, Replyjoin Reply r on r.board= b 이런식으로 

자신을 보유한 reply 매칭해서 찾으면 된다. 

 

B 보유한 reply 객체, logical하게는 b에 달린 reply >> group by 통해 수를 계산. 

+ 

Pageable 객체로, 일정한 size, 정렬 순서 등등을 객체로 받아 처리하게 

>> count 쿼리가 암시적으로 사용되기에 countQuery 정의. 

 

Page<Object[]> :  Object[] 담은 객체. 

Pageable 객체가 담은 시작 페이지, 페이지 size, 정렬순서 에 기반하여 select 된 정보들을 

페이지 단위로 리턴해준다. 

Object[] >> select된 정보들이 저장되어있다. 이 경우, Board, Member, Long 3가지 타입이 select되는데, 이 정보가 Object[]에 들어가는 것. 

Object[0] >> 선택된 Board 객체 

Object[1] >> 선택된 writer 

Object[2] >> 선택된 ReplyCount 

>> 나중에 사용할 때, type Case로 적절한 타입으로 변환해서 사용. 

 

Pageable 사용법.  

 

>> 한 목록에 10개의 Board 객체( 게시물) 

 

 

@Autowired: 생성자 주입 방식( setter 주입 등보다 이점이 많다)  

>> @RequiredArgConstruct(@Data에 포함) 어노테이션을 쓰면 일일이 @Autowired할 필요 없다. 

 

 

생성자 주입: 인스턴스 생성시 최초 1번만 불려짐. >> 불변! 

 

Setter 주입: setter불려질 때마다 변경 가능성 > bad! 

 

 

>> Entity 타입, PK 타입( gno, bno 등등)  

>> save(Entity ) 에서 Entity 정의하는 등에서 사용