학교 API에 커넥션 재사용하기

희운·2026년 4월 23일

기존 미팀 프로젝트에서는 미팀 자체 로그인과 소셜 로그인을 사용했지만 대학생 중심으로 페르소나를 좁히기 위해 세종대학교 포털 로그인을 통해서 학생인증을 하기로했다. 사용자는 미팀을 통해서 로그인을 하면 학교 API에 요청을 보내 학교 학생인지를 검증한다. 학교 API에 요청을 보낼 경우 응답시간을 측정하고 TCP 커넥션 응답시간에 얼만큼 차지하지는 알고싶었다.

학교 API 응답시간 분석

운영서버에서 학교 포털 서버로 curl 명령어를 통해 응답시간을 분석해보았다.

{
  "DNS 조회 시간": 0.001779s,
  "TCP 연결 시간": 0.012955s,
  "SSL/TLS 핸드쉐이크": 0.030608s,
  "첫 데이터 수신(TTFB)": 0.039398s,
  "-----------------": "-----------------",
  "전체 소요 시간": 0.039451s
}

위의 결과는 누적 시간이므로 이전 결과까지 걸린 시간을 제외시키고 전체 소요시간에서 비중하는 비율을 계산해 보았다.

분석 구간누적 시간 (Cumulative)순수 소요 시간 (Duration)비중 (%)비고
DNS 조회0.0017s1.7ms4.3%도메인 IP 변환
순수 TCP 연결0.0129s11.2ms28.4%3-way Handshake
순수 SSL 핸드쉐이크0.0306s17.7ms44.9%보안 터널 구축 (가장 무거운 작업)
순수 서버 처리 (TTFB)0.0393s8.7ms22.1%API 로직 및 DB 조회
전체 합계0.0394s39.4ms100%-

전체 시간 39.4ms 중 데이터를 주고받기 위한 준비 단계(DNS + TCP + SSL)에만 30.6ms가 소요되었다. 즉, 전체 요청 시간의 약 77%가 네트워크 연결을 맺는 데 사용되고 있다. 실제 서버가 비즈니스 로직을 처리하는 시간(8.7ms)보다 연결을 만드는 시간이 약 3.5배 더 길다는 것을 알 수 있다.
물론 순수 서버 처리시간에 실제 데이터를 보내는 네트워크 시간이 포함되어 있지만 이 부분은 생략해도 대부분의 시간을 커넥션을 맺는데 많은 시간을 차지하는걸 알 수 있다.

학교 서버는 커넥션을 유지할까?

HTTP/1.1 부터는 지속적인 연결을 지원한다.
Connetion : keep-alive 헤더를 통해 커넥션을 재사용 가능하다는것을 알 수 있다.
근데 HTTP/1.1 부터는 default 가 keep-alive 이므로 헤더를 생략한다고 하는데
왜 학교 서버는 명시적으로 헤더에 넣을까? 찾아보니 서버 앞단에 보안장비나 로드밸런서에서 명시적으로 헤더에 넣어주는 경우가 있다고 한다.

curl -i -s -A "Mozilla/5.0" \
-e "https://portal.sej****.ac.kr" \
--data-urlencode "mainLogin=N" \
--data-urlencode "id=*******" \
--data-urlencode "password=*********" \
"https://***********************" | head -n 25
HTTP/1.1 200 OK
Server: Apache
Date: Mon, 27 Apr 2026 10:27:11 GMT
Content-Type: text/html; charset=UTF-8
Content-Length: 2060
Connection: keep-alive
X-ORACLE-DMS-ECID: aa7c22e1-262d-48bd-abe4-24bf5a67be31-0097724e
X-ORACLE-DMS-RID: 0

그럼 학교 서버는 커넥션을 유지한다는것을 알 수 있지만 커넥션을 몇초 동안 유지하는지는 알 수 없다. 만약에 커넥션 유지를 1초 유지한다고 가정해보면 커넥션을 재사용해서 요청을 보낼일은 적을것이다. 트래픽이 많은 경우에는 1초 동안 커넥션을 유지해도 많은 요청이 커넥션을 재사용하겠지만 현재 미팀 서비스에서는 무의미한 커넥션 유지 시간이라고 판단된다.

