Programming/Java
JAVA 중복 처리 방지 방법
d-e-v-j
2024. 8. 23. 03:00
반응형
JavaScript에서 중복 실행이 방지가 안되어 있다면, JAVA에서 해주면 된다.
시스템적으로 볼때 JavaScript에서 방지하는게 더 효율적이라고 생각 되지만,
타사의 화면과 우리의 Backend를 연결하다보면 어쩔수 없이 JAVA에서 해야 되는 경우가 많다.
이번엔 JAVA에서 중복 처리 방지하는 방법에 대해서 알아보자
1. 식별자 사용(UUID)
고유한 식별자를 생성하여 Request에 포함
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
public class RequestHandler {
private Set<String> processedRequests = new HashSet<>();
public synchronized String handleRequest(String requestId) {
if (processedRequests.contains(requestId)) {
return "Duplicate request, ignoring.";
}
processedRequests.add(requestId);
// 실제 작업 수행
String result = performAction();
return result;
}
private String performAction() {
// 실제 작업 로직
return "Action performed successfully";
}
public static void main(String[] args) {
RequestHandler handler = new RequestHandler();
String requestId1 = UUID.randomUUID().toString();
System.out.println(handler.handleRequest(requestId1)); // 정상 처리
// 동일한 ID로 다시 요청 시도
System.out.println(handler.handleRequest(requestId1)); // 중복 처리, 무시됨
}
}
2. Session 또는 메모리에 상태 저장
Session이나 메모리에 요청 상태를 저장하고 동일한 요청이 다시 들어오면 무시한다.
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
public class RequestHandler {
private ConcurrentMap<String, String> requestStatusMap = new ConcurrentHashMap<>();
public String handleRequest(String requestId) {
if (requestStatusMap.containsKey(requestId)) {
return "Duplicate request, already processed.";
}
requestStatusMap.put(requestId, "Processing");
// 실제 작업 수행
String result = performAction();
requestStatusMap.put(requestId, "Completed");
return result;
}
private String performAction() {
// 실제 작업 로직
return "Action performed successfully";
}
public static void main(String[] args) {
RequestHandler handler = new RequestHandler();
String requestId1 = "request1";
System.out.println(handler.handleRequest(requestId1)); // 정상 처리
// 동일한 ID로 다시 요청 시도
System.out.println(handler.handleRequest(requestId1)); // 중복 처리, 무시됨
}
}
3. 데이터베이스 기반 중복 방지
데이터 베이스에 요청을 저장하고, 동일한 요청이 중복으로 들어오는 것을 방지한다.
이것은 복잡해 보일수 있지만, 여러 서버 인스턴스가 있는 분산 환경에서 사용하기 용이하다.
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
public class RequestHandler {
public String handleRequest(String requestId) throws Exception {
try (Connection conn = getConnection()) {
if (isRequestProcessed(conn, requestId)) {
return "Duplicate request, already processed.";
}
markRequestAsProcessed(conn, requestId);
// 실제 작업 수행
String result = performAction();
return result;
}
}
private Connection getConnection() throws Exception {
// 데이터베이스 연결 생성 (예시)
return DriverManager.getConnection("jdbc:h2:mem:test", "sa", "");
}
private boolean isRequestProcessed(Connection conn, String requestId) throws Exception {
String query = "SELECT COUNT(*) FROM processed_requests WHERE request_id = ?";
try (PreparedStatement stmt = conn.prepareStatement(query)) {
stmt.setString(1, requestId);
try (ResultSet rs = stmt.executeQuery()) {
if (rs.next()) {
return rs.getInt(1) > 0;
}
return false;
}
}
}
private void markRequestAsProcessed(Connection conn, String requestId) throws Exception {
String insert = "INSERT INTO processed_requests (request_id) VALUES (?)";
try (PreparedStatement stmt = conn.prepareStatement(insert)) {
stmt.setString(1, requestId);
stmt.executeUpdate();
}
}
private String performAction() {
// 실제 작업 로직
return "Action performed successfully";
}
public static void main(String[] args) throws Exception {
RequestHandler handler = new RequestHandler();
String requestId1 = "request1";
System.out.println(handler.handleRequest(requestId1)); // 정상 처리
// 동일한 ID로 다시 요청 시도
System.out.println(handler.handleRequest(requestId1)); // 중복 처리, 무시됨
}
}
4. 타임스탬프와 제한시간 사용
Request에 타임스탬프를 부여하고, 일정 시간내에 동일한 요청이 반복되면 무시한다. 가장 직관적으로 이해가 쉽지만, 네트워크상의 오류로 중복요청의 타임스탬프가 동일하게 부여된다면 에러가 발생할 수 있다.
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
public class RequestHandler {
private ConcurrentMap<String, Long> requestTimestamps = new ConcurrentHashMap<>();
private static final long REQUEST_TIMEOUT_MS = 5000; // 5초
public synchronized String handleRequest(String requestId) {
long currentTime = System.currentTimeMillis();
if (requestTimestamps.containsKey(requestId)) {
long lastRequestTime = requestTimestamps.get(requestId);
if (currentTime - lastRequestTime < REQUEST_TIMEOUT_MS) {
return "Duplicate request, ignoring.";
}
}
requestTimestamps.put(requestId, currentTime);
// 실제 작업 수행
String result = performAction();
return result;
}
private String performAction() {
// 실제 작업 로직
return "Action performed successfully";
}
public static void main(String[] args) {
RequestHandler handler = new RequestHandler();
String requestId1 = "request1";
System.out.println(handler.handleRequest(requestId1)); // 정상 처리
// 동일한 ID로 5초 이내에 다시 요청 시도
System.out.println(handler.handleRequest(requestId1)); // 중복 처리, 무시됨
}
}
이 방법들은 JAVA 서버측에서 중복 요청을 방지하는데 많이 쓰이는 방법들이며,
상황에 맞게 알맞은 방법을 선택해서 사용해 보자.
728x90
반응형
LIST