![[프로젝트] Redis로 캐싱 구현하기](https://blog.kakaocdn.net/dn/yfPUy/btsJDwuYz6M/it9xZlzrSGKsspszo18Yz0/img.png)
💡 개념Redis- 오픈 소스 In-memory 데이터 저장소- String / Hash / Set / List 등을 저장 가능- 전통적인 디스크 방식보다 훨씬 빠르며, 주로 캐시(cache)용도로 사용- 현재는 단순 캐시 용도 이외에도 데이터베이스, 메시지 브로커, 스트리밍 엔진으로도 사용캐시로 사용?- 호출할 때마다 계산을 해야하고 계산이 오래걸리거나, 시점에 따라 결과값이 바뀌지 않는경우(예시: 어제까지 발생한 서비스의 총 매출같은 통계값) 🔥 개발 방향사용자 정보는 현재 프로젝트에서 변경될 일이 없으므로 인증 부분에서 캐싱을 적용하려고 함기존: 사용자 인증(로그인)을 진행할 때, 항상 DB에서 사용자 정보를 가져옴개발 진행 방향:- 처음 사용자 인증(로그인) 시 DB select 후, 캐시에 ..
🆘 문제 상황Docker desktop을 설치했는데 retrieving system version: exec: "sw_vers": executable file not found in $PATH initializing api proxy server: getting linux engine: getting services IP: computing ServiceIP of : invalid CIDR address:에러가 발생하며 종료되었다. Docker 데몬이 제대로 실행되고 있는지 확인하려고 터미널에서 아래 명령어를 사용했지만 데몬 자체도 실행 중이지 않았다.docker info sw_vers 오류sw_vers는 macOS에서 시스템 버전을 확인하는 명령어→ cmd 창에서 'sw_vers'를 입력했을 ..
![[프로젝트] N+1 문제 해결하기 (Fetch Join+QueryDSL, Hibernate최적화)](https://blog.kakaocdn.net/dn/E692D/btsJCUVp0p1/tJy97Pmh2GfrkGUCmAkEZ0/img.png)
🆘 문제 상황Thread 프로젝트 중 1:N (Post : PostComment)관계가 맺어져 있는 상황에서 사용자 전체 조회 시 일대다 관계로 매핑된 테이블의 조회 쿼리까지 함께 날라가는 N+1 문제가 발생했다. Java 코드List posts = postRepository.findAll();for (Post post : posts) { post.getPostComments().size();}실행 결과Hibernate: select p1_0.id, p1_0.content, p1_0.created_at, p1_0.created_by, p1_0.modified_at, p1_0.modified_by, p1..
💡 QueryDSL 이란?하이버네이트 쿼리 언어(HQL: Hibernate Query Language)의 쿼리를 타입에 안전하게 생성 및 관리해주는 프레임워크QueryDSL이 등장하기 이전에는 Mybatis, JPQL, Criteria 등 문자열 형태로 쿼리문을 작성하여 컴파일 시에 오류를 발견하는 것이 불가능했음QueryDSL은 JPA 뿐만 아니라 SQL, MongoDB, Lucenece 등다양한 언어에 대해서 서비스를 제공함QueryDSL을 사용하여 기존의 @Query를 대체하려면, JPAQueryFactory를 사용해 동적 쿼리를 작성할 수 있음1. Q클래스 생성- 해당 엔티티의 필드들을 객체로 다루는 도구- QueryDSL이 컴파일 시 자동으로 생성 (Post → QPost) public cla..
![[프로젝트] OAuth2 인증 구현하기 (KakaoOAuth) + SecurityConfig 설정](https://blog.kakaocdn.net/dn/madBT/btsJvvJROXT/S9V0sXC2UbFdVyYSO9KP00/img.png)
✅ Githttps://github.com/ellaCoo/sns/pull/46📌 상황이전에 SpringSecurity로 로그인 기능(https://github.com/ellaCoo/sns/pull/27)을 구현했는데,회원가입 기능말고 카카오 로그인 기능을 추가하려고 한다. 1. build.gradle 에 Spring Security OAuth2 Client 의존성 추가한다implementation 'org.springframework.boot:spring-boot-starter-oauth2-client' // kakao auth 2. application.yaml 파일에 카카오 OAuth2 스프링 프로퍼티 설정을 추가한다카카오 개발자 문서를 참고하여 OAuth 2.0 서비스..
![[프로젝트] N:N 관계 → 1:N & N:1 로 구현하기](https://blog.kakaocdn.net/dn/mb1AM/btsJwe1vHX3/VRdlJKYkFMIzVsgr6K8aZk/img.png)
✅ Githttps://github.com/ellaCoo/sns/issues/17https://github.com/ellaCoo/sns/pull/40 📌 상황[ 포스트 : 해시태그 ]가 [ N : N ] 관계로 설계된 상태에서,관계형 데이터베이스는 정규화된 테이블 2개로 다대다 관계를 표현할 수 없다는 한계에 부딪쳤다.(@ManyToMany 어노테이션 사용하는 방법은 연결 테이블을 개발자가 직접 관리하는 방식이 아니기에..)⇒ 연결 테이블과 연결 테이블용 엔티티를 추가하여 일대다, 다대일 관계로 풀어내보자왜 ManyToMany 를 지양해야 하는가?ManyToMany를 사용하면 직접 테이블관리나 인덱스 설정을 할 수 없고, post_hashtag가 자동적으로 만들어져서 개입하고, 직접 수정하기 어려워짐...
![[프로젝트] 댓글과 대댓글 관계 로직 엔티티 하나로 구현하기 (JPA)](https://blog.kakaocdn.net/dn/djs30l/btsJtgTdbUf/mNTHqGuW3Ku9orOAuk75kK/img.png)
✅ Git Issuehttps://github.com/ellaCoo/sns/issues/6https://github.com/ellaCoo/sns/pull/31📌 상황→ Post에 해당하는 댓글에 대댓글까지 기능을 추가하기 위해 parent_comment_id 컬럼을 추가함 ✔️ PostId로 [ 포스트정보 + 해당 포스트 댓글 + 유저의 좋아요 정보 ] 가져올 때, PostComment(댓글)과 대댓글을 createdAt(생성일시)로 정렬하여 함께 Response 객체에 담기1. Post 엔티티 안에 Set postComments = new LinkedHashSet();를 정의하여 관계 맵핑2. PostService 에서 postRepository.findById(postId) 로 Post 가져오기3...
![[삽질록] 민감 정보의 환경변수 치환 후 테스트 실패 현상](https://blog.kakaocdn.net/dn/VxiwU/btsJkvQb3Ol/GvqOAoKKgd1xC4ct8557j0/img.png)
🆘 문제상황// application.yamlspring: datasource: url: ${LOCAL_DB_URL} username: ${LOCAL_DB_USERNAME} password: ${LOCAL_DB_PASSWORD}@SpringBootTestclass ApplicationTests { @Test void contextLoads() { }}환경변수를 이용해 application.yaml안에 있던 민감 정보를 치환하여 보안성을 높였는데, 일부 스프링 부트 테스트가 실패한다.문제 원인@SpringBootTest 는 초기 테스트 환경을 구성하면서 프로퍼티 파일의 설정을 참고하기 때문⇒ 환경변수가 주입되지 않은 테스트 환경에서 @SpringBootTest 가 이를 ..
![[삽질록] Spring Security 인증 구현 하고 insert 테스트 오류 (AuditorAware)](https://blog.kakaocdn.net/dn/bozL7h/btsJjnxY9fB/JseDpEy2AuVHozKYNChzw1/img.png)
🆘 문제상황spring security로 인증을 구현 후 기존의 Test를 돌렸더니 insert 에서 에러가 발생했다.기존 코드/*단위 테스트에서는 spring 컨테이너를 사용하면 안된다.@DataJpaTest: repository 객체를 의존주입 받을 수 있게 해준다. | @Transactional 을 갖고있어서 테스트 이후 자동 롤백 가능 */@DisplayName("JPA 연결 테스트")@Import(JpaConfig.class)@DataJpaTestpublic class JpaRepositoryTest { @Autowired private PostRepository postRepository; @Autowired private PostCommentRepository postCommen..
🆘 문제상황@DisplayName("컨트롤러 - Post")@WebMvcTest(PostController.class) //MVC 관련 빈들만 로드함 - 테스트 실행이 빠르고, 메모리 사용량 적음 | 서비스, 리포지토리 등의 빈은 로드되지 않음class PostControllerTest { private final MockMvc mvc; //HTTP 요청을 모의(mock)하여 컨트롤러의 동작을 테스트 | 실제 웹 서버를 띄우지 않고도 컨트롤러의 요청-응답 흐름을 테스트할 수 있음 // 필드주입 @MockBean // ->MockBean이 생성자 주입 지원하지 않음 private PostService postService; // 생성자주입 PostControllerTest..