[12.22] 내일배움캠프[Spring] TIL-37
1. Spring 숙련과제 완료
진행상황
- 현재 직급에 따른 권한 분류와 댓글의 작성까지 작업했었다.
Problem 등장
- 게시글 < -> 댓글 : 나는 댓글의 입장에서 게시글의 고유
BOARD_ID
를 가진다면, 요구사항을 만족시킬 수 있기 때문에 양방향 관계
설계를 하지 않았었다. 실제로 요구사항을 만족시키는데는 굳이 양방향 연관까지는 필요가 없었다.
- 하지만 게시글의 입장에서 하나의 게시글이 여러 댓글을 가지고 있는 입장이 될 수 있고, 게시글을 통해 댓글에 접근해야 하는 경우가 생길 수 있었고,
양방향 연관관계
로 설정해주었다.
양방향 연관관계
로 인해 기존에 코드에 대한 순환 오류가 여기저기서 터지기 시작했다.StackOverFlow
기존 Controller 설계 - Problem
@GetMapping("/board/list")
public List<Board> getBoardList(){
return boardService.getBoardAll();
}
Entity
자체를 반환하는 경우를 최소화 해야했다.
- 현재
Controller
는 @RestController
이다. -> View
랜더링이 아니고, Json
타입으로 반환 값을 보는 프로젝트 였기 때문이다.
- 그럼
List<Boadr>
를 Json
으로 반환해야하는데,이 때 순환참조의 오류가 발생한다.
- 사실
Entity
자체를 반환하지 않았다면 생기지 않았을 것 -> 실제로 StackOverFlow
의 오류가 터져도, H2
를 들여다 보면 정상적으로 데이터는 들어가있다.
설계 Problem에 따른 해결방안 모색
- 사실 간단한 해결 방법은 존재했다.
@JsonManagedReference , @JsonBackReference
의 어노테이션을 연관관계 주인 엔티티와 아닌 엔티티를 구별하여 넣어준다면 순환참조를 막을 수 있다.
- 하지만 반환
DTO
를 만들어 주는 방법을 선택했고, 많이들 좋다고는 하지만 아직 직접 느껴보지는 못했다.
- 결론 :
DTO
를 응답 객체를 감싸 Response
해주자!
설계 Problem에 따른 해결(Board Part)
Board Entity
자체를 지금까지 반환했었기 때문에 Comment
와 양방향 연관관계가 형성되자, 당연히 순환 참조의 오류가 발생할 수 밖에 없다.
BoardResponseDto
package com.sparta.spartaboard.dto;
import com.sparta.spartaboard.entity.Board;
import com.sparta.spartaboard.entity.Comment;
import lombok.Getter;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
@Getter
public class BoardResponseDto {
private String title;
private String username;
private String contents;
private LocalDateTime createdAt;
private LocalDateTime modifiedAt;
private List<CommentResponseDto> commentList = new ArrayList<>();
public BoardResponseDto(Board board ) {
this.title = board.getTitle();
this.username = board.getUsername();
this.contents = board.getContents();
this.createdAt = board.getCreatedAt();
this.modifiedAt = board.getModifiedAt();
for(Comment comment : board.getComments()){
commentList.add(new CommentResponseDto(comment));
}
}
}
- 사실
comment
를 List
로 넣는 부분에서 많이 애먹었다.
- 게시글이 해당 게시글에 따른 댓글
들
을 가지고 있어야하기 때문에 ..!
BoardService 수정
@Transactional
public List<BoardResponseDto> getBoardAll(){...}
@Transactional
public BoardResponseDto createBoard(BoardRequestDTO boardDto, HttpServletRequest request) {...}
@Transactional
public Optional<BoardResponseDto> findBoardById(Long id){...}
@Transactional
public BoardResponseDto update(Long id, BoardRequestDTO boardDto, HttpServletRequest request){...}
- 그냥
Entity(Boadr)
가 아닌 Dto
로 감싸서 return하여 순환참조오류를 막았다.
package com.sparta.spartaboard.dto;
import com.sparta.spartaboard.entity.Board;
import com.sparta.spartaboard.entity.Comment;
import com.sparta.spartaboard.entity.User;
import lombok.Getter;
import java.time.LocalDateTime;
@Getter
public class CommentResponseDto {
private Long id;
private String contents;
private LocalDateTime createdAt;
private LocalDateTime modifiedAt;
public CommentResponseDto(Comment comment) {
this.id = comment.getId();
this.contents = comment.getContents();
this.createdAt = comment.getCreatedAt();
this.modifiedAt = comment.getModifiedAt();
}
}
@Transactional
public CommentResponseDto addComments(Long id, CommentRequestDto requestDto, HttpServletRequest request) {...}
@Transactional
public List<CommentResponseDto> getComments(Long id, HttpServletRequest request) {...}
@Transactional
public CommentResponseDto update(Long id,CommentRequestDto commentRequestDto, HttpServletRequest request){...}
@Transactional
public ResponseMsgStatusCodeDto delete(Long id, HttpServletRequest request){...}
Problem 해결 후 동작 모습





2. Java - CodingTest
Level - 0
핸드폰 번호 암호화
- 문제 설명
1.프로그래머스 모바일은 개인정보 보호를 위해 고지서를 보낼 때 고객들의 전화번호의 일부를 가립니다.
phone_number | return |
---|
"01033334444" | "***4444" |
"027778888" | "*8888" |
class Solution {
public String solution(String phone_number) {
String last_four_num = phone_number.substring(phone_number.length()-4);
StringBuffer phoneSecretNum = new StringBuffer();
for(int i=0;i<phone_number.length()-4;i++){
phoneSecretNum.append("*");
}
phoneSecretNum.append(last_four_num);
phoneSecretNum.toString();
return phoneSecretNum.toString();
}
}
문자열 다루기 기본
- 문제 설명
1.문자열 s의 길이가 4 혹은 6이고, 숫자로만 구성돼있는지 확인해주는 함수, solution을 완성하세요. 예를 들어 s가 "a234"이면 False를 리턴하고 "1234"라면 True를 리턴하면 됩니다.
s | return |
---|
"a234" | false |
"1234" | true |
public boolean solution(String s) {
char[] res = s.toCharArray();
if(s.length()==4 || s.length()==6 ){
for(char i : res){
if(i > 'A'){
return false;
}
}
return true;
}
return false;
}
x만큼 간격
- 문제 설명
1.함수 solution은 정수 x와 자연수 n을 입력 받아, x부터 시작해 x씩 증가하는 숫자를 n개 지니는 리스트를 리턴해야 합니다. 다음 제한 조건을 보고, 조건을 만족하는 함수, solution을 완성해주세요.
x | n | answer |
---|
2 | 5 | [2,4,6,8,10] |
4 | 3 | [4,8,12] |
-4 | 2 | [-4, -8] |
class Solution {
public long[] solution(int x, int n) {
long acc = x;
long[] answer = new long[n];
for(int i=0;i<n;i++){
answer[i] = acc;
acc+=x;
}
return answer;
}
}