코드 훔쳐보는 변태 코더
춤 좋아하는 백엔드 개발자(였으면 좋겠다)
국비지원교육 (5)
23-01-20~23 TIL

오늘 진행한 것들 🤔

  • 토이프로젝트 진행
    • 캐릭터 상세정보 조회 뷰 구현
    • 캐릭터 버프강화 상세조회 로직 구현
      • 버퍼일시에 장비에 버퍼관련 버프강화 옵션이 붙기때문에, 장비까지 조회하여 수치를 가져오도록 구현
    • 게시판과 연동하여 게시판에서 언급이 몇번이 되었는지 조회하는 로직 구현
    • 캐릭터 장비 상세조회 뷰 구현 (모달창으로 상세 옵션을 조회가능하도록 구현)
    • 계정과 모험단 연동을 위한 인증기능 구현
      • 랜덤한 직업과 닉네임을 부여한 후 , 해당 캐릭터가 등록을 원하는 모험단 소속으로 생성되었는지 체크 후 등록하도록 구현

사이트에서 검색되어 디비에 저장된 캐릭터들을 기반으로 명성기준 랭킹도 조회가 가능하다.
캐릭터 장비를 클릭하면 상세 정보 조회가 가능하다. (장비별로 성장옵션이 다른 커스텀 장비가 존재하고, 추후에 데미지 계산을 위해서 장비 옵션을 참고해야할 순간이 올 수 있다고 판단하여 추가하였다.)
장착 아바타 혹은 능력치 등등 해당 게임사에서 제공해주는 데이터중 핵심 데이터는 대부분 가져와서 출력할 수 있도록 구현했다.
게시글에서 캐릭터를 언급하였을때
캐릭터 상세조회 페이지에서 게시글에서 몇번 언급되었는지 확인이 가능하다.
버퍼의 경우 해당 옵션처럼 버퍼전용옵션으로 핵심 버프 스킬을 강화시켜주는 옵션이 존재한다.
신화 아이템의 경우 현 시즌에서는 거의 착용되지 않으나, 정확한 데이터 검증을 위해 신화 아이템의 경우와 신화아이템이 아닌 현 시즌 에픽아이템일 경우 두 가지 수 모두 챙겨서 버프스킬 레벨과 수치를 변경해주었다.
조회를 위한 json 데이터가 값이 일정하게 들어오는것이 거의 없었다. 따라서 최대한 핵심 키워드에 맞춰서 값을 가져오고, 해당 값이 있는 value를 가져와야했기때문에 하드코딩이 불가피했다.
흑흑.
모험단 인증을 위해서 캐릭터를 검색하고 등록하기 전 모습
랜덤으로 문자열과 현재 디비상 존재하는 캐릭터들 사이 랜덤한 직업이름을 가져와서 인증하도록 구현했다.
인증이 완료되면 디비 내에 존재하는 같은 모험단 이름을 가진 캐릭터들이 해당 계정으로 귀속되고 다른 계정에서는 해당 캐릭터들이 소속된 모험단을 등록할 수 없게된다.

 

