일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 백준
- 기본유형
- DP
- 부분수열의합2
- 알고리즘
- DFS
- 다시보기
- 트러블슈팅
- 그리디
- JUnit
- 자바
- SWEA
- database
- SSAFY
- JPA
- 코테
- 다익스트라
- 완전탐색
- 알고리즘기본개념
- 코드트리
- 완탐
- Union Find
- BFS
- 유니온파인드
- Spring
- 싸피
- 코딩테스트
- 코딩테스트실력진단
- Java
- 그래프
- Today
- Total
목록무엇을 합니다/프로젝트 (13)
HwangHub
커뮤니티 서비스는 likelion univeristy 서비스의 핵심 기능 중 하나이다. 유저들에게 가치를 전달할 수 있는 핵심 도메인이다. 즉, 서비스의 성공의 선두에 커뮤니티 서비스가 제공되어야 한다. 그럼에도, 현재는 쿼리 하나하나를 무겁게 실행하고 있어 데이터가 조금만 많아져도 서버가 많은 부담을 느끼고 있다. 이를 확인하고자 먼저 테스트 데이터를 강제로 늘려보았다. 운영 DB를 mysql로 사용하고 있기 때문에 이와 최대한 근사한 환경을 구축하고자 로컬 test db로 mysql로 구성하였다. 테스트용 더미데이터 입력을 위해 프로시저를 제작하여 등록하여 호출을 통해 데이터 복제를 수행하였다. CREATE DEFINER=`likelion`@`localhost` PROCEDURE `InsertMill..
문제 인지 현재 프로젝트에 다음과 같은 문제가 있다. 우리 프로젝트에서는 레디스를 사용하여 commentCount, likeCount를 관리하고 있다. 이를 기준으로 한 sort(랭킹)을 위해서 사용한다. 하지만 정상적으로 redis가 업데이트 되고 있지 않는 것으로 확인되었다. 상황 파악 우리 프로젝트에서 레디스가 어떻게 사용되고 있는지 먼저 파악하였다. 기본적으로 직렬화할 때 TIMESTAMPS 형식을 disable 함 직렬화할 때 자바의 LocalDateTime으로 적용시킴 타입 검사할 때 non-final이 기본값으로 되도록 설정 Lettuce(레디스 자바 클라이언트) 사용 적용 자료구조 : String key-value 형태로 저장중 (우리는 로 저장) string의 prefix 가 "postC..
ISSUE 운영중인 서버의 DB 스키마를 변경해야 했다. 로직을 수정하다보니 기존 스키마에 불필요한 칼럼이 존재함을 알게 된 것이다. 경우에 따라서는 칼럼을 추가해야 하는 경우도 있었다. 현재 운영 서버는 ddl-auto : none 으로 설정하고 사용하고 있다. 따라서 스키마 수정만을 위해 ddl-auto : update 처리하고 restart하는건 벼룩 잡겠다고 집을 태우는 것과 유사한 느낌이라고 판단했다. 잘 운영되고 있는 서버를 로직 수정도 아닌 상황에서 내려야 하며, ddl-auto에 의존하게 되면 어떻게 sql이 작성될지 알기 어렵다는 게 문제다. 즉, 리스크가 있는 선택이라는 거다. SQL 몇 줄 쓰는게 어려운 일도 아닌데, 참 바보같게도 과거에는 ddl-auto에 의존적으로 스키마 구성을 ..
나는 멋쟁이사자처럼 커뮤니티 개발 프로젝트에서 백엔드 리드를 맡아, 서버 리드와 함께 어플리케이션 설계에 대하여 같이 고민하였다. 우리는 이 프로젝트를 ver1.0으로 끝낼 생각이 없었고, 향후 계속 유지보수를 해야 하는 프로젝트로 계획하고 있었기에 유지보수성을 어떻게 가져갈지 고민하지 않을 수 없었다. 우리는 기획팀의 화면정의서를 바탕으로 요구사항을 정리하였고, 기본적으로 백오피스, 채팅, 그리고 클라이언트를 위한 API 서버를 구현해야 함을 이해했다. 이를 구현함에 있어서 각각의 서비스는 반드시 같은 버전으로 업데이트 될 필요가 없다. 다시 말해서, 백오피스 버전을 업그레이드 했다고 해서 클라이언트를 위한 API 코드들까지 전부 리빌드할 필요가 없다는 의미이다. 이처럼 빌드 종속성을 최대한 느슨하게 ..
기존 구현 postId와 parentCommentId를 둘 다 body로 받아서 대댓글 생성. 문제점 parentComment가 가진 postId와 childComment가 가진 postId가 불일치하진 않는지 체크해야 한다. 이는 불필요한 로직을 추가적으로 양산하며, 클라이언트가 postId까지 신경쓰도록 반영해야 하므로 서버에서 parentComment가 가진 postId를 뽑아서 반영해주는 로직이 더 깔끔할 것이라 보았다. 결과 로직 private Comment childCommentBy(CommentCreateChildServiceDto request) { Comment comment = Comment.builder() .post(getPostFromParentComment(request)) .a..
문제 쿼리는 다음과 같다. public List findAll(Long postId) { return queryFactory .select(commentDetailResponseDto()) .from(comment) .join(comment.author, user) .leftJoin(comment.parentComment, comment) .leftJoin(comment.commentLikes, commentLike) .where(comment.post.id.eq(postId)) .orderBy(comment.createdDate.asc()) .fetch(); } parentComment를 join하여 조회하기 때문에 발생한 문제로 보았다. 즉, 내가 쿼리에 대한 이해가 부족하여 아예 잘못 짠 것이다. ..
문제 상황 분명 PK 자동생성 전략을 사용하였는데, 위와 같은 에러가 발생하였다. 엔티티를 정의한 방식은 아래와 같다. @Entity public class Post extends BaseTimeEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "post_id") private Long id; ... } 해결 스택오버플로우에 따르면, "경우에 따라 모델이나 ORM은 데이터베이스의 변경사항이 정확하게 반영되지 않을 수 있다.(SchemeUpdate) 코드 상의 오류를 정확히 파악할 수 없다면 다시 만들어보세요.(SchemeExport)" 라고 한다. 아무래도 ddl update 방식으로는 generate strat..
문제 상황 기존에 작업에서는 게시글 엔티티가 아래와 같이 선언되어 있었다. @Entity public class Post extends BaseTimeEntity { ... @Column(length = 500) private String title; @Column(length = 50000) private String body; ... } 본문 필드에 50000으로 받겠다고 선언되어있었는데, 이는 일반적이지 않은 선언이다. 우선 mysql 기준 레코드 전체 크기가 65,535 bytes로 제한되어 있으므로, 50000과 같은 길이 설정 자체에서 오류를 일으키기도 하고, 그것 외에도 실제 생성하면서도 레코드가 생성되지 않고 에러를 발생시킬 수 있기 때문이다. 반면, 일반적으로 긴 문자열을 저장하기 위해 ..
data jpa에서는 persistenceContext라는 개념이 존재하고, 엔티티 스냅샷을 비교하여 dirtyChecking을 수행하는 방식으로 운영된다. 따라서 엔티티가 persistence layer 이외에 노출되는 것은 엔티티에 대하여 불필요한 엑세스 포인트를 과하게 노출시키는 행위이며, 만약 협업을 하다가 로직이 꼬이게 되면 의도치 않은 엔티티 수정이 발생될 수 있다. 그 외에도 여러가지의 '안정성'을 위한다는 이유들로 persistence layer 이외의 레이어에서는 dto 사용이 적극 권장된다. 가지고 있던 문제는? 멋대플랫폼 아키텍처의 처음 구현 방식에서는 엔티티가 useCase라는 client 객체에서부터 사용되고 있었다. 처음 presentation layer에서 dto로 reques..
기존에는 유저 ID를 클라이언트에서 입력하도록 API가 설계되어 있었다. 즉, Controller 레벨에서 pathVariable 또는 requestParam으로 userId를 받고 있었다. 아래는 api 중 유사한 api의 예시이다. @GetMapping("/mypage/author/{userId}") public SuccessResponse findAuthorPosts(@PathVariable Long userId, @RequestParam Integer page, @RequestParam Integer size) { ... return SuccessResponse.of(response); } 문제가 무엇인가? 클라이언트는 엑세스 토큰, 리프레시 토큰을 가지고 있음에 불과하고, 로그인 유저 정보를 관..