전체 글

·트러블슈팅
https://github.com/ALLREVA/Allreva_BE 최근에 진행한 프로젝트이다 주제는 '공연 차대절 플랫폼' 으로 KOPIS 에서 공연 정보를 받아와서 해당 공연의 정보를 조회할 수 있고, 특정 공연의 차대절 및 수요조사 글을 등록할 수 있다 나는 트래픽이 많이 몰릴 것으로 예상되며 변경이 흔치 않은 '공연 상세 조회'에 캐싱을 도입하고자 하였다     ALLREVA 프로젝트에서 '공연' 도메인의 특성우선 캐싱 전략을 세우기 이전에 해당 프로젝트에서 캐싱을 적용하려고 하는 도메인의 특성이 무엇인지 살펴봐야한다 ALLREVA 프로젝트에서 내가 정리한 공연 도메인의 제일 중요한 특성들은 다음과 같다 정보의 갱신이 매우 드물게 발생한다우리는 KOPIS 로 '하루에 한 번' 특정 시각에 공연 데..
·트러블슈팅
초기 요구사항최종 프로젝트에서 검색을 위해 MySQL 과 ElasticSearch 의 데이터를 sync 해야했다 이를 위해 적용할 수 있었던 기술은1. Debezium 의 CDC 2. Kafka 로 원자적 이벤트 발행 가 있었는데 우리는 그중에서 2번 'Kafka 로 원자적 이벤트 발행' 을 선택하였다 CDC 기술은 스키마에 의존적인데 프로젝트가 진행되면서 컬럼이 바뀔 가능성이 매우 높다고 생각하였다또한 실시간성 역시 필요하지 않다고 판단하였으며 비용적인 부분또한 문제가 되었다 따라서 우리는 Kafka 로 원자적 이벤트 발행을 하기 위해 Polling Publisher Pattern 을 적용하였다  카프카를 걷어내야만 했던 이유하지만 배포를 하면서 Kafka 가 자꾸 죽어버리는 문제가 발생하였다.또한 K..
·트러블슈팅
트랜잭션 범위에 대한 고민 트랜잭션의 범위가 넓으면 편리할 수 있으나 읽기 성능이 저하되고, 데드락 발생 가능성이 높아진다.모든 프로젝트들이 마찬가지이겠으나 특히 티켓팅처럼 한순간에 많은 요청들이 몰리는 경우, 트랜잭션의 범위가 너무 넓다면 곤란하다. 그렇다면 트랜잭션의 범위가 지나치게 짧다면 어떨까? DB 를 사용하는 모든 상황에서 트랜잭션을 시작하고 끝맺는다면 역시 성능이 좋지 않을 것이다. 트랜잭션의 비용은 생각보다 크다. 그렇다면 적정수준이 어느정도일까? 소거법으로 트랜잭션에서 제거하는게 확실히 좋은 상황먼저 지워보자.(트랜잭션이 꼭 필요한 상황과 꼭 제거해야 하는 상황을 고려해보자) 토스 API 는 트랜잭션에서 제외하자우리 프로젝트에서 결제를 담당하고있는 토스 API..트랜잭션에서 제외하였을 때..
·Java/Java 기본
finalfinal : 값의 재할당을 막는다(불변과는 다르다)(ex. List 의 경우 final 선언을 해도 값이 변할 수 있다) 보통 service 클래스를 주입받아서 사용할 때 final 을 자주 접하였을 텐데, 함수 파라미터 앞에는 왜 final 을 붙이는 걸까? 매개변수의 재할당 금지매개변수의 재할당을 금지하기 위해서이다 예를 들어보자 int plusMethod1(int x) { x = x + 10; return x; } int plusMethod2(final int x) { // 매개변수의 재할당 금지 int result = x + 10; return result; } plusMethod1( ) 은 매개변..
·Java/Java 기본
record 란?기존 코드package number.study;import lombok.Getter;@Getterpublic final class practice { private final String name; private final int age; public practice(String name, int age) { this.name = name; this.age = age; }}  record 사용 코드package number.study;public record practice(String name, int age) {}  레코드를 사용하면 위의 코드가 아래의 코드로 변하게 된다 레코드는 보일러 플레이트 코드를 제거하기 위해 등장했다(위의 클래스..
·Java/Java 기본
의존관계 역전의 법칙 (Dependency Inversion Principle)1. 상위 모듈은 하위 모듈에 의존해서는 안된다. 상위 모듈과 하위 모듈 모두 추상화에 의존해야 한다.2. 추상화는 세부사항에 의존해서는 안된다. 세부사항이 추상화에 의존해야 한다. 의존관계 역전의 법칙을 잘 적용하게 되면 우리는 하위 모듈의 변경에 의해 상위 모듈이 영향을 받지 않도록 구현할 수 있다 단순 '추상화에 의존해야 한다'로만 DIP 를 이해해서는 안된다'상위 모듈은 하위 모듈에 의존해서는 안된다' 라는 내용 역시 적용해야 진정한 DIP 를 적용하는 것이라 할 수 있다 그렇다면 과연 상위 모듈과 하위 모듈이 뭘까? 모듈모듈이란 전체 소프트웨어 시스템을 작은 단위로 쪼개 놓은 것,작은 단위로 서로 긴밀하게 연관관계가 ..
·Java/Java 기본
@Datapublic class Member { private Long id; private String name; private int age;} 우리가 자주 마주하는 코드들이다 그런데 우리가 자주 보는 이 코드들이 항상 id 값(보통 PK) 의 타입을 long 이 아니라 Long 으로 주는 것을 알 수 있다 왜 굳이 Wrapper 클래스인 Long을 사용하는 걸까 그에 대한 이유는 null을 사용할 수 있기 때문이다 만약 id 필드의 타입을 long 타입으로 설정한 경우 id 의 default value 는 0이 된다id 의 기본값이 0 이라는 것은 문제를 초래한다id 에 '값을 선언하지 않아서 0인 경우'와 '값을 0으로 선언한 경우' 를 구분할 수 없게 된다 하지만 Wrapper ..
·Spring
우리는 스프링으로 웹페이지를 만들 때 @ModelAttribute 등을 사용하여 파라미터로 손쉽게 값을 읽어온다또한 값을 View 로 넘겨줄떄 String 타입으로 반환하는 등 세세한 내용을 신경쓰지 않고 코드를 작성할 수 있다 복잡한 Http 요청을 어떻게 객체로 자동 바인딩을 하며 View 를 String 타입으로 호출할 수 있는 것일까? 이런 편의성을 제공해주는 ArgumentResolver 와 ReturnValueHandler 에 대해 알아보자 ArgumentResolverArgumentResolver 의 정확한 명칭은 HandlerMethodArgumentResolver 이다HandlerMethodArgumentResolver 인터페이스가 정의한 메소드들을 보자 1. supportsParamet..
김관현
관현log