오늘 겪었던 문제 🤔

  • 문제라기보다는 고민거리가 있었다.
    • 해당 캐릭터의 레이드 데미지를 예측하기 위해선 스킬 계수(퍼센트 데미지) 정보가 필요한데, 게임사에서 제공해주는 데이터에서는 일정한 정보를 가진 데이터가 존재하지 않았다.
    • 예를 들면 A스킬의 옵션 설명 : ~~~공격 12타 {value1} x 12 \n ~~범위 {value2} px  이런식으로 데이터가 불규칙하게 되어있었다.
    • 해당 게임사가 그렇게 데이터를 관리한다면 곧 그 게임사에서도 어떠한 알고리즘? 로직? 을 구현해 최종 스킬 데미지를 계산이 가능할텐데 , 도저히 내 머릿속에서는 방법이 떠오르지 않았다.
      • 첫번째 방법으로는 스킬 데미지 설명 옵션을 가져온 후 , 핵심 키워드 (데미지, 공격, 스킬 등) 가 담겨있는 문자열만 뽑아서 value를 더하거나 곱해 계산하려고 했었다.
        • 해당 방법은 고정된 곱셈 수 , px(범위) 등등 여러 문제가 있어서 포기
      • 해당된 키워드중 데미지와 관련없는 키워드를 모두 제거 후 value 더하기
        • 해당 방법 또한 마찬가지로 최종 퍼센트가 타 사이트와 맞지 않았다.
    • 방법은 뭐가 있을까 ..? 다른 계수를 정리해놓은 사이트에서 일일히 데이터를 가져와서 해결하기엔 비효율적이다.
    • 마찬가지로 버프력 또한 내가 지금 해당 게임을 하지 않고있으니 계산방법을 전혀 몰라서.. 일단 1차적인 방법으로 나중에 도움이 될 수 있도록 캐릭터를 조회할때 착용 장비의 상세 정보도 가져오도록 변경했다.
      • 장비에 보면 고정적으로 스킬 데미지 퍼센트를 증가해주는 옵션이 있거나, 버프스킬의 스텟이나 공격력 증가 옵션을 강화시켜주는 옵션이 존재했기때문에, 해당 옵션으로 총 증가 스텟/퍼센트를 가공해서 버프력을 계산하거나 데미지를 계산하도록 하면 될 것 같았다.
      • 최적의 방안은 아니지만, 해당 문제를 해결하기 위해서 한단계 더 나아갔다! 라고 생각하고있다 :)

오늘 해결한 오류 🤔

 

오늘의 배운점🤔

  • JPA의 @SqlDelete 기능과 @Where 을 알게되었다.
    • 첫 프로젝트를 진행할때, 삭제 기능을 단순히 db상에 데이터를 남기고 컬럼하나의 값만 바꾸는 soft delete 가 아닌 , hard delete로 진행을 했었고, 추후에 soft delete 로만 바꿨는데, 이때 jpa에서 제공해주는 메소드를 사용하지 않고, setter로 일일히 자식객체까지 컬럼값을 변경해주었었다.
    • @SqlDelete 어노테이션으로 간단히 Update 쿼리문을 실행해 자식객체까지 cascade 설정을 해주면 알아서 컬럼값을 변경해준다.
    • +@ 로 deletedAt 변수를 선언해 추후에 일정 기간이 지난 데이터는 완전히 삭제가 가능하도록 건수를 남겨두었다. (관리자 페이지에서 구현을 하거나 자동으로 처리가 가능한 기능을 활용하면 좋을거같은데, 아직 배운게 없어서 모르겠다. 고민을 많이 해봐야겠다 :)
    • @Where 같은 경우엔 데이터를 불러올때 설정한 값들로만 불러올수있도록 (예를들어 삭제가 false인 데이터만) 설정할 수 있으나, 현재 프로젝트 같은 경우엔 회원의 게시글이나 댓글 기록이 삭제된 게시글,댓글도 확인이 가능해야했기 때문에 Where 어노테이션을 사용하면 예외가 발생했었다. 따라서 큰 변경점 없이 SqlDelete 어노테이션만 사용하고 Where 은 따로 사용하지 않았다.
  • RestApi 에 대해서 한번 더 공부해보았다.
    • 현재 진행하는 프로젝트에 컨트롤러와 맵핑되어있는 uri들이 모두 엉망이라는것을 알게되었다.
    • 아직 자세하게 공부하진 못했지만, rest api 의 정해진 규약? 에 맞춰서 uri들을 모두 수정해주었다.
    • 특히 어떠한 자원이 담겨져있는 (게시판,캐릭터,유저 등등) 곳에는 구분자를 써서 복수로 표현해주는 (characters, articles, users) 같은 규칙을 다 갖고있도록 변경해주었다.
    • 대문자를 쓰지 않는것과 중간을 구분해줄때 '-' 를 사용해주는 것 등 여러가지를 신경써서 수정해주었다.

화이팅~

 

남은 소소한 목표

-> 캐릭터 랭킹 페이지 구현 (직업별로 명성, 게시판에서 언급된 횟수, 혹은 전체 캐릭터 중 몇순위인지 등등)

