요즘 웹 애플리케이션을 개발하면서 자주 마주치는 친구들이 있습니다. 바로 HttpServletRequest, HttpServletResponse, 그리고 ConcurrentHashMap입니다. 특히 동시에 많은 요청을 처리해야 하는 서비스를 만들 때 이 셋의 조화로운 활용은 성능과 안정성을 좌우합니다. 오늘은 이 세 가지 요소를 중심으로 제가 최근 개발하면서 겪었던 경험과 그에 따른 고찰을 여러분과 공유하고자 합니다.
저는 최근 실시간 메시징 기능을 갖춘 웹 애플리케이션을 개발했습니다. 사용자들은 /CREATE/<Queue Name>과 같은 URL을 통해 새로운 메시지 큐를 생성할 수 있습니다. HttpServletRequest 객체는 이 요청에 대한 모든 정보를 담고 있습니다. req.getPathInfo()를 통해 /CREATE/PLAY 와 같은 경로 정보를, req.getQueryString()을 통해 URL에 포함된 쿼리 파라미터를 얻을 수 있죠. POST 요청의 경우, req.getInputStream()을 통해 요청 본문(body)에 담긴 데이터를 읽어들입니다. 이 예시에서는 JSON 형태의 데이터를 받아 Gson 라이브러리를 이용하여 JsonObject로 파싱하여 사용했습니다. gson.fromJson(sb.toString(), JsonObject.class) 부분이 바로 그 과정입니다. 받은 JSON 데이터를 처리한 후에는 HttpServletResponse 객체를 이용하여 클라이언트에게 응답을 보냅니다. 여기서 중요한 점은 동시에 여러 사용자가 큐를 생성하려고 시도할 수 있다는 것입니다.
이러한 동시 접근을 효율적으로 관리하기 위해 ConcurrentHashMap을 사용했습니다. 저는 각 큐의 이름을 키로, 큐에 대한 정보(예: 생성 시간, 현재 연결된 사용자 수)를 값으로 저장하는 ConcurrentHashMap<String, Integer> 맵을 구현했습니다. ConcurrentHashMap은 이름에서 알 수 있듯이 동시 접근에 대해 안전하게 설계되어 있기 때문에, 여러 스레드가 동시에 맵에 접근하여 읽고 쓸 수 있습니다. 만약 HashMap과 같은 일반적인 맵을 사용했다면, 동시 접근으로 인해 예상치 못한 동작이나 데이터 손상이 발생할 수 있었겠죠. ConcurrentHashMap의 사용은 이러한 위험을 방지하고 안정적인 서비스 운영을 보장하는 데 큰 도움이 되었습니다. 실제로, ConcurrentHashMap의 putIfAbsent() 메서드를 이용하여 큐 생성 요청 중복을 효과적으로 처리할 수 있었습니다. 이미 존재하는 큐에 대해서는 새로운 큐를 생성하지 않고, 기존 큐에 대한 정보를 반환하는 방식입니다.
결론적으로, HttpServletRequest와 HttpServletResponse는 클라이언트와 서버 간의 통신을 담당하는 필수적인 요소이며, ConcurrentHashMap은 다중 스레드 환경에서 안전하고 효율적인 데이터 관리를 가능하게 합니다. 이 세 가지 요소를 적절하게 조합하여 사용하면 성능과 안정성이 모두 뛰어난 웹 애플리케이션을 개발할 수 있습니다. 특히 동시성을 고려해야 하는 서비스를 개발할 때는 ConcurrentHashMap의 사용을 적극적으로 고려해 보는 것을 추천합니다. 복잡한 동시 처리 로직을 구현하는 대신, ConcurrentHashMap의 다양한 메서드들을 활용하여 간결하고 안전한 코드를 작성할 수 있습니다.