본문 바로가기

Kotlin

(19)
(Spring) 어떤 식으로 캐시를 구성하는 것이 좋을까?? 캐시 전략에 대해 알아보자 웹 페이지를 개발하기 위해서는 우리는 캐시를 활용해서 성능을 개선해야 할 경우가 있을 것이다 오늘은 그러한 캐시를 어떤 방법으로 활용할 수 있는지 알아보고자 한다 캐시란?? : 휘발성 메모리로 컴퓨터의 전원이 꺼지면 지워지는 특징이 있지만 DB에서 조회하는 것과 다르게 굉장히 빠르게 조회할 수 있다는 특징이 있다 이러한 특징이 있는 캐시는 장단점이 명확하기 때문에 전술적으로 혹은 전략적으로 캐시의 설계전략을 잘 설계해서 가져가는 것이 좋다  캐시 전략은 크게 쓰기 / 읽기 전략이 있다 먼저 읽기 전략은 아래와 같은 전략들이 있다 1. Look Aside 전략 그림에서 볼 수 있듯이 먼저 캐시를 방문 하고 캐시 미스가 날 경우 DB에서 조회 및 캐시에 저장하는 방법이다 장점캐시와 DB가 분리 운영되고 있기..
(Spring) 크론 표현식에 대해 알아보자 이번 개인 프로젝트에서 나는 SoftDelete를 구현하기로 했다 SoftDelete란??Delete 쿼리가 날아갈 시점에 Delete를 시키지 않고 이 데이터를 업데이트 하면서 추후에 복구 및 증거 수집등에서 유용하게 사용하기 위한 방법이다단점으로는 Query를 관리를 많이 해야 하고 DB에 데이터가 지속적으로 축적되지 않기 위해서 관리를 해줘야 한다우선 SoftDelete를 구현하기 위해서 간단하게 정책을 설정하기로 했다 SoftDelete 된 내용은 본인 혹은 관리자만 볼 수 있어야 한다SoftDelete 된 내용은 90일이 지나면 삭제가 되서 지속적으로 데이터가 축적되는 현상은 방지한다이 2가지 정책을 가정하고 시작을 하려고 한다 우선 오늘은 2번째 정책인 90일이 지나면 자동으로 삭제가 되는 A..
(Spring) No property {} found for type {} 해결 법 JPA와 QueryDSL 을 동시에 사용하려다 보면 이런 현상들이 발생 한다@Transactional@Serviceclass IssueService( private val issueRepository: IssueRepository, private val queryDslIssueRepository: QueryDslIssueRepository private val memberService: ExternalMemberService,){이런 식으로 2개의 Repository를 주입 받아야 하는 현상이 생기는 것이다 나는 이 부분이 마음에 안들어서 JPA와 QueryDSL 을 하나의 Repository로 통합을 해보려고 한다위와 같이 리펙터링을 하여 Service 코드에서 하나의 Repositor..
(Spring) 관점 지향 코딩의 핵심!! AOP 의 설정 법을 알아보자 implementation("org.springframework.boot:spring-boot-starter-aop")AOP 란??부가 기능과 핵심 기능을 구분하여 부가 기능을 모듈화 하여 Application 전체에서 사용 할 수 있도록 하는 방법Annotation 을 사용하여 모듈화 할 수 있고 이를 전체적으로 사용할 수 있다사용하기 전에 build.gradle에 설정을 해주고 가자!! AOP를 사용하기 위해서는 실행 위치나 메서드의 상태 변화 따라서 다음과 같은 Annotation 을 적용할 수 있다@AspectAOP를 사용하기 위해서 정의한 클래스 위에 지정해 준다@PointcutAOP기능을 메서드, Annotation 등 어디에 적용시킬지 지점을 설정 지점을 설정하기 위한 Annotation@B..
(Spring) 발생할 가능성은 언제든지 있다!! StackOverflowError 금일 발생한 문제는 StackOverflowError 이다  StackOverflowError 는 재귀 함수를 많이 호출한 나머지 스텍 메모리가 초과해서 발생하는 애러라고 볼 수 있다 우선 나는 처음에 해당 문제에 대한 인지를 못하고 있고 내가 맵핑하지 않은 애러 메세지만 떴기 때문에 JWT 인증 문제인 줄 알았다 그러나 로그를 확인해보니까  at com.yoong.myissue.domain.team.dto.TeamResponse$Companion.from(TeamResponse.kt:16) ~[main/:na] at com.yoong.myissue.domain.issue.entity.Issue.toIssueResponse(Issue.kt:79) ~[main/:na] // X100이런 애러가..
[Spring / QueryDSL] UnsatisfiedDependencyException, Error creating bean with name 해결 Spring에서 JPA와 QueryDSL 을 동시에 도입 하는 방법은 여러가지가 있는데 그중 2가지를 소개해보자면 Service Layer에서 생성자로 JpaRepository, QueryRepository를 동시에 주입 시키는 방법이 방법은 가장 직관적이고 쉽게 사용하는 방법이다따로 각각의 Repository를 만들어서 Service에서 같이 생성자를 주입받는 방법이다하지만 Service객체의 결합도가 높아진다는 단점이 있다@Service@Transactionalclass TeamService( private val teamRepository: TeamRepository, private val queryDslTeamRepository: QueryDslTeamRepository) 2. 추상적인..
(Spring) 인증 개발을 하면서 겪은 다양한 버그들 1. Error creating bean with name 'jwtPlugin' defined in file여러가지 원인이 있을 수가 있었다Jwt의 의존성이 제대로 적용이 안되어 있을 수 있다application.yml 파일에 설정을 제대로 적용을 안했을 수도 있다JwtPlugin에 @Component Annotation을 붙여주지 않았다나는 이번에 확인 시 에 2번 application.yml 파일에 설정을 제대로 되지 않은 문제가 있었다 정확하게 말하면 주입 받는 생성자에 제대로 된 경로를 적어주지 않아서 발생한 문제였다 따라서 해당 경로를 수정해주면서 문제를 해결 했다AS-IS@Componentclass JwtPlugin( @Value("\${jwt.issuer}") private val is..
(Spring) Type mismatch: inferred type is Duration but TemporalAmount! was expected 애러 해결 금일 인증 토큰을 생성하는 JwtPlugIn 을 만드는 과정에서 뜬금없이 Type mismatch: inferred type is Duration but TemporalAmount! was expected 이런 컴파일 애러를 확인 했다 fun generateToken(subject: String, email: String, role: String, expirationPeriod : Duration): String{ val key = Keys.hmacShaKeyFor(secret.toByteArray(StandardCharsets.UTF_8)) val now = Instant.now() val claims: Claims = Jwts.claims() ..