-> 모험단 등록 관련 특혜 (개인 프로필 아이콘 모험단 등록 캐릭터들중 골라서 변경하고, 특별한 모험단 등록 아이콘 부여)

-> 모험단 페이지 (캐릭터 타임라인 혹은 모험단 전체 타임라인)

-> 관리자 페이지 (공지사항 등록 및 시간이 지난 삭제 게시글,댓글 삭제처리 등등 )

-> 캐릭터 데미지/버프력 산출 공식 알아내기

-> 데이터 가져올때 예외처리 (1초 안에 가져올 수 있는 데이터 수가 초과했을때 스레드 슬립 등)

 

 

'TIL' 카테고리의 다른 글

23-01-29 TIL  (0) 2023.01.30
23-01-25~26 TIL  (0) 2023.01.26
23-01-19 TIL 토이 프로젝트(게임 랭킹전적 조회 커뮤니티) 중간점검  (0) 2023.01.19
23-01-17~18 TIL  (0) 2023.01.19
23-01-16 TIL  (0) 2023.01.17
  Comments,     Trackbacks
23-01-19 TIL 토이 프로젝트(게임 랭킹전적 조회 커뮤니티) 중간점검

오늘 진행한 것들 🤔

  • 토이프로젝트
    • 마이페이지 활동내역 뷰 수정
    • 마이페이지 활동내역 조건별 정렬 기능 구현
    • 마이페이지 활동내역 페이지네이션 구현
    • 마이페이지 알림 기능 추가
      • 내가 아닌 다른사람이 내 게시글과 댓글에 좋아요 , 좋아요 취소 혹은 댓글 달기, 혹은 글이 삭제되어 내 댓글까지 삭제되었을때 알림을 남기도록 구현함

활동 내역, 삭제되면 빨간색으로 표시
댓글 활동 내역, 마찬가지로 삭제되었을때는 링크가 걸리지 않는다.
미리보기는 불가능한 활동알람. 클릭시 해당 게시글로 이동이 가능하다.
디테일하게 정렬이 가능하다. 페이징도 가능하다 굿!

이제 정말 본격적인 외부 데이터를 활용한 통계 기능을 구현하기 전 커뮤니티의 모든 기능을 구현했다.

 

오늘 겪었던 문제 🤔

  • 부모 객체에 자식 객체를 집어넣을때 어떤건 따로 저장하지 않아도 영속성이 전이되어 같이 저장되는 반면에 어떤건 안되는 현상
    • 저장이 되었다고 로그가 출력이 되지만 디비에 들어온 데이터는 존재하지 않는다. (임시방편으로 저장후 집합에 집어넣는것으로 해결)

오늘의 고민거리 🤔

  • 현재 프로젝트에서의 비동기 처리, 과연 필요할까?
    • 최악의 경우, 한페이지의 검색결과당 10번의 추가적인 API 조회가 필요하다.
    • 만약 9명이상의 사용자가 한번에 검색을 같이할땐? (API리밋 오류 발생)
      • 해당 에러에대한 예외처리를 진행 (스레드 1초 슬립?)
    • 한 캐릭터의 세부사항을 조회할때 페이지를 이동하여 각각의 탭마다 정보를 추가적으로 가져온다. / 한번에 가져와서 css로 숨긴다.
      • 만약 필요한 정보만 보고싶은데 불필요하게 모든 세부정보를 조회해버린다면?
      • 마찬가지로 API 리밋 오류 발생 가능.
      • 최적의 상황은 SPA (싱글페이지 어플리케이션) 이지만.. 지금 상황에서는 불가능하다. (지식부족)
      • 타임리프를 사용하고있지만, 제이쿼리로 계속 불편하게 ajax 를 통해 데이터를 긁어와서 태그를 갖다 붙이는 일이 맞는걸까 ? (고려해봐야하는부분.)
  • 사용자 입장에서 웹페이지에 오래 남아있을 수 있는 방법은 뭐가 있을까?\
  • 에러페이지로의 잦은 이동을 지양하기
    • 많은 데이터 제공하기 (다양한 통계 )
      • 직업별 분포도 (네오플 API 캐릭터 기본정보 조회 활용)
      • 직업별 명성 분포도 (네오플 API 능력치 세부 조회 활용)
      • 직업별 레이드 클리어 분포도 (네오플 API 타임라인 코드 활용)
      • 직업별 예상 최신 레이드 데미지 랭킹 (네오플 API 스킬정보/장비/능력치/버프강화 세부정보 조회 활용)
      • 캐릭별 원하는 스펙으로 맞췄을시에 예상 데미지 (네오플 API 스킬정보/장비/능력치/버프강화 세부정보 조회 활용)
      • 다양한 커뮤니티 (보기좋은 인터페이스 제공)
    • 메인페이지에는 ? 
      • 캐릭터 데미지 랭킹
      • 게시판
      • 홈페이지상 등록된 캐릭터들중 한번이라도 검색된적 있는 캐릭터들의 최신 레이드 클리어 현황 

