프로그래밍 언어 65

[SPRING BATCH] 1. 스프링 배치란

개요스프링 배치(Spring Batch)는 대량의 데이터를 처리하는 데 특화된 배치 프로세싱 프레임워크이다.데이터 읽기, 처리, 쓰기 과정을 간단하게 설정할 수 있게 설계되어 있다.   프로젝트 생성IntelliJ를 사용한 프로젝트 생성 방법이다.JPA, H2 Database, Spring Batch를 추가하여 프로젝트를 생성한다.// build.gradleplugins { id 'java' id 'org.springframework.boot' version '3.4.0' id 'io.spring.dependency-management' version '1.1.6'}group = 'com.temp'version = '0.0.1-SNAPSHOT'java { toolchain { ..

[SPRING BOOT] 멀티모듈 프로젝트 설계하기

개요대규모 애플리케이션에서는 유지보수와 확장성을 고려해 프로젝트를 모듈로 나누는 경우가 있다.이번 글에서는 Spring Boot 멀티모듈 프로젝트를 설계하고 구성하는 방법을 작성했다.  멀티모듈 프로젝트?멀티모듈 프로젝트는 하나의 루트 프로젝트 아래에 여러 서브모듈을 포함하는 프로젝트 구조이다.각 모듈은 독립적으로 개발 및 배포될 수 있지만, 상호 간에 의존성을 가질 수 있다. 왜 멀티모듈 프로젝트를 사용하는가?모듈화: 비즈니스 로직을 분리하여 코드 유지보수성을 높인다.재사용성: 공통 모듈을 여러 프로젝트에서 재사용할 수 있다.협업 용이성: 팀원이 서로 다른 모듈을 독립적으로 개발할 수 있다.빌드 최적화: 특정 모듈만 빌드하거나 테스트할 수 있다. 프로젝트 구조spring-multi-module-proj..

[SPRING BOOT] WebSocket과 Redis를 활용한 실시간 채팅 시스템 구축하기

개요Spring Boot와 WebSocket을 활용하면 효율적인 실시간 통신 기능을 구현할 수 있다.이번 글에서는 Redis를 추가로 사용해 메시지 저장과 자동 삭제 기능을 갖춘 채팅 시스템을 구축하는 방법을 작성했다.  구성요소WebSocket: 클라이언트와 서버 간의 양방향 통신을 가능하게 하는 프로토콜.Redis: 메시지 저장소로 활용하며 TTL(Time to Live)을 사용해 일정 시간이 지나면 메시지를 삭제.Spring Boot: WebSocket 서버를 구현하는 데 사용.  WebSocket 설정Spring Boot에서 WebSocket 서버를 구현하려면 @EnableWebSocket과 WebSocketHandler를 사용한다. WebSocketConfig.javaWebSocket 설정파일..

[SPRING BOOT] CORS 에러와 DELETE요청 해결하기

개요Spring Boot를 사용하며 DELETE 요청에서만 CORS(Cross-Origin Resource Sharing) 문제가 발생하는 경우가 있다.이번 글에서는 CORS의 기본 개념부터 Spring Boot에서 DELETE 요청과 관련된 문제를 해결하는 방법을 작성했다.   CORS ?CORS는 브라우저가 다른 도메인의 리소스에 접근할 때 보안을 위해 요청을 제한하는 정책이다.예를 들어, 클라이언트 애플리케이션이 http://localhost:3000에서 실행 중인데, API 서버가 http://localhost:8080에 있다면, 기본적으로 브라우저는 이를 다른 서버로 간주한다.CORS 문제는 요청 헤더, 메서드, 또는 인증 정보가 예상과 다를 때 주로 발생한다. DELETE 요청에서 CORS ..

[SPRING BOOT] UnrecognizedPropertyException 해결하기

개요Spring Boot를 사용하며 JSON 데이터를 직렬화/역직렬화할 때, UnrecognizedPropertyException이 발생하는 경우가 있다.이 예외는 Jackson 라이브러리가 JSON을 자바 객체로 변환하는 과정에서 예상하지 못한 필드가 발견되었을 때 발생하는데 이를 해결하는 방법에 대해서 설명하고자 한다. 문제 상황ResponseVo라는 클래스가 아래와 같이 정의되어 있을 때, JSON데이터가 정의되어 있지 않은 필드를 담고 있을 경우 에러가 발생한다.@Datapublic class ResponseVo { private String responseMessage; private String responseCode;}// JSON DATA{ responseMessage: 'suc..