Keep-Alive: timeout=5, max=100 와 같이 헤더에 명시적으로 제공해 주는 경우도 존재하지만 서버쪽에서 헤더를 생략했거나, 명시적으로 공개하지 않았을 것이다. 현재 우리 미팀 서버에서는 학교 서버에서 제공하는 커넥션 timeout 시간이 어느정도 유지되는지 알아야 커넥션을 재사용하여 유의미한 성능개선을 할 수 있다고 판단했다.

학교 서버의 timeout 측정하기

학교 서버에 터미널1에서는 openssl 명령어를 사용하여 프로세스에 연결을 유지하고, 다른 터미널2 에서는 while 스크립트를 통해서 연결 상태를 1초 마다 확인해 보았다.


while true; do
  # openssl이 443 포트로 연결을 맺고 있는지 확인
  STATUS=$(lsof -i :443 | grep openssl)

  if [ -z "$STATUS" ]; then
    echo "---------------------------------------"
    echo "X [$(date +%T)] 커넥션이 끊겼습니다. (실험 종료)"
    echo "---------------------------------------"
    break
  fi

  echo "O [$(date +%T)] 연결 유지 중..."
  sleep 1
done
O [19:50:33] 연결 유지 중...
O [19:50:34] 연결 유지 중...
O [19:50:35] 연결 유지 중...
O [19:50:36] 연결 유지 중...
O [19:50:38] 연결 유지 중...
--- 생략
O [19:55:49] 연결 유지 중...
O [19:55:50] 연결 유지 중...
---------------------------------------
X [19:55:51] 커넥션이 끊겼습니다. (실험 종료)
---------------------------------------

대량 5분 20초(320) 초 동안 커넥션이 유지되는걸 알 수 있었다.
학교 서버에서는 생각보다 오랜시간 동안 커넥션을 유지하도록 되어있다.
학교 서버로 요청의 많이 가더라도 재사용 시간이 길기 때문에 많은 요청에서도 커넥션 시간을 줄일수 있다고 판단된다.

짧은 시간 안에 요청이 많을 경우

짧은 시간안에 많은 로그인 요청이 발생 경우 어떻게 될까?
만약 요청 속도 > 커넥션 반환 속도 인 경우 커넥션 재사용이 불가능하다.
이와 같은 상황은 아래와 같은 상황에서 발생한다.

위와 같은 상황이 발생할 경우 커넥션을 재사용하지 못하고 매번 새로운 커넥션을 생성해서 사용해서 요청을 보낼 것이다.
물론 현재 커넥션 사용 시간이 짧은 상황이라 위와 같은 상황이 낮은 확률로 발생할것이다.
위의 그림을 보면 요청1, 요청2, 요청3과 같은 상황에서는 동시 요청 수만큼 외부 서버와 커넥션을 맺는 것을 확인할 수 있다. 이는 문제가 될 수 있는데, 많은 커넥션 생성과 요청은 외부 API 서버에 DDOS 공격을 초래할 수 있으며, 커넥션의 TIME_WAIT 또한 문제가 발생 할 수 있다. 따라서, 외부 서버와 소통하는 커넥션을 잘 관리하는 것이 중요할 것이다.

실제로 동시 요청이 발생했을 때 서버가 새로운 커넥션을 생성하여 병렬로 처리하는지 확인하기 위해 실험을 진행했다. Apache Bench를 사용하여 10명의 사용자가 동시에 로그인을 시도하는 상황을 시뮬레이션했으며, netstat 명령어를 통해 실시간으로 확립된(ESTABLISHED) TCP 커넥션의 개수를 확인했다.