오늘 해결한 오류 🤔

  • 조건문을 잘못 활용하여 원하는 결과값이 리턴되지 않았던 오류

  • 스위치문은 가독성이 좋지않아서 if문을 활용하라던 말이 생각이 났다.
  • 그런가....................................? 이렇게 고치긴 했지만 딱히 그 의견에 찬성하진 않는 입장이다.

 

오늘의 배운점🤔

  • 새로운 기능을 구현했습니다.
    • 사용자 알림 기능을 구현했습니다. 인스타그램에서 쉽게 볼 수 있었던.. 생각보다 어렵진 않았습니다.

 

'TIL' 카테고리의 다른 글

23-01-25~26 TIL  (0) 2023.01.26
23-01-20~23 TIL  (0) 2023.01.25
23-01-17~18 TIL  (0) 2023.01.19
23-01-16 TIL  (0) 2023.01.17
23-01-15 TIL  (2) 2023.01.16
  Comments,     Trackbacks
23-01-12 TIL

오늘 진행한 것들 🤔

  •  토이프로젝트
    • 스프링부트 버전 변경과 그에따른 그래들 빌드 내용 수정
    • 캐릭터 , 유저 계정 관련 테스트 코드 작성
    • 게시판, 댓글 도메인 설계
    • 게시판 핵심 비즈니스 로직 설계 및 테스트 실행
    • 더 세세한 검색과 출력을 위한 쿼리문 작성
    • 게시판 리스트 뷰 구현
    •  

처음으로 jpa를 사용하면서 쿼리문을 직접 작성해보았다.
기본적인 뷰를 구현했다.
나쁘지않게 연관관계를 맺은것 같다.

오늘 겪었던 문제 🤔

  • 딱히?

오늘 해결한 오류 🤔

  • 흠..딱히..?

오늘의 배운점🤔

  • 오늘은 전체적으로 별 일 없이 흘러갔습니다.
    • 전보다 엔티티 설계에 대한 이해도가 조금 더 늘은것 같습니다.
    • 오늘의 설계는 확실히 전보다 빨랐고, 알찼습니다 :)
    • 처음으로 jpa를 이용하면서 쿼리문을 작성했습니다.
      • 기존에 막무가내로 메소드 이름만 무작정 지어서 이용했을땐 디테일한 결과를 가져오기도 힘들었고, 2차 가공이 필요했던 반면, 직접 쿼리를 짜서 활용하니 훨씬 편리했습니다. 

 

내일도 화이팅! 

'TIL' 카테고리의 다른 글

23-01-14 TIL  (0) 2023.01.15
23-01-13 TIL  (0) 2023.01.14
23-01-10 TIL  (0) 2023.01.10
23-01-09 TIL  (0) 2023.01.09
23-01-07 TIL  (0) 2023.01.08
  Comments,     Trackbacks
22-12-29 TIL

오늘 진행한 것들 🤔

  • 알고리즘 풀데이
 

백준 11726번 2xn 타일링 (자바) 풀이

