본문 바로가기
반응형

Develop223

[HTTP] Accept-Charset은 왜 deprecated 되었나 1. Accept Charset 설정 HTTP 헤더의 Accept에 "application/json;charset=UTF-8"값을 넣기 위해 아래와 같은 코드를 작성했다. 여기서 Accept는 클라이언트가 처리할 수 있는 미디어 타입을 알리기 위해 사용한다. IntelliJ가 노란 줄로 표기해 주면서 deprecated 된 코드임을 알려주었다. HttpHeaders headers = new HttpHeaders(); headers.setAccept(List.of(MediaType.APPLICATION_JSON_UTF8)); deprecated 된 사유에 대해 친절하게도 Spring이 주석을 달아두었다. 아래와 같은 내용이 적혀있었다. Deprecated as of 5.2 in favor of APPLIC.. 2023. 5. 2.
[Kotest] 오버로딩한 메서드 테스트하기 (feat: slot) 현재 우리 팀에서는 모종의 이유로 애플리케이션 코드는 Java, 테스트 코드는 Kotest로 작성하고 있다. 오늘은 테스트 코드를 작성하다 겪은 일에 대해 작성할 예정이다. (예제 코드는 문제 상황과 유사하게 만든 코드일 뿐, 실무 코드와는 관련이 없습니다.) 자바에서는 한 클래스 내에서 이름이 같은 메서드를 중복으로 정의할 수 없다. 하지만 '메서드 오버로딩'을 통해 매개변수의 개수나 타입 등을 다르게 하면 같은 이름의 메서드를 작성하는 것이 가능하다. 메소드 내부 구현은 상황에 따라 달라지겠지만 오늘은 아래와 같은 코드에 대한 테스트 코드를 작성하려고 한다. public class Order { public void order(OrderRequest orderRequest) { order(orderR.. 2023. 3. 5.
[Java] 스프링 부트를 제거해서 생긴 일 😄 개요 깃허브 프로필에 블로그 최신 포스트를 업데이트 시켜주는 간단한 토이 프로젝트를 만들었다. (현재 이 프로젝트는 최소한의 기능만 만들고 업데이트를 중단하고 있다. 나중에 회사 적응이 끝나고 시간적으로 여유가 난다면.. 다시 개선할 예정이다.) 처음에는 Spring Boot를 이용하다가 최대한 간소화 시키기 위해 제거했다. 그 과정 중에서 겪은 오류에 대해서 정리해보려 한다. 자바만으로도 당연히 되겠지, 라고 생각했던 기능 중 알고보니 스프링/스프링 부트가 담당했던 기능! 을 기억해두기 위한 포스팅이다. 👿 jar 파일에서 클래스를 못 찾는다? GitHub Action 스크립트를 작성할 때 jar 파일을 생성하고, 이 jar 파일을 실행하는 형식으로 만들었다. Spring을 적용했을 때는 무사히 동.. 2023. 2. 5.
[Java] replaceAll 대신 replace 사용하기 🙂 개요 String에서 흔히 사용하는 메서드 중에서는 replaceAll라는게 있다. 다들 알다시피 replaceAll은 특정 문자를 다른 문자로 대치할 수 있게 해주는 아주 편리한 메서드이다. 그러다 replaceAll보다는 replace를 사용하는 것이 좋다는 이야기를 듣게 되어 사실인지 살펴보기 위해 해당 포스팅을 작성하게 되었다. 🤓 간단 테스트 먼저 replace에 대해 흔히 하는 오해를 바로 잡고 가야한다. replaceAll 메서드가 따로 있다보니 replace는 일치하는 첫 부분 또는 일부만 대체해 주는건가? 라고 착각할 수 있다. 예를 들어 A를 B로 대체한다고 가정할 때, AA가 BA로 대체될 거라고 착각한다. 하지만 실제로는 BB로 대체된다. (참고로 여러 일치하는 문자열 중 첫 부.. 2023. 1. 22.
[Java] 동시성 이슈 해결하기 (1) 같은 계좌를 이용하는 A와 B라는 이용자가 있다고 가정한다. 동일한 시간에 A는 카드를 이용해 상품을 결제했고, B는 은행 어플을 통해 계좌이체를 했다. 대략의 플로우를 상상해보면 아래와 같다. A와 B는 같은 시간에 잔액을 조회했다. A는 40,000원을 결제하여 계좌에 남은 잔액인 60,000원을 반영하였다. 같은 시각, B는 20,000원을 계좌 이체하였다. B의 처리 속도가 약간 늦어져 A가 계산된 금액 반영을 한 뒤에야 B의 계산된 금액을 반영했다. 한 계좌에서 각각 40,000원과 20,000원이 결제되었으니 잔액은 40,000원이 남아야한다. 하지만 현재 80,000원이 남은 상태임을 확인할 수 있다. 이는 계좌라는 같은 자원에 여러 사람이 동시에 접근하기 때문에 발생하는 문제이다. 다양한 .. 2022. 12. 9.
[Spring/AOP] JDK Dynamic Proxy vs CGLIB Proxy 목차 JDK Dynamic Proxy vs CGLIB Proxy JDK Dynamic Proxy CGLIB Proxy JDK Dynamic Proxy vs CGLIB Proxy Spring AOP와 proxy Spring에서 사용하는 proxy Spring Boot에서 사용하는 proxy 왜 진작 CGLIB을 이용하지 않았을까? 1. JDK Dynamic Proxy vs CGLIB Proxy 💣 Spring에서는 프록시를 이용해 AOP를 지원한다. (AOP를 모른다면 이 링크를 참고하자. Spring의 대표적인 AOP인 @Transactional과 AOP에 대한 간략한 설명을 담았다.) JDK Dynamic Proxy, CGLIB 두 가지 방식을 사용하는데 왜 프록시 종류가 2가지나 있는지, 언제 어떤 .. 2022. 11. 23.
[JPA] @Query와 @Transactional을 꼭 같이 써야하나요?🤔 😄 서론 지난 번에 deleteAll과 관련해 N+1 문제가 발생했었다. 그 과정에 @Query를 이용해 직접 JPQL을 작성하여 해결했는데 (🔗관련 글 링크) 한가지 의문이 생겼다. 해당 문제를 해결하기 위해 다양한 문서들을 찾아보았는데 많은 예제에서 JPQL을 사용할 때 @Transactional 어노테이션을 붙이고 있었다. 안 붙여도 잘 동작하는데 왜 그랬을까? 원인을 찾아보기 시작했다. 😏 Repository 구현체와 트랜잭션 우리가 JPA를 사용해서 ***Repository 클래스를 만들 때 일반적으로 Repository나 JpaRepository를 확장한다. public interface ReminderRepository extends Repository { // ... } Custom Rep.. 2022. 11. 17.
[JPA] delete문이 N개가 발생한다고요?😱 💥 원인 발생 현재 진행중인 프로젝트에서 deleteAllByXXX를 호출하자 delete가 N개 나가는 현상이 발생했다. 왜 여러개가 나갈까? 왜 한번에 삭제되지 않는걸까?를 찾아보게 되었다. 📝 원인 분석 deleteAll이 어떤 식으로 동작하는지 확인하기 위해 아래와 같은 과정을 거쳤다. 일단 저희 Repository에서는 Repository를 extends하고 있기 때문에 해당 클래스로 살펴보았다. 구현체를 찾아 따라가다보니 SimpleJpaRepository 다다르게 되었다. 내부 구현을 확인해보니 delete를 for문을 돌면서 호출했다.😱 반면에 deleteAllInBatch는 여러번 호출하는 것이 아닌 한번에 호출하고 있었다. @Repository @Transactional(readOnly.. 2022. 11. 13.
[Java] volatile 키워드 (feat. Atomic & Concurrent) 😵 서론 멀티 스레드로 인한 동시성 문제를 해결하기 위해 Java는 synchronized 키워드와 Atomic 타입이 있다고 알려져있다. 그런데 Atomic 타입은 왜 Thread-safe하다고 할까? 이 이유에 대해서 찾다가 volatile이라는 키워드에 대해 알게 되었다. 이번 포스팅에서는 해당 키워드에 대해 파헤쳐보려고 한다. 😎 Atomic & Concurrent & volatile 예제를 살펴보기 위해 AtomicInteger의 내부 코드를 가져왔다. 특별할 것 없어 보이지만 value에 volatile이라는 키워드가 붙는다는 점이 눈에 띈다. AtomicBoolean, AtomicLong도 살펴봤는데 모두 volatile 키워드가 붙었다. public class AtomicInteger ex.. 2022. 11. 9.
반응형