프로젝트/크루트 25

jpa 쿼리 수 줄이기

프로젝트 관련된 정보를 수정하려 할 때 프로젝트의 멤버인지를 체크해주는 checkIsMember() 함수가 있다. data jpa를 사용한 repository에서 코드를 이렇게 작성했었다. 하나는 count를 가져와서 project를 같이 가져오지 않는다. 그 결과 나중에 project가 필요할 때 db에 쿼리를 다시 날려서 가져와야 한다. @Query(value = "select count(*) from (select project_id as pid from Project p where p.project_id = :projectId) join Part pa on (pa.project_id = pid) join User_Part up on (pa.part_id = up.part_id)" + " where..

ec2를 종료해서 도커와 젠킨스가 죽었을 때 살리는 법

sudo docker start service 명령을 실행 시 계속 에러가 뜨면서 문제가 생겼다. 이리저리 방법을 찾아 에러의 원인을 찾아보니 /etc/fstab에 문제가 있단다. /etc/fstab에서 뒤에 달린 /swapfile swap swap defaults 0 0 가 문제였다. 시험 공부한다고 ec2를 꺼뒀다가 다시 켰더니 swap 메모리 할당했던 게 없어졌었고 (free 명령어를 입력해보면 알 수 있다.) 위 파일에서는 swap 메모리를 사용하라고 하니 문제가 발생했던 것이다. 그래서 다시 swap 메모리를 할당해주고 전에 만들어둔 젠킨스를 다시 도커 컨테이너에 올렸더니 문제가 해결됐다. sudo service docker start 를 통해 다시 도커를 시작해주고 sudo usermod -a..

jpa의 orphanRemoval이 잘 작동하는 지 테스트가 하고 싶을 때

테스트코드를 작성하지 않고 손수 인수테스트를 하며 개발하는 동안 UserPart 또는 UserStack에서 논리 상으로는 제거가 되어야 하는데 제거되지 않은 데이터를 발견한 적이 있다. 중간에 잘못된 메소드를 실행했다가 그 결과가 났는 지 아니면 현재 메소드들도 어딘가에 문제가 있는 지 알 수가 없었다. 이래서 테스트 코드를 작성하면서 개발해야 한다. 아무튼 이런 찝찝한 기분을 받았기 때문에 jpa의 orphanRemoval이 잘 작동해 db에서 데이터가 삭제되는 지 확인하고 싶었다. 그래서 나름 테스트코드를 짜봤다. @Transactional public void modifyUsingStacks(Part part, List stacks) { // 초기화 시킨 뒤 다시 채우기 part.getPartSta..

service layer에서는 도대체 뭘 테스트 해야해요?

DTO(repository) 레이어에서는 spring data jpa를 쓰는 경우 @DataJpaTest와 TestEntityManager를 사용하면 원하는 대로 테스트를 할 수 있다. testEntityManager로 jpa의 모든 동작(persist, delte 등)을 사용할 수 있다. 테스트를 위해 넣은 데이터는 나중에 롤백되기 때문에 데이터베이스에 영구적인 영향을 미치지 않는다. spring data jpa 자체가 이미 검증된 모듈인데 테스트할 필요가 뭐가 있냐고 생각할 수 있다. 그 말에 동의한다. 그래서 @Query를 사용해서 내가 지정한 쿼리를 날리는 메소드만 테스트 중이다. service layer를 테스트하려 했는데 도대체 뭘 테스트 해야겠는 지 모르겠었다. @ExtendWith(Mock..

Entity에 @Transactional을 쓰고 싶은데 그래도 될까?

처음에 service layer에서 프로젝트 생성 시 3개의 파트를 db에 저장하고, 프로젝트 제안자는 자기 포지션에 따라 적절한 파트에 들어가도록 UserPart 테이블에도 데이터가 저장되게 했다. ProjectRepository를 테스트하면서 project entity 안에 이 로직(프로젝트 생성 시 파트 3개 생성, userpart 1개 생성)이 들어가면 범용성이 좋아질거 같다고 생각했다. 그래서 ProjectService에 있던 로직을 제거하고 ProjectRepositoy에 넣어봤다. 참고로 생성자에는 @Transactional 애노테이션을 쓸 수 없다. @Target({ElementType.TYPE, ElementType.METHOD}) @Transactional의 타겟에 class는 없다. ..

모바일 브라우저에서는 로그인이 안 되는 이유

윈도우 노트북의 웹 브라우저에서는 로그인이 잘 됐는데 모바일에서 크롬을 열고 로그인을 시도하면 계속 실패했다, 그 원인을 오랫동안 찾아 헤맸다. 모바일 브라우저와 윈도우 브라우저의 메커니즘이 무언가 다른 것은 분명하다. 환경 크로스 도메인 요청 https 요청 스프링에서 세션 쿠키 설정은 ,httpOnly, secure, same-ste: none을 적용했다, 아직까지 SameSite=None을 인식하지 못하는 클라이언트는 이를 무시하고 특성이 설정되지 않은 것처럼 계속 작동하게 됩니다. 버전이 낮은 브라우저는 SameSite = None을 지원하지 않는다. 그러한 브라우저는 SameSite=Lax인 것처럼 작동한다. pc 브라우저에서는 지원하고 있지만 아직 모바일 브라우저에서는 지원이 안 되는 기능이 ..

https와 cross domain으로 서버와 통신 시 쿠키 보내는 법

현재 서버와의 통신 사항은 이렇다 프론트엔드와 백엔드가 서로 다른 도메인을 가지고 있다. (cross domain) = 서로 다른 url 프론트엔드와 백엔드 모두 ssl을 끼고 통신한다. (https) 로컬에서 테스트할 때는 서버가 보내준 쿠키를 프론트 단에서 잘 저장했었다. 프론트엔드 서버는 localhost:3000, 백엔드 서버는 localhost:8080에서 호스팅되고 있었다. 프론트엔드가 server side rendering 중이다. 문제는 서버와 프론트를 모두 호스팅하고 https로 통신할 때였다. login을 해도 세션 쿠키가 브라우저에 저장되지 않아(혹은 쿠키는 받았지만 서버에 보내지 않아) 로그인이 정상적으로 성공하지 않았다. 이 글을 작성하고 보니 쿠키를 서버로 보내지 않았던 거다. ..

vscode에서 template을 사용해서 귀찮음을 줄이자

저렇게 상단 파일 탭 > 기본 설정 > 사용자 코드 조각이 있다. 저걸 누르면 vscode에서 템플릿을 사용할 수 있다. vscode의 확장 중에 vue와 관련된 확장이 있어 vueinit을 사용하면 composite api 전용 템플릿이 바로 만들어진다. 이 부분이 굉장히 편해서 vue를 쓰기도 한다. 그런데 nuxt 전용 hook인 fetch는 확장에 등록이 되어있지 않아 하나하나 작성을 했었다. 굉장히 귀찮았는데 왜 이제야 해결 방법을 찾아봤을까? vue 파일을 상당히 많이 만들고 난 뒤에야 vscode에서도 template을 지원한다는 것을 검색해봤다. vue 안의 script에만 scope를 적용하는 방법까지는 찾지 못 했다. javascript scope로 범위를 조금 넓혀도 vue 안의 sc..

JPA를 쓰는데 Fk 제약조건 때문에 골머리 썩고 있다면 cascade를 사용해서 쉽게쉽게 갑시다

FK 제약조건으로 인해 객체를 삭제할 때는 제거하려는 객체를 참조하고 있는 객체들부터 먼저 제거해줘야 한다. Question 객체를 삭제하고자 하지만 Notification에서 FK로 Question의 id를 참조하고 있는 상황이다. 그래서 Question 객체를 삭제하려고 할 때 연관된 Notification 객체들부터 전부 제거해줘야 했다. jpa의 orpahnRemoval=true를 이용하고 Question 객체의 필드인 Notification 배열을 clear 해주는 방식으로 구현을 했었다. 그런데 FK 관계가 한두개가 아니다보니 이렇게 하는 건 중간에 실수가 발생하기 쉽겠다는 생각이 들었다. @Transactional public void delete(Question question) { // ..