시간 제한메모리 제한제출정답맞힌 사람정답 비율 1 초 256 MB 128307 48836 36026 35.916% 문제 2×n 크기의 직사각형을 1×2, 2×1 타일로 채우는 방법의 수를 구하는 프로그램을 작성하시오. 아래 그림은 2

codinghentai.tistory.com

 

 

백준 9095번 1,2,3 더하기 (자바) 풀이

시간 제한메모리 제한제출정답맞힌 사람정답 비율 1 초 (추가 시간 없음) 512 MB 91254 59805 40667 63.913% 문제 정수 4를 1, 2, 3의 합으로 나타내는 방법은 총 7가지가 있다. 합을 나타낼 때는 수를 1개 이

codinghentai.tistory.com

 

 

백준 2156번 포도주 시식 (자바) 풀이

시간 제한메모리 제한제출정답맞힌 사람정답 비율 2 초 128 MB 111806 38034 27406 32.620% 문제 효주는 포도주 시식회에 갔다. 그 곳에 갔더니, 테이블 위에 다양한 포도주가 들어있는 포도주 잔이 일렬

codinghentai.tistory.com

 

 

백준 2579번 계단오르기 (자바) 풀이

시간 제한메모리 제한제출정답맞힌 사람정답 비율 1 초 128 MB 140615 47946 34657 33.776% 문제 계단 오르기 게임은 계단 아래 시작점부터 계단 꼭대기에 위치한 도착점까지 가는 게임이다. 과 같이 각각

codinghentai.tistory.com

 

 

백준 11727번 2xn 타일링 2 (자바) 풀이

문제 2×n 직사각형을 1×2, 2×1과 2×2 타일로 채우는 방법의 수를 구하는 프로그램을 작성하시오. 아래 그림은 2×17 직사각형을 채운 한가지 예이다. 입력 첫째 줄에 n이 주어진다. (1 ≤ n ≤ 1,000)

codinghentai.tistory.com

등 몇문제

 

오늘의 배운 점 🤔

  • 오늘은 알게모르게 알고리즘 문제가 풀고싶어서 풀데이로 진행해보았습니다.
  • 동적계획법과 분할정복을 활용해 문제풀이를 진행했습니다.
  • 오늘의 수확은 그래도 어제보다 동적계획법을 활용하는법을 익힌것 같다는 것입니다.
    • 동적계획법 문제는 대부분 일정한 패턴으로 반복되는 문제가 많았습니다. 
    • 단순히 하루이틀전까지만 해도 문제를 계속 쳐다봐도 이해가 되지 않았는데 오늘은 풀이를 안보고 제출한 문제도 있어서 뿌듯했습니다.
    • 하지만 안풀린 문제들도 많았습니다. 제출까지 했으나 정리조차도 이해가 안가서 올리지 못한 문제들이 존재합니다.
    • 확실히 풀데이는 잘풀릴때는 괜찮지만 안풀리는 문제가 생기기 시작하면 그떄부터 멘탈이 흔들리는것 같습니다.
    • 내일부터는 절대 이렇게 하지 않고 두문제 이상 풀이하지 않으리라.. 다짐을 하게 됐습니다

 

목표를 지키지 않으니 세우지 않겠습니다.. 🫠

'TIL' 카테고리의 다른 글

23-01-04 TIL  (0) 2023.01.05
23-01-02 TIL  (0) 2023.01.02
22-12-28 TIL  (0) 2022.12.28
22-12-26 TIL  (0) 2022.12.26
22-12-22 TIL  (0) 2022.12.22
  Comments,     Trackbacks
JPA - 프록시객체와 즉시로딩/지연로딩

프록시 ?

엔티티를 조회할 때 연관된 엔티티들이 항상 사용되는 것은 아니다.

예제 8.3 회원과 팀 정보를 출력하는 비즈니스 로직
public void printUserAndTeam(String memberId) {
    Member member = em.find(Member.class, memberId);
    Team team = member.getTeam();
    System.out.println("회원 이름: " + member.getUsername());
    System.out.println("소속팀: "   + team.getName());
  }

-알라딘 eBook <자바 ORM 표준 JPA 프로그래밍> (김영한 지음) 중에서

