✍️개발로그

20220820_클론코딩(항해인사이드) 2일차

Jaeyoung Kim 2022. 8. 20. 21:38
728x90

항해99 7주차, 클론코딩 주차가 시작되었고 어떤 것을 클론코딩할지 조원들과 논의하던 와중

실전 프로젝트를 앞두고 FE, BE 모두 CRUD를 반복적으로 해볼 수 있는 커뮤니티 사이트를 클론해보자는 쪽으로 얘기가 되었다.

 

다수의 국내외 커뮤니티 사이트를 살펴보았고 그중 디시인사이드가 1주일(정확히는 6일)이라는 시간동안 기능적인 부분이나 보여지는 부분에서 우리가 연습하기에 가장 좋은 사이트라 FE, BE 모두 생각하였고 항해99 게시판을 만든다는 가정 하에 본격적으로 프로젝트를 설계해 나가였다.

금주 내가 맡은 부분은 댓글, 대댓글, 좋아요(개념), 싫어요(비추) 부분이다.

 

CLOB

ERD를 설계하던 중 기존 VARCHAR 타입으로 설정하던 CONTENT를 CLOB 타입으로 설정해보자는 이야기가 나왔다.

CLOB 타입은 VARCHAR(String)타입 보다 많은 텍스트 데이터를 저장할 수 있는 데이터 타입이라고 한다.

VARCHAR
size 크기의 가변길이 문자 데이터타입  
최대크기 : 4,000B

CLOB
대용량의 텍스트 데이터를 저장하기 위한 데이터 타입
최대크키 : 4GB

이를 Spring에서 사용하기 위한 방법을 찾다가 잠깐 헤매긴하였으나 생각보다 간단하였다.

Entity 클래스쪽에서 CLOB으로 변환해주고 싶은 필드에 @Lob이라고 어노테이션만 붙여주면 되었다.

(여기서 Lob은 LargeObject라고 한다.)

    @Lob
    @Column(nullable = false)
    private String content;

매핑하는 필드가 Char나 String과 같은 문자면 CLOB, BLOB으로 자동 매핑된다고 한다.

 

JPA Auditing

content 필드를 제외하고 Comment 클래스에서 생성할 필드는 생성시간인 createdAt과 modifiedAt뿐이었다.

이를 위해서 JPA Auditing을 사용하였다.

 

Reference

 

JPA Auditing 기능이란?

JPA Auditing이란? Java에서 ORM 기술인 JPA를 사용하여 도메인을 관계형 데이터베이스 테이블에 매핑할 때 공통적으로 도메인들이 가지고 있는 필드나 컬럼들이 존재합니다. 대표적으로 생성일자, 수

webcoding-start.tistory.com

 

 

Spring Data JPA Audit기능을 활용해 Entity 생성시간 / 수정시간 자동 매핑하기

보통 시스템에 필요한 테이블을 설계하면 이력 관리 등의 목적으로 row 생성시간, 수정시간을 저장할 컬럼 두는 경우가 많습니다. JPA를 통해 해당 테이블들을 엔티티로 매핑하면 여러 테이블에

do-study.tistory.com

자주 망각하는 부분인데,
AuditingEntityListener을 사용하기 위해선 어플리케이션 구동 클래스에 @EnableJpaAuditing 을 달아줘야 한다 .  

 

ResponseEntity

지난주까지는 retrurn 값을 설정함에 있어 전체 Class를 아우르는 ResponseDto라는 Dto 클래스를 생성하여 제네릭으로 리턴 값을 설정하였었다. 하지만 코드는 내가 직접 작성한 것이 아닌 주특기 심화주차 모범답안에서 무지성으로 긁어온 것이나 다름 없었기에 나중에도 반복적으로 해당 방식으로 작업을 해야하나라는 의문과 막연한 걱정이 있었다.

그러던 와중, 금주에도 마찬가지로 return값을 설정해주어야했고 조장님께서 현업에서 사용하는 방식이라고 들으셨었다며 ResponseEntity를 사용해보는게 어떻겠냐고 말씀하셨다.

 

불필요하게 Entity Class를 추가하거나 장황한 코드를 익힐 필요도 없이 Spring Framwork가 제공하는 간편한 클래스였다.

ResponseEntity 는 헤더와 바디, 상태 코드로 구성되어 있고 http 응답을 나타낼 때 사용 한다.
Http 응답을 편하게 구성하여 보낼 때 사용 하는 클래스 이다.


ResponseEntity 는 HttpEntity( http 헤더, 바디 ) 를 상속 받았고, HttpStatus 상태 코드를 추가 하였다.
HttpEntity는 HTTP 요청, 응답을 나타내기 위한 entity로 헤더와 바디로 구성되어 있다.
return ResponseEntity.ok().body(dto);
return ResponseEntity.badRequest().body(dto);
return ResponseEntity.noContent().body(dto);

Reference

 

[ Springboot ] ResponseEntity 란

