분류 전체보기459 [Spring Boot] Quartz Scheduler 아래와 같은 요구사항이 있다고 가정해보자."5분에 한 번씩 A 로직이 실행됐으면 좋겠어요."그러면 간단하게 @Scheduled를 사용하면 구현이 가능할 것이다. @Scheduled(cron = "0 */5 * * * *") // 매 5분마다 실행public void ALogic() { // A 로직 log.info("@@ A Login Run");}위의 요구사항은 쉽다. "x분에 한 번" 이라는 요구사항이 명확하게 있으니까. 하지만 아래와 같은 요구사항이 있다고 가정하면 어떻게 될까?"A 로직이 동적으로 실행됐으면 좋겠어요. 사용자가 1분에 한 번으로 다섯 개를 실행시킬 수도 있고, 10분에 한 개만 실행시킬 수도 있게요."이러면 @Scheduled 만으로 구현이 까다로워질 것이다. 기본적으로 스케줄링을.. 2025. 2. 20. [JS] 로컬 스토리지와 세션 스토리지 쇼핑몰에 들어가 로그인을 하지 않은 상태로 장바구니에 담아보자. 그리고 다른 페이지를 전전하다, 다시 장바구니에 들어가보자. 그러면 장바구니는 텅 비어있는가? 아니다. 장바구니에는 아까 담아놓은 상품이 그대로 들어가있다. 서버에서 로그인하지 않은 사용자의 데이터도 관리하는 걸까? 물론 하려면 할 수는 있다. 하지만 굳이 그래야 할까? 로그인하지 않은 사용자의 데이터마저도 저장하면 그만큼 서버 자원과 네트워크 트래픽이 추가로 발생할 것이기에, 시스템에 부담을 줄 수 있다. 그러면 어떻게 해야할까? 방법은 서버가 아니라 클라이언트 측 저장소를 활용하는 것이다. 이를 통해 서버와의 통신을 최소화 하면서도, 사용자가 웹 사이트를 탐색하는 동안 장바구니에 담긴 상품을 유지할 수 있다. 이처럼 클라이언트 측 저장소.. 2025. 2. 6. [JAVA] Record란 무엇인가? 학교나 학원에서 Java를 배울 때 멤버변수는 private으로 선언하며 getter, setter 등으로 접근 가능하게 하라고 배운다. 이는 객체의 캡슐화를 위해 당연히 해야할 일이다.캡슐화 (encapsulation)객체의 속성과 메서드를 하나로 묶고, 외부에서 직접 접근하지 못하도록 제한한다. setter 함수를 통해서만 데이터를 수정하도록 해서 유효성 방지를 통해 잘못된 데이터 수정을 방지하고,내부 필드가 바뀌어도 getter/setter만 유지하면 외부 코드에는 영향이 없기에 유지보수와 확장성이 좋으며, 객체의 독립성이 유지된다. 또한 getter만 제공함으로써 읽기 전용으로 활용도 가능하다. 객체를 만들 때 getter, setter는 당연히 기재하고, 상황과 필요에 toString, equa.. 2025. 2. 4. [JAVA] 동시성있는 변수를 사용합시다. 옛날부터 포스팅하고 싶은 내용이 있었는데, 조금 귀찮기도 하고 너무 당연한 거라서 굳이 하지 않고 있었다. 그런데 바로 직전에 API에 여러 개의 요청을 동시에 보내는 테스트 코드도 작성했고 하니이어서 계속해서 포스팅하고 싶었던 내용을 작성해볼까 한다. 동시성을 제어하는 변수 주제는 제목에서 알 수 있듯 "동시성" 이다. 당연한 말이지만 우리가 만드는 어플리케이션은 단일 사용자를 위한 것이 아니다. 다수의 사용자를 위한 것이고, 그러니 다수의 사용자가 오차가 거의 없이 동시에 어플리케이션에 접근하는 것을 유의해서 개발을 수행해야 한다. 그런 것에 개념이 없던 시절이 있었다. 그 때 아래와 같은 요구사항이 있었다. 대충 설명해보자면 아래와 같다.A 서비스에는 B, C 메소드가 있다.누군가 B 메소드를 호출.. 2024. 11. 6. JUnit Test로 컨트롤러 API 테스트 (RestTemplate, MockMVC) 테스트를 할 때는 서비스단을 호출하는 경우도 있지만, 종종 컨트롤러에 있는 API를 호출하는 경우도 있다. 이는 너무 당연한 거라서 굳이 따로 포스팅을 하지 않았었다. 그런데 오늘도 PM 부장님의 요청으로 한 가지 테스트를 하기로 했다. 테스트는 별 건 아니고, 특정 API를 여러 번 찔러서 평균적으로 속도가 얼마나 걸리는지 확인해보는 일이었다. 굳이 JMeter까지 사용할 건 아닌 것 같아서, 간단하게 Test 코드를 작성하고 돌리려고 했다. 우선 테스트 대상으로 아래와 같은 간단한 API가 있다고 해보자.private static SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");@GetMapping("/date")public String date().. 2024. 11. 6. SSE를 사용해 알람 구현 비슷하지만 다른 웹 어플리케이션 두 개를 우리 팀과 다른 팀에서 각자 구현중이다. 정말 상세하게 요구사항을 하나 하나 짚어보면 엄연히 다른 웹 어플리케이션이지만, 어느정도 비슷한 어플리케이션 이니만큼 공통적인 부분은 존재한다.그리고 다른 팀은 우리 팀에 비해 인원이 월등히 많기 때문에 개발 속도가 현저히 빠르고, 이로 인해 공통적인 부분은 해당 팀의 소스코드를 참고해서 개발을 수행중이다. 어쨌든 공통적인 부분 중에는 알람 기능도 존재한다. 별 건 아니고 배치 모듈에서 이상사항을 발견하고 알람을 DB에 Insert하면, 이를 로그인한 사용자들의 화면에 띄워주는 것이다.알람 기능 역시 다른 팀이 먼저 개발을 해놓았기에 이를 참고해서 개발을 했다. 그리고 그 과정에서 SSE라는 새로운 개념을 알게 되었다. 오.. 2024. 10. 29. Redis도 네트워크 딜레이를 고려해야 한다 이번에 받은 요구사항이다.리스트 페이지에서 특정 데이터 목록을 조회한 후 상세 조회 페이지로 이동한다.상세 조회 페이지에는 "이전", "다음" 게시물 조회 기능이 존재한다.리스트 페이지에서 조회된 순서에 따라 "이전", "다음" 게시물로 이동해야 한다.위 요구사항은 조회를 할 때 사용한 파라미터를 쿼리 파라미터 등으로 넘겨 조회 조건을 유지함으로써 쉽게 구현이 가능하다. 하지만 문제가 하나 있는데, 그것은 바로 상세조회 페이지에서 "상태 변경이 가능"하고, 이 상태가 리스트 페이지에서 "조회 조건"에 포함된다는 것이었다. 예를 들어보자."댓글이 0개"인 게시글만을 필터링해서 목록을 조회했다.가장 첫번째에 있는 A 게시글에 들어간다.댓글을 달았다."다음 게시물로 이동" 버튼을 눌러 다음 게시물인 B 게시글.. 2024. 10. 28. [Mybatis] Insert 후 자동으로 생성된 PK 가져오기 게시판을 예로 들어보자.아래와 같은 테이블이 존재한다고 가정한다. DROP TABLE IF EXISTS file_info;DROP TABLE IF EXISTS board_info;CREATE TABLE board_info ( `board_id` INT NOT NULL AUTO_INCREMENT, `board_title` VARCHAR(100) NULL, `board_content` VARCHAR(2000) NULL, `writer` VARCHAR(20) NULL, `crtr_dtm` TIMESTAMP NULL, PRIMARY KEY (`board_id`));CREATE TABLE file_info ( `file_id` INT NOT NULL AUTO_INCREMENT, `board_id` INT NOT .. 2024. 9. 14. [Thymeleaf] 데이터를 동적으로 바꾸기 - replaceWith 재직중인 회사에서는 웹 UI 개발 시 거의 전부 Thymeleaf\ 사용을 선호한다. 그리고 DOM 관리에는 JQuery를, 데이터 로딩에는 Ajax를 사용하는 것을 선호한다. 사실 처음부터 웹 UI 개발을 주로 할 생각은 없었다. 원래는 백엔드 개발자가 되고 싶었고, 현재 회사도 원래는 백엔드 개발자로 들어오게 되었다. 하지만 만성 인력난에 허덕이는 중소기업의 특성상 백엔드 개발만 할 수는 없고, 제안서 작성부터 요구사항 식별, 설계, 개발, 테스트, 배포 등 전과정을 해야만 했다. 웹 UI 개발도 별로 원하지는 않았지만 어쩔 수 없이 해야하는 부분 중 하나였다. 그동안 웹 UI를 개발할 때마다 나는 한 가지 말을 입에 달고 살았다.저는 원래 웹 개발자가 아니에요. 여러 가지 뜻이 함축된 말이었다. 백.. 2024. 9. 14. Mybatis 중복 쿼리 공통화 (<sql>과 <include>) + Interceptor 이번 프로젝트에서는 4중 조인 등 복잡한 쿼리가 많은 탓에 JPA 대신 MyBatis를 채택해서 사용했다. 그리고 지금까지 MyBatis를 사용하면서 뭣도 모르고 사용하고 있었다는 사실을 눈치챘다. 그것은 바로 지금까지 를 사용한 적이 없다는 것이었다. 어찌됐던 지금이라도 알았으니 다행이라고 생각하고, 연습 및 재활용을 위해 블로그에 기록을 해놓을까 한다. 코드에서 여러 메소드에 중복된 코드가 존재하면 어떻게 할까? 당연한 말이지만 중복된 코드가 여러 군데 존재하면 유지 보수가 어렵다. 만약 해당 코드에서 문제가 발생했을 경우 동일한 모든 코드를 수정해야 하기 때문이다. 게다가 쓸데없이 코드가 길어져 가독성도 저하된다. 이를 위해 중복된 코드가 발견될 경우 메소드로 만드는 "메소드화' 리팩토링을 하곤 .. 2024. 9. 7. [Spring] 자바 이미지 핸들링 이번 프로젝트에서 개발한 웹 사이트는 이미지를 핸들링할 일이 많은 프로젝트였다. 게다가 이미지를 그냥 가져오는 것이 아니라 "특정 부위만 잘라서" 가져와야 했는데, 이를 하려다보니 아무래도 시간이 오래 걸려 "28개의 이미지가 출력되는 웹 페이지가 출력되는 데 0.2 초 내로 걸렸으면 좋겠다. 단, 성능을 위해 이미지 품질 저하는 없어야 하고 반드시 원본 이미지를 출력해야 한다." 는 요구사항을 충족할 수가 없었다. 그래서 이런 저런 방법을 사용하며 삽질을 한 끝에 해당 기능을 완료했고, 추후 필요 시 재사용을 위한 포스팅을 해볼까 한다. 프로젝트 준비우선 핸들링할 이미지를 선택하자. 구글에서 귀여운 시츄 사진을 가져왔다. 해당 사진은 D:\images\ 내에 넣어놓았다. 그리고 스프링 프로젝트를 생성.. 2024. 7. 21. [Thymeleaf] Lang 설정을 통한 다국어 페이지 제공 웹 사이트들을 들어가다보면, 아래와 같이 여러 언어를 지원하는 웹 사이트를 발견할 수 있다. 지금까지는 국내에서만 사용될 웹 사이트를 개발했기에 굳이 해당 기술을 익힐 필요가 없었다. 하지만 다음 프로젝트는 해외에서 사용될 예정이기에 한국어+영어+a 를 지원하는 웹 사이트가 필요했고, 이에 다국어 웹 사이트 개발 방법을 공부해볼까 한다. 우선 다국어 설정 전에 html에서 사용하는 메세지를 모아놓는 messages.properties 설정 방법을 알아볼까 한다. messages.properties를 사용한 텍스트 출력 자바 코드 내에서 여러 클래스에서 동시에 사용하는 변수는 static으로 만들거나 혹은 enum으로 만들어 사용하고 관리한다. THYMELEAF 개발 시에도 이렇게 여러 페이지에서 동일.. 2024. 6. 10. 이전 1 2 3 4 ··· 39 다음