해당 코드에서는 멤버 아이디로 엔티티를 호출하면 member 엔티티와 연관된 team 엔티티까지 같이 가져온다.

 

하지만 이 코드에서 팀에대한 출력은 없이 회원 정보만 출력한다면 ? ⇒ 팀 데이터베이스까지 함께 조회해버리니 효율적이지 않다.

해당 문제를 해결하기 위해 엔티티가 실제 사용될 때 까지 데이터베이스 조회를 지연하는 방법을 제공하는데 이것을 지연로딩 이라고 한다. → 말그대로 해당 코드에서 member.getTeam() 메소드가 호출되지 않는다면 팀에대한 데이터베이스 조회는 하지 않는다.

 

지연 로딩 기능을 사용하려면 실제 엔티티 객체 대신에 데이터베이스 조회를 지연할 수 있는 가짜 객체가 필요한데 이것을 프록시 객체라고 한다.

‘Proxy. 대리(행위)나 대리권, 대리 투표, 대리인 등 을 뜻한다.’

프록시 기초 🤔

엔티티를 실제 사용하는 시점까지 데이터베이스 조회를 미루고 싶다면 getReference() 메소드를 사용하면 된다.

해당 메소드를 호출할 때 JPA는 데이터베이스를 조회하지 않고 실제 엔티티 객체도 생성하지 안히는다. 대신 접근을 위임한 프록시 객체를 반환한다.

  • 프록시의 특징
    • 프록시는 실제 클래스와 겉 모양이 같다. 사용하는 입장에서는 구분하지 않고 사용하면 된다.
    • 프록시 객체는 실체 객체에 대한 참조를 보관한다. 그리고 객체의 메소드를 호출하면 프록시 객체는 실제 객체의 메소드를 호출한다.
    • 객체는 처음 사용할 때 한 번만 초기화된다.
    • 객체를 초기화 한다고 프록시 객체가 실제 엔티티로 바뀌는 것은 아니다. 실제 엔티티에 접근 할 수 있는것
    • 원본 엔티티를 상속받은 객체이므로 타입 체크시에 주의해야한다.
    • 영속성 컨텍스트에 찾는 엔티티가 이미 있다면 DB를 조회하지 않고 실제 엔티티를 반환한다.
    • 준영속 상태의 프록시를 초기화 하면 문제가 발생한다.
  • 프록시 객체의 초기화
    • 프록시 객체는 실제로 사용될 때 데이터베이스를 조회해 실제 엔티티 객체를 생성하는데, 이것을 프록시 객체의 초기화 라고 한다. ⇒ 사용될때 실제 객체를 생성하기 때문
      • 메소드 호출→ 초기화 요청→ 영속성 컨텍스트에 엔티티 생성 요청 → DB조회→ 영속성 컨텍스트가 DB를 조회해서 실제 엔티티 생성 / 해당 순서로 프록시 객체의 초기화가 이뤄진다.
  • 프록시와 식별자
    • 프록시 객체는 식별자 값을 보관하기 때문에 식별자 값을 조회하는 메소드를 호출해도 프록시를 초기화하지 않는다.
    • 프록시는 연관관계를 설정할 때 유용하게 사용할 수 있다. → 식별자 값만 사용하기 때문에 데이터베이스 접근 횟수를 줄일 수 있다.
  • 프록시 확인
    • JPA가 제공하는 PersistenceUnitUtil.isLoaded(Object entity) 메소드를 사용하면 인스턴스의 초기화 여부를 확인할 수 있다. ⇒ 인스턴스의 초기화 여부가 분명해야 하는 경우가 있을까 ? 🤔
      • 극각의 성능을 내려면 초기화 여부까지 따져가며 데이터베이스 조회 횟수를 줄이는 방법도 있을거같다.. 🤔

즉시 로딩과 지연 로딩 🤔