ab -n 200 -c 10 -k -p post_data.txt -T "application/json" http://localhost:8080/api/v1/auth/login/sejong & sleep 0.2; netstat -an | grep 8080 | grep ESTABLISHED
Benchmarking localhost (be patient)
tcp6       0      0  ::1.8080               ::1.53425              ESTABLISHED
tcp6       0      0  ::1.53425              ::1.8080               ESTABLISHED
tcp6       0      0  ::1.8080               ::1.53424              ESTABLISHED
tcp6       0      0  ::1.53424              ::1.8080               ESTABLISHED
tcp6       0      0  ::1.8080               ::1.53423              ESTABLISHED
tcp6       0      0  ::1.8080               ::1.53422              ESTABLISHED
tcp6       0      0  ::1.53423              ::1.8080               ESTABLISHED
tcp6       0      0  ::1.53422              ::1.8080               ESTABLISHED
tcp6       0      0  ::1.8080               ::1.53421              ESTABLISHED
tcp6       0      0  ::1.8080               ::1.53420              ESTABLISHED
tcp6       0      0  ::1.53421              ::1.8080               ESTABLISHED
tcp6       0      0  ::1.53420              ::1.8080               ESTABLISHED
tcp6       0      0  ::1.8080               ::1.53419              ESTABLISHED
tcp6       0      0  ::1.8080               ::1.53418              ESTABLISHED
tcp6       0      0  ::1.53419              ::1.8080               ESTABLISHED
tcp6       0      0  ::1.53418              ::1.8080               ESTABLISHED
tcp6       0      0  ::1.8080               ::1.53417              ESTABLISHED
tcp6       0      0  ::1.8080               ::1.53416              ESTABLISHED
tcp6       0      0  ::1.53417              ::1.8080               ESTABLISHED
tcp6       0      0  ::1.53416              ::1.8080               ESTABLISHED

예상대로 동시 요청을 보낼 경우 새로운 커넥션을 생성해서 학교 로그인 API 로 요청을 보낸다.
이렇게 동시 요청이 많을 경우 학교 서버쪽에서 DDOS 공격으로 인지할수 있기 때문에 학교 서버와 커넥션을 제한해서 재사용하는게 좋을것이다.

커넥션 풀을 사용하자

학교 서버는 대략 320초 동안 커넥션이 유지되는것을 알수 있었다.
그럼 클라이언트(미팀 서버)에서 320초 이상 커넥션을 유지하려고 하면 어떻게 될까? 이미 죽은 커넥션을 가지고 학교 서버로 요청을 보내봤자 오류가 발생할 것이다.
즉, 클라이언트만 열러있다고 판단하게 되고 결국 사용자에게 오류 응답을 제공할것이다. 또한 위의 그림과 같이 커넥션 풀 없이 동시 요청이 들어온다면 keep-alive 의 이점을 누릴수가 없다.

커넥션을 유지하기 위해 2가지 방법을 생각해 보았다.

  1. keep-alive 가 끝나기 전(약 320초)에 주기적으로 API 재요청
  2. 커넥션 풀을 미리 생성해 두고 320초 전에 새로운 커넥션 생성

1번으로 주기적으로 API 요청을 보낼경우 커넥션을 지속적으로 유지 가능하기 때문에
API 를 재요청 하려고 했지만 학교 서버의 경우 keep-alive 의 max request 값을 알 수 없기 때문에, 계속해서 요청을 보낼경우 요청 횟수가 초과되어 연결이 끊겨 버리는 경우가 발생할수 있다. 또한 학교 서버로 320초 전에 주기적으로 요청을 보내야 한다.

학교 서버는 keep-alive 헤더를 보내지 않기 때문에 max 값도 알수 없다.
timeout은 직접 실험하였을때 320초 가량 유지되었다.
이를 바탕으로 파라미터를 설정해야한다.
HikariCp 에서 idle Timeout 은 유휴 커넥션이 사용되지 않을 경우 제거하기 까지의 시간을 뜻한다.
같은 의미로 Apache HttpClient 에서는 evictIdleConnections() 파라미터를 설정하여 유휴 커넥션 타임아웃을 지정할 수 있다.
현재 학교 서버의 keep-alive timeout 은 대략 320초 정도로 측정되었기 때문에 이보다 짧은 시간 안에 미팀 서버(클라이언트)에서 먼저 커넥션을 끊어줘야 한다.
또한, DDOS 방지를 위해서 최대 커넥션의 개수를 5개로 제한하였다. 학교 서버로의 로그인 요청의 평균 응답시간은 대략 200ms 정도로 측정되었고. 초당 로그인 요청 5 * (1000 / 200) 정도로, 1초에 25개의 로그인 요청 정도면 현재로써 충분하다고 판단되었기 때문이다.

profile
기록하는 공간

0개의 댓글