프로젝트/씈크럼 프로젝트

여태 프로젝트 진행하면서 동시성 문제에 대해 생각하지 않았다. 사실 그럴 힘이 없었다. 근데 자바에서는 멀티 스레드를 지원하는데 문제는 여기서 발생한다. 멀티 스레드 -> 즉 하나의 프로세스에서 여러 개의 스레드가 동시에 작업을 진행한다. 씈크럼 프로젝트에서 스크럼의 참여 인원을 +1 시키는 메서드가 존재한다. public void plusCurrentMember(){ if(this.maxMember 최대 멤버 : 20명, 현재 멤버 : 19명 만약에 두 유저가 해당 스크럼 정보를 통해 참여를 진행한다면? 둘 다 현재 참여가 가능하다고 판단해서 Update Query를 날리게 되고, 결국 데이터 정합성에 문제가 발생한다. 나는 여태 이런 경우를 생각하지 않고 진행했었는데 이제는 멀티 스레드에 대해 생각할..
프로젝트를 진행하면서 람다는 시큐리티에서 사용해봤지만 Stream은 전혀 사용하지 않고 있었다.(잘 모르기도 했고 for문이 더 편했어서) 이번에 stream을 사용해보고자 코드를 리팩토링하고 시간을 측정했는데 생각 외의 결과가 나왔다. 아래는 스크럼을 조회하는 서비스이고 데이터는 2000개, 스레드 20개, 루프카운트 10으로 조회를 시작했다. // 스크럼 팀 조회 @Override public ScrumRoomListResponseDTO findScrums(Long teamId) { User user = securityContext.getUser(); Team team = teamRepository.findById(teamId) .orElseThrow(() -> new TeamNotFoundExcep..
유저 닉네임 변경 API를 예시로 들어보자. PatchMapping을 사용해서 특정 컬럼만 업데이트하는 RESTAPI라고 선언을 하고 nickname을 받아서 JPA의 더티체킹으로 업데이트를 진행한다. 우리가 원하는 건 닉네임만 업데이트가 진행되길 원한다. 그러나 결과는 그게 아니던데??? 분명 업데이트 쿼리는 나가는데 왜 모든 컬럼에 대해서 set이 들어가는 거지? 결국 이는 리소스 낭비로 이어지지 않나? 라는 생각이 들어 그 이유와 해결 방법을 찾아보았다. 이유 JPA의 구현체인 하이버네이트는 결국 JDBC API를 내부적으로 사용하는데, 웹 개발을 공부하셨던 분들이라면 Statement와 PreparedStatement를 들어보셨을 것이다. Statement를 사용하면 쿼리를 사용할 때마다 아래의 ..
JPA를 사용하면서 @CreatedDate, @LastModifiedDate 어노테이션을 유용하게 사용했었습니다. Entity를 생성하면 자동으로 생성 시간을 넣어주고, Update가 발생하면 자동으로 수정 시간을 변경해주었습니다. 현재 Scrum, User 엔티티에서 해당 어노테이션을 사용하는데 전부 Entity마다 각각 지정을 해주었었습니다. @CreatedDate @Column(nullable = false) private LocalDateTime createdDate; @LastModifiedDate @Column(nullable = false) private LocalDateTime updatedDate; 모든 테이블마다 이렇게 동일한 코드를 사용하는 것은 너무 비효율적이라는 생각이 들었습니다...
Scrum을 검색하면서 페이지네이션을 도입해야 했습니다. 검색 조건은 아래의 2가지 조건이 존재한다고 가정했습니다. 1. 스크럼 제목으로 검색 2. 리더의 닉네임으로 검색 둘 중 하나의 값만 들어와야 하며, 둘 다 공백 or Null로 들어오는 경우 클라이언트 에러를 리턴합니다. 가장 먼저 고민했던 점은 검색어를 어떤 방식으로 전달하냐의 문제가 발생했습니다. 1. 검색어를 통한 조회니깐 GET을 통해 url에 쿼리스트링으로 전달하자. 2. POST로 검색 타입, 데이터를 DTO로 받아서 처리하기. 처음에는 당연히 검색 조회니깐 1번을 선택하려고 했습니다. 그런데 2번도 불가능하지는 않는 방법이라 생각했고, 왜 사용을 안하는지 궁금했습니다. REST API에서 POST 메서드는 데이터의 생성, 변화를 일으..
현재 프로젝트에서 모든 CRUD 처리를 쿼리메서드, JPQL로 처리했었다. 단순한 조회는 대부분 쿼리메서드로 처리하고, fetchJoin이나 조건이 여러 개인 경우 JPQL을 사용했었다. 그러나 이제 검색 조건을 만들면서 동적 쿼리를 사용하는 케이스가 생기게 되었다. 현재 검색 조건으로 1. 스크럼의 제목 2. 리더의 닉네임 이 2개의 조건이 or로 들어오게 된다. 검색 조건을 dto로 받기에 동적으로 들어오는 조건에 맞춰서 쿼리가 나가야하는데 처음에 JPQL을 사용해서 만들었더니 결국 쿼리를 2개 만들어서 어떤 검색타입으로 들어왔는지 확인해서 불러주어야 했다. 이런 불편함을 없애고자 했던 이유도 컸고, 결국 실무에서 JPA를 사용하면 동적 쿼리를 많이 다루기에 QueryDsl을 거의 필수로 사용한다는 ..
현재 유저가 스크럼 생성 가능 여부를 알려주는 메서드입니다. @Query("SELECT s FROM Scrum s WHERE s.user = :user AND s.deleteDate IS NULL AND s.endTime IS NULL") List findByUserWithAndDeleteDateIsNullAndEndTimeIsNull(@Param("user") User user); 3개의 조건으로 해당하는 Scrum을 찾아서 List에 담은 다음에 리스트가 비었는지, 아닌지에 따라 true, false를 리턴했습니다. 그러나 다시 코드를 천천히 살펴보니, 3개 조건에 해당하는 스크럼이 하나라도 존재하면 false를 리턴해주면 되는 간단한 문제였습니다. 아마 당시에는 해당 방법이 쉬운 방법이라 생각하고 ..
현재 AccessToken, RefreshToken을 전부 쿠키로 담아서 전송하도록 만들었다. 심심해서 쿠키에 있는 AccessToken을 조금 바꿔서 swagger로 전송을 보냈더니 바로 SignatureException을 뱉어내기 시작했다. 문제는 내 코드에 해당 에러를 처리해주는 부분이 없었다는 거. 그래서 응답으로 이렇게 500에러가 터져버린다. 그래서 토큰에서 값을 파싱할 때 해당 예외처리를 진행해주었다. public Long getUserId(String token){ try { return Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token) .getBody().get("userId", Long.class); } catch (Expir..
indeep
'프로젝트/씈크럼 프로젝트' 카테고리의 글 목록