JPA는 개발자가 조회 시점을 선택할 수 있도록 두가지 방법을 제공한다.

  • 즉시 로딩
    • 엔티티를 조회할 때 연관된 엔티티도 함께 조회한다.
    • 설정방법 : @ManyToOne (fetch = FetchType.EAGER)
    • 즉시 로딩을 최적화 하기 위해서 조인 쿼리를 사용하기도 한다. → 조인쿼리를 사용하면 쿼리 한번으로 두 엔티티를 모두 조회한다. (외래 키에 NOT NULL 제약 조건을 설정하면 값이 있는것을 보장하기 때문에 내부 조인을 사용할 수 있다. nullable=false 를 설정하면 기본으로 설정되있는 외부조인 대신에 내부조인을 사용한다.)
      • 선택적 관계 → 외부 조인, 필수 관계 → 내부 조인
  • 지연 로딩
    • 연관 엔티티를 실제 사용하는 시점에 DB를 조회한다.
    • 설정 방법 : @ManyToOne (fetch = FetchType.LAZY)
  • 정리
    • 대부분의 애플리케이션 로직에서 연관관계가 맺어져있는 엔티티를 같이 사용한다면 join 을 이용해서 한번에 조회하는것이 더 효율적이다.

지연 로딩 활용 🤔

지연 로딩을 어떻게 활용하면 좋을까? 본인이 기존에 진행하던 프로젝트로 예를 들어보았다.

@Entity
public class Article extends AuditingFields{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY) // 프라이머리 키
    private Long id;
    //@setter 가 붙은 값이 입력값, 없으면 자동
    @Setter @Column(nullable = false) String title; //n
    // ull 이 아닌 값을 컬럼에 저장 함
    @Setter
    @JoinColumn(name = "userId")
    @ManyToOne(optional = false,fetch = FetchType.EAGER)
    private UserAccount userAccount; // 유저 정보 (ID)

    @Setter @Column(nullable = false,length = 10000) private String content;

    @OrderBy("createdAt")  //id 순서
    @OneToMany(mappedBy = "article", cascade = CascadeType.ALL, fetch = FetchType.LAZY) //양방향 관계 (article이 주체)
    @ToString.Exclude //과부하 발생 예방
    private final Set<ArticleComment> articleComments = new LinkedHashSet<>();

    @OneToMany(mappedBy = "article")
    @ToString.Exclude
    @Setter
    private Set<ArticleHashtag> hashtags = new HashSet<>();

해당 테이블에서 연관관계는 UserAccount ,ArticleComment 와 ArticleHashtag 에 맺어져있다.

해시태그 엔티티는 단독으로 관리되지 않기 때문에 Article 엔티티에 연관관계를 직접 맺어주었고, 마찬가지로 게시글을 작성하거나 댓글을 작성할때 무조건 계정 정보가 들어가고, 댓글 또한 단독으로 관리되지 않기때문에 맺어주었다.

  • UserAccount
    • 게시글이 불러와질때마다 단순히 게시글에 nickname 컬럼이 생성되어있거나 하지 않고 외래 키로 UserAccount 엔티티의 정보를 바로 참조해 출력하기 때문에 EAGER 로 설정해주었다.
  • ArticleComment
    • 댓글은 단독으로 관리되지 않지만, 게시글과 댓글을 한번에 가져오는게 아닌 따로 비동기 통신으로 댓글을 관리한다. 하지만 연관관계는 맺을 수 밖에 없는 상황이기 때문에 키만 참조하고 한번에 조회할 필요가 없기때문에 LAZY로 설정해주었다.
  • ArticleHashtag
    • ArticleHashtag 는 중간 테이블 엔티티가 따로 존재한다. 해당 부분에 지연로딩 즉시로딩을 명시해줬는데, Articled은 LAZY, Hashtag도 LAZY를 명시해주었다.
      • 어차피 게시글을 조회하면 영속성 컨텍스트에서 관리되기때문에 db를 조회해오지 않는다.
      • hashtag 를 즉시로딩 해버리면 해당 해시태그가 등록된 게시글까지 다 불러올것 같다는 생각에 LAZY를 주었다.

이런식으로 각각 엔티티를 조회하는 부분이 달라서 데이터베이스가 무조건 따로 조회되는 경우 말고는 조회 횟수를 신경써가며 즉시로딩, 지연로딩을 활용해주면 좋다.