ResponseEntity 는 헤더와 바디, 상태 코드로 구성되어 있고 http 응답을 나타낼 때 사용 한다. Http 응답을 편하게 구성하여 보낼 떄 사용 하는 클래스 이다. ResponseEntity 는 HttpEntity( http 헤더, 바디 )..

goateedev.tistory.com

 

Map.of

이번에는 API 명세서를 작성함에 있어 전주 미숙했던 BE에서 작성하여 FE에 넘겨주는 방식이 아닌 처음부터 끝까지 BE와 FE가 이야기를 하며 설계하였다. 그 과정에서 return하는 방식 뿐만 아니라 return 값 또한 다르게 설정되었는데 다음과 같다.

기능 ... Request Response
댓글작성 ... {
 ”nickname”: 비회원닉네임
 ”password”: 댓글비밀번호
 ”postId” : 게시글ID,
 "content": 내용
}
HTTP STATUS 200
{
 “commentId”: 댓글ID
 “msg”: 댓글이 작성되었습니다.
}

지난주차의 경우에는 이미 ResponseDto란 클래스 내부에 success라는 메소드를 만들어 data를 뱉게 설정되어있었지만 이번주차는 ResponseEntity 클래스를 사용하기로 했기에 다른 방식으로 API 명세상의 Response를 충족시켜야했다.

처음 생각했던 방식은 아래같은 무식한 방법이었다.

    @PostMapping("api/comments")
    public ResponseEntity<?> createComment(@RequestBody CommentRequestDto commentRequestDto) {
       CommentResponseDto commentResponseDto = commentService.createComment(commentRequestDto);
        return ResponseEntity.ok().body("CommentId :" + commentResponseDto.getId());
    }

임시로 작성해두긴했어도 암만봐도 이건 아니다 싶어서 다른 방식을 빠르게 찾기 시작하였고 다르게 구현하였던 조의 방식을 알게되었다. 바로 Map 인터페이스 그 중에서  Map.of 라는 내부 인터페이스를 사용하는 방식이었다. Map.of 인터페이스는 매우 직관적으로 사용방법이 간단하였다.

Map.of(k1, v1, k2, v2, .... , k10, v10)
위와 같은 방식으로 총 10개의 key와 value의 쌍을 입력하여 사용할 수 있다.

이를 통해 코드가 훨씬 깔끔해질 수 있었다.

    @PostMapping("api/comments")
    public ResponseEntity<?> createComment(@RequestBody CommentRequestDto commentRequestDto) {
       CommentResponseDto commentResponseDto = commentService.createComment(commentRequestDto);
        return ResponseEntity.ok().body(Map.of("commentId",commentResponseDto.getId(),"msg","댓글이 작성되었습니다."));
    }
}

Reference

 

Java9 , Map.of(key, value);

https://www.amitph.com/create-hashmap-in-java/ Map.of 에는 key와 value를 최대 10개 까지 넣을 수 있는 메소드를 지원한다. 아래와 같이 map을 생성하면 된다. Map map = Map.of(1, "first", 2, "second");..

iseunghan.tistory.com

 

@RequestParam

그간 스프링 MVC 설계를 진행하며 파라미터 값을 받아올 때 @Pathvariable 혹은 @RequestBody로만 받아왔었다.

하지만 이번에 API 명세서를 작성하며 Front분들이 요청하신 URL이 기존에 써왔던 방식과 달랐다.

 

 api/comments?postId={postId} 

 

처음 스프링 MVC 구조를 배웠을 당시 @RequestParam에 대해서도 간단하게 익혔었지만 사용해보지 않았던터라 이번 기회에 한 번 코드를 작성해보며 사용법을 확실하게 익혀보고자 하였다.

 

프론트에서 요청하였던 위 URL을 처리하기위해서는 @RequestParam을 사용하여야했고 이는 파라미터의 값과 이름을 함께 전달하는 방식으로 게시판 등에서 페이지 및 검색 정보를 함께 전달하는 방식을 사용할 때 많이 사용된다고 한다.

적용법도 여태 사용해왔던 @Pathvariable과 @RequestBody 등과 크게 다르지 않았다.

@RequestParam("value") type 변수명

 api/comments?postId={postId} 
FE에서 요청한 위 URL 처리를 위해서는 URL은 ("/api/comments")
메소드의 파라미터값은 @RequestParam("postId") Long postId 로 설정해주면 되었다. 

Reference

 

@RequestParam과 @PathVariable?

컨트롤라에서 Requestparam으로 파라미터 값을 넘겨받을 때 아무 생각 없이 사용하곤 했는데, 이번 기회에 이 어노테이션에 대해 정리해 보고자 한다. 스프링에서는 컨트롤러로 사용할 클래스 상단

2ham-s.tistory.com


서로 다른 조에 속했던 인원들이 모여서 새로운 프로젝트를 본격적으로 시작하니 배우는 부분이 상당히 많았다.

잊지않고 기억하기 위해서 꾸준히 기록하는 습관을 들여보자!

728x90