Java (22) 썸네일형 리스트형 XSLT로 XML 데이터를 HTML로 변환해 JSP로 출력 해보기 레거시 프로젝트를 진행하면서 XSLT 기반 화면 렌더링을 처음 마주했던 경험이 있었다. XML을 단순히 데이터 저장으로만 인지하고 있던 나는,“이걸로 화면도 그리네?” 하며 굉장히 생소하고 흥미로웠다. 국내에서는 사용하는 예도 적고 자료가 많지 않아,직접 DOM 구조를 보면서 XSLT와 HTML의 매핑 관계를 하나씩 파악해야 했다. 이 과정을 통해 “데이터와 화면을 이렇게 분리할 수도 있구나”라는 새로운 시각을 얻을 수 있었다. 이번 포스팅에서는 바로 그 경험을 바탕으로,XSLT가 무엇인지, XML을 어떻게 HTML로 변환할 수 있는지 간단한 예제를 통해 정리해보려 한다.XSLT란?XSLT(Extensible Stylesheet Language Transformations)는XML 데이터를 원하는 형태(.. 실행 계획(Explain Analyze)으로 보는 SQL 성능 튜닝: 병목 구간 제거하기 쿼리 실행 계획 (Query Plan) 이란?쿼리 실행 계획은 데이터베이스 관리 시스템(DBMS)이 SQL 쿼리를 어떻게 실행할지에 대한 절차를 나타낸 설계도이다.우리가 SQL을 실행하면 결과만 반환되지만, 그 내부에서는 어떤 인덱스를 사용할지, 어떤 방식으로 테이블을 읽을지, 어떤 순서로 조인을 수행할지 같은 복잡한 의사결정 과정이 일어난다.실행 계획은 이 과정을 단계별로 보여주며, 성능 병목 구간을 찾고 쿼리를 최적화하는 데 핵심적인 도구가 된다. 그리고 이 실행 계획을 만드는 두뇌가 바로 옵티마이저(Optimizer) 이다. 옵티마이저(Optimizer)란?옵티마이저는 SQL을 가장 효율적으로 수행하기 위한 최적의 처리 경로(Execution Path) 를 설계하는 DBMS의 핵심 엔진이다.컴퓨터에.. Redis 캐싱 적용과 TTL, 캐시 전략 패턴 활용기 개요프로젝트가 1차 개발을 마치고 2차 개발에 들어가던 시점, 회원 수가 200명에서 최대 2만 명까지 늘어날 수 있다는 요구사항을 받았다. 이에 따라 사용자 경험 개선과 성능 강화를 위해 Redis 도입을 검토했지만, 고객사는 추가 비용을 우려해 쉽게 동의하지 않았다. 당시 서버 환경은 AWS ECS Fargate 기반이었고, 가장 단순한 방법은 ElastiCache를 사용하는 것이었다. 하지만 비용이 만만치 않았기 때문에, 결국 비용을 줄이기 위해 EC2에 Redis를 직접 설치하는 방법을 택했다. 이 과정에서 초기 과정이라 모니터링을 따로 붙이진 못했다.하지만 고객사의 상황에 맞춰 성능 개선과 비용 절감을 동시에 가져갈 수 있었다. 오늘은 이렇게 적용된 Redis가 어떻게 구성되어 있고, 언제 사용.. open-in-view=false 환경에서 LazyInitializationException → 403 에러 전파 사례 개요오늘은 실제 프로젝트를 프런트 분들과 함께 진행하면서, 생각지도 못했던(?) 어이없는 에러를 공유하려고 한다.서비스 운영 중 특정 조회 화면에 들어가면 자꾸 로그인이 풀려 튕겨나가는 현상이 발생했다.퇴근 직전에 AWS CloudWatch 로그를 확인해 보니, 원인은 다름 아닌 LazyInitializationException.그런데 더 황당했던 건 이 예외가 프런트 쪽에서 “로그아웃”으로 처리되어 버린 것이었다.원인을 찾아보니, 함께 개발하던 분이 @Transactional 하나를 누락했을 뿐인데… 사용자 입장에선 로그아웃된 것처럼 보였던 거다.결국 @Transactional 추가만으로 해결했지만, 이 일을 계기로 “open-in-view=false일 때 왜 이런 일이 생길까?”라는 궁금증이 생겼다... Spring Boot 다중 서버 환경에서 SchedulerLock으로 스케줄러 동시 실행 제어 개요회사에서 프로젝트를 진행하던 중, ECS 기반 다중 서버 환경에서 동일한 스케줄러 작업이 동시에 실행되는 문제를 마주치게 된 적이 있었다. 각 스케줄러는 사용자 인스턴스2개 , 관리자 인스턴스 2개가 올라가 있었고 서버 인스턴스가 늘어나면서 같은 작업이 여러 번 실행되는 상황이 발생했다. 그 결과 불필요한 DB 접근, 자원 낭비, 성능 저하 같은 부작용이 우려되었다. 그때는 이 문제를 막기 위해 ShedLock + RDB 조합을 사용했다.DB 테이블에 락 정보를 저장해 두고, 한 번에 한 서버만 해당 스케줄러를 실행하도록 막는 방식이었다. 문제 자체는 해결됐지만, 지금 생각해 보면 아쉬움이 크다. 락 제어만을 위해 DB에 주기적으로 쓰기/삭제를 반복시키는 건 DB의 본래 역할(트랜잭션 데이터 관리)과.. Kafka Listener 예외 반복 실행되는 이유 그리고 해결 요즘 경매 기능 개발 중 Kafka로 입찰 메시지를 처리하고 있는데, 이상한 상황을 하나 마주했다.프론트에서 입찰 금액을 현재가 이하로 보내면, 백엔드에서는 당연히 예외를 던지게 돼 있다. 문제는 이때 Kafka 컨슈머가 해당 메시지를 계속해서 반복 실행하면서 로그가 쌓이고, 결국 장애처럼 느껴질 정도로 실행하면서 터져버렸다.로그를 보면 아래처럼 계속 같은 메시지를 읽고 실패하고, 다시 읽고 실패하는 로그가 찍힌다. 분명 예외가 발생했는데도, Kafka가 계속 같은 메시지를 소비하고 있었다.Kafka 리스너가 예외를 던졌는데, 이걸 “정상 처리되지 않았다”고 인식하고 계속 재시도하고 있었던 거다.Kafka는 메시지를 읽고, 예외 없이 끝나야 성공적으로 처리했다고 판단한다.그런데 RuntimeExcepti.. 전략 패턴에서 Object vs 제네릭, 왜 나는 제네릭을 선택했을까? 최근 개인 프로젝트(실시간 채팅 시스템)를 진행하면서 전략 패턴을 적용하는 과정에서 재미있는 고민을 하게 되었다.바로 공통 인터페이스의 파라미터를 Object로 받을지, 아니면 제네릭으로 추상화할지에 대한 문제였다. 처음에는 단순한 문제처럼 보였지만, 실제로 구조를 짜면서 생각보다 깊은 고민을 하게 되었고, 결국 제네릭 기반 설계를 선택했다. 이 글에서는 그 과정을 회고해보고자 한다.문제 배경내가 만든 프로젝트에는 여러 종류의 채팅방 생성 방식이 필요했다.AuctionChatRoomCreator : Long productId 기반 경매 채팅방 생성ProductChatRoomCreator : ProductChatRequest 기반 일반 상품 채팅방 생성GroupChatRoomCreator : GroupCh.. Spring에서 확장성을 고려한 채팅방 생성 로직 전략 패턴 적용 개선 전: 단일 메서드로 직접 처리/** 1:1 상품 채팅방 생성 or 조회 */@Transactionalpublic ChatRoomResponse createOrGetProductChat(Long productId, User buyer) { ChatRoom room = chatRoomRepository .findByTypeAndProductIdAndBuyer(ChatRoomType.DIRECT, productId, buyer.getId()) .orElseGet(() -> { Product product = productService.findById(productId); ChatRoom newRoom = ChatRoom.builder(.. 이전 1 2 3 다음