본문 바로가기

실습72

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.
[JAVA Spring] Thread에 시간제한(Timtout) 걸기 저번 프로젝트를 진행하던 중 한 가지 문제사항에 직면했다. 우선 로직은 아래와 같다.사용자가 데이터를 업로드한다.프로그램은 데이터를 받아 큐에 임시저장한 후 사용자에게 업로드 완료 알림을 보낸다.스케줄러가 동작하며 주기적으로 큐에서 데이터를 빼 스레드에 할당해 비즈니스 로직을 실행시킨다. 이 때 문제사항이 생겼다.사용자가 데이터를 업로드할 때, 업로드된 데이터가 너무 큰 경우이다. 너무 큰 데이터를 업로드했을 때 시간이 오래 소요되는 것은 당연한 일이다. 하지만 지나치게 오랜 시간이 소요되면 어찌됐던 문제가 발생할 수 있다. 게다가 가장 중요한 문제는 위에서 사용자가 업로드한다는 데이터는 파일(엑셀 혹은 csv)인데, 엑셀의 경우 poi 라이브러리를 이용해 구현했다. 하지만 너무 큰 엑셀 파일이 업로드되.. 2024. 5. 17.
Spring Validation 프로젝트가 끝나고 종료 보고까지 잠시 할 게 없어서 인터넷을 뒤적거리며 이런 저런 개발 자료를 보던 중 처음 보는 것을 발견했다. 지금까지 Controller에서 사용자 입력을 받으면 코드 내에서 해당 입력에 대한 검증을 수행했었다. 이것이 당연하다고 생각하고 있었기 때문이다. 하지만 간단한 검증 작업은 굳이 수기로 하지 않아도 됐었다. 그냥 Spring Validation을 사용하면 알아서 사전에 설정한 검증을 수행해주는 것이었다..!!!처음 알았다..!!! 사실 입력값 검증이라는 것이 간단한 것만 하는 것이 아니기에, 이러한 라이브러리를 알게 되었어도 이를 자주 사용할지는 의문이다. 하지만 이는 단지 내 사고가 편협한 것일 수도 있고, 또한 어떤 지식이던 알아두면 좋다는 신념 하에 한 번 공부를 해볼.. 2024. 5. 7.
@DependsOn을 사용한 Bean 생성 순서 제어 너무너무너무 당연한 말이지만 빈 생성 순서는 중요하다. A빈이 B빈을 멤버 변수로 갖는다면 B빈이 먼저 선언되고, A빈이 후에 선언되어야 하는 건 당연한 일이다. 그런데 이번에 프로젝트를 진행하며 예상치 못한 상황을 맞닥뜨렸다. 우선 해당 프로젝트에서는 테이블 생성 등 DB 초기화를 굳이 별도의 쿼리로 입력하고 싶지 않아 schema.sql 파일을 통해 스키마를 사전에 정의해놓도록 설정했다. schema.sql : DB의 스키마를 정의하는 SQL로, 최초 테이블 생성 시 사용됨 data.sql : 초기 데이터 삽입 SQL로, 테이블 생성 후 필요한 초기 데이터를 삽입하는 데 사용됨 그리고 기능 중에는 아래와 같은 기능이 있었다. 간단하게 설명하면 사용자에게 요청을 받으면 해당 요청을 "대기" 상태로 저장.. 2024. 4. 10.
[JAVA] OpenCSV를 사용한 CSV 파일 만들기 이전 포스팅에 이어간다. https://123okk2.tistory.com/509 [JAVA] OpenCSV를 이용한 CSV 파싱 프로젝트 내 요구사항 중에는 아래와 같은 요구사항이 존재했다. 사용자가 엑셀 혹은 csv 파일을 서버에 업로드할 수 있을 것 사용자가 엑셀 혹은 csv 파일을 서버에서 다운로드할 수 있을 것 사 123okk2.tistory.com 이번에는 OpenCSV를 활용한 csv 파일 만들기이다. DB에서 데이터를 가져왔다 가정하고, 해당 데이터를 csv 팡ㄹ로 만들어 사용자에게 파일을 제공하는 코드를 공유하려고 한다. 코드 작성 작성 방법은 별게 없다. 그냥 String[]을 CSVReader.writeNext()의 파라미터로 입력만 해주면 된다. DownloadService.java.. 2024. 4. 1.