프록시와 컬렉션 래퍼 🤔

  • 하이버네이트는 엔티티를 영속 상태로 만들 때 컬렉션이 있으면 해당 컬렉션을 추척하고 관리할 목적으로 원본 컬렉션을 하이버네이트가 제공하는 내장 컬렉션으로 변경하는데, 이것을 컬렉션 래퍼라고 한다.
  • 컬렉션을 조회하는 메소드를 호출해도 컬렉션은 초기화 되지 않고, 컬렉션에서 실제 데이터를 조회할 때 데이터베이스를 조회해서 초기화한다.

JPA 기본 Fetch 전략 🤔

  • fetch 속성의 기본 설정값은 다음과 같다.
    • @ManyToOne, @OneToOne : 즉시로딩
    • @OneToMany, @ManyToMany : 지연로딩
  • 추천되는 방법은 모든 연관관계에 지연 로딩을 사용하는것이다.
    • 위에 적용한 로딩 방식을 죄다 지연로딩으로 변경해야겠다. (ㅡ,.ㅡ)
    • 꼭 필요한 곳에만 즉시 로딩을 사용하도록 최적화하면 된다.

영속성 전이 : CASCADE 🤔

  • 연관된 엔티티도 함께 영속 상태로 만들고 싶다면 영속성 전이 기능을 사용하면 된다.
    • 부모 엔티티를 저장할 때 자식 엔티티도 함께 저장할 수 있다.
  • cascade = CascadeType.PERSIST 옵션을 적용하면 부모와 자식 엔티티를 한 번에 영속화 할 수 있다.
  • 영속성 전이는 엔티티를 삭제할때도 부모엔티티만 삭제했을때 자식 엔티티까지 함께 삭제해준다.

고아 객체 🤔

  • JPA는 연관관계가 끊어진 자식 엔티티를 자동으로 삭제하는 기능을 제공하는데 이것을 고아 객체 제거라고 한다.
  • 고아 객체 제거는 참조가 엔티티는 다른 곳에서 참조하지 않는 고아 객체로 보고 삭제하는 기능이다.
  • orphanRemoval 은 @OneToOne, @OneToMany.에만 사용할 수 있다. (삭제한 엔티티를 다른곳에서도 참조하면 문제가 생기기 때문이다.)

마무리

느낀점 🤔

  • 그동안 fetch = FetchType.LAZY 이게 뭔지 전혀 모르고 사용했었는데 지연로딩이라는걸 드디어 알게되었습니다….
  • 중간에 즉시 로딩과 지연로딩을 각각 맞는 상황에 명시하는걸 보고 제 프로젝트에 적용해보았으나 결국엔 확실한 상황 말고는 지연로딩이 좋다는걸 뒤늦게 보고 말았습니다.
    • 지연 로딩을 지원한다는게 결국에는 한번 데이터를 가져올때 최대한 알짜배기만 골라온다는 느낌이라고 단번에 이해가 되었습니다.
  • 양방향 관계에 있어서 영속성 전이를 관리할 수 있으면 좋을텐데, 아직까지는 완전히 이해가 되지는 않은 느낌입니다.
    • 즉시로딩과 지연로딩을 공부한 후 중간 엔티티가 각 엔티티의 부모 엔티티라고 봐야하는것인지.. 헷갈렸습니다.
    • 생각해보니 제 프로젝트에서는 중간 엔티티를 삭제해버리면 각각의 엔티티도 삭제되도록 되있던거 같은데, 해당 부분을 다시 생각하고 구조를 바꿔도 될 것 같습니다 😀
  • 프록시 객체에 대한 개념을 여기서 완벽히 이해한것 같습니다.
    • 여기서 한번 더 getReferenceById 와 findById 의 차이를 짚고 넘어가야 할 것 같습니다.
  • #패스트캠퍼스 #국비지원교육 #메가바이트스쿨 #MegabyteSchool #개발자취업부트캠프 #내일배움카드
  Comments,     Trackbacks