[NEXT.JS] Enums(열거형)과 Constants(상수)

개요처음 개발을 할 때 변하지 않고 반복사용되는 모든 값에 대해 Constants를 사용했습니다.예를 들어 HTTP METHOD나 URL, 약관 설명 등에 대한 긴 Contents 등에 대해서입니다. Constants// HTTP METHODConst HttpMethod = { PUT: 'PUT', GET: 'GET', DEL: 'DELETE', POST: 'POST'} 그러다 다른 프로젝트들을 접하면서 HTTP METHOD나 URI 등을 Enums로 사용하는 것을 보면서 이에 대한 확실한 개념정리가 필요하다고 느끼게 되었습니다. Enumsenum HttpMethod { GET = 'GET', POST = 'POST', PUT = 'PUT', DEL = 'DEL',}  Enu..

[NEXT.JS] 없는 페이지 처리(Not Found Page)

개요Next.JS에서 없는 페이지로 이동할 때, 모든 경로에 대해 동시 처리하는 방법에 대한 내용입니다. [...not_found]동적 경로(Dynamic Route)로 설정된 페이지 파일로, URL의 일치하지 않는 모든 경로를 처리하는 데 사용됩니다.[...not_found]는 "Catch-All Route"라고 불리는 동적 경로 패턴을 의미합니다.  폴더 구조, 코드src app [...not_found] page.js not-found.tsx not-found.tsxexport default function NotFound() { return ( 페이지 없음 ..

[NEXT.JS] Dynamic Import

개요이전 개발자가 개발한 프로젝트를 보고 무지성으로 프로젝트 구조를 잡아서 개발을 수행했었는데, 프로젝트를 완성해서 정상적으로 서비스를 하고 있지만 정확히 어떤 이유로 사용하는 지 모를 코드들이 있기 때문에 NEXT.JS를 더욱 이해하기 위해 하나씩 파헤쳐보려고 합니다.  구조 설명현재 모든 app router 내부 디렉토리는 아래와 같은 구조입니다._module 디렉토리에는 각 컨테이너에서 사용하는 component들과 css를 모아놓았습니다.app - home - _module - page.tsx - page.body.tsx - contents - _module - page.tsx - page.body.tsx - notice ..

[NEXT.JS] Zustand

개요Zustand는 간단하면서도 강력한 상태 관리 라이브러리입니다. React 애플리케이션에서 전역 상태를 쉽게 관리할 수 있게 해주며, Redux와 비교했을 때 훨씬 더 간단하고 직관적인 API를 제공합니다.Zustand는 독일어로 "상태"를 의미하며, React의 Hooks를 기반으로 합니다.  특징간단한 APIZustand는 매우 간단한 API를 제공하여, 몇 줄의 코드만으로 상태를 정의하고 사용할 수 있습니다.이는 Redux와 같은 복잡한 설정 없이도 쉽게 상태 관리를 할 수 있게 해줍니다.import create from 'zustand';const useStore = create(set => ({ count: 0, increment: () => set(state => ({ count: st..

[NEXT.JS] SWR

개요SWR(Stale-While-Revalidate)은 React Hooks를 사용하여 데이터 가져오기와 캐싱을 간단하게 만들어주는 라이브러리입니다. Next.js와 함께 사용하면 매우 효율적인 데이터 페칭을 구현할 수 있습니다. SWR은 Vercel에서 개발한 라이브러리로, 최신 데이터 페칭 전략을 제공합니다.  특징자동 캐싱 및 재검증 (Stale-While-Revalidate)SWR의 이름에서 알 수 있듯이, 데이터가 오래되었는지 여부에 따라 자동으로 데이터를 캐싱하고, 백그라운드에서 재검증합니다.이는 데이터의 신선도를 유지하면서 빠른 응답을 제공합니다.import useSWR from 'swr';import axios from 'axios';const fetcher = url => axios.ge..