Http와 Https는 모두 OSI(Open System Interconnection) 7계층에서 말하는 7-응용계층(application)의 프로토콜이다.
여기서 Application 계층은 '일반적인 응용 서비스를 수행하는 역할을 담당하는 계층'으로 여러 프로토콜에 대하여 사용자 인터페이스를 제공한다고 한다.
대표적인 프로토콜로는 text기반의 Http(hypertext transfer protocol), FTP(File Transfer Protocol), SMTP(Small Mail Transfer Protocol) 등이 있다. 각각 데이터를 텍스트 기반으로 주고받는 프로토콜, 서버와 클라이언트 사이에 파일을 주고받기위한 프로토콜, 이메일을 보내기 위해 이용되는 프로토콜을 말한다.
그리고 빌드 파일이 만들어진 해당 폴더에 가서 git bash를 열고 아래 코드를 입력한다
빌드파일 내용을 EC2의 frontend 폴더로 이전해주는 코드이다.
scp -i "/c/Users/folder/.ssh/forplanbee.pem" -r * ubuntu@***.***.***.site:/home/ubuntu/tomcat/webapps/frontend/
//처음 경로는 .pem 키파일이 있는 폴더 // 그다음은 우분투 도메인 혹은 아이피 그리고 내부에 fe를 받을 폴더
//fe파일을 받을 폴더는 미리 만들어둔 상태이다
continue connecting 물음에서 yes를 입력하면 아래와 같이 build 폴더내의 파일들이 EC2로 업로드 된다.
또한 나중에 해보니 http만 사용했을때는 'https가 아니라 위험하다'는 식의 알림이 계속 뜨기도 했다.
특히 Docker에서 Ngrinder를 사용해본 경험으로 Docker기반의 배포를 꼭 하고 싶었는데 문제가 발생했다.
비용문제로 EC2는 프리티어를 사용했는데, Docker를 돌리니까 지속적으로 SSH 연결이 끊기고 리소스 부족한 문제가 발생.
즉 EC2가 Docker를 견뎌내지 못하는 문제!
도커파일도 만들고 잘 하고있었지만 프리티어로는 어려움이 있었다.
그래서 아쉽지만 Docker는 사용하지 않고, EC2에 톰캣을 설치하는 일반적인 방식의 배포를 진행하기로 했다.
1차 배포후(톰캣 배포 + Vercel 배포) 실행했을때 https를 사용해야한다는 오류 발생
Nginx를 통해 HTTPS를 연동해주기로 했다.
위를 성공해서 2차 배포하니, 지난번 팀플젝때 했던 것처럼 어찌저찌 로그인은 되지만 세션이 전혀 유지가 되지 않는 문제가 발생했다. 또한 CORS오류도 한 번 발생하여, @CrossOrigin 어노테이션 대신 전역적 CORS설정 하는 것으로 Config 파일 추가해주었다.
세션 유지 되지 않는 문제는 login시에 서버에서 세션을 만들어내긴 하지만, 다음 api들에서는 세션이 하나도 유지되지 않기때문에 발생하는 문제였다. 지난번에도 해결하지 못했던 문제였기때문에 이번엔 꼭 해결하고 싶었다.
지난번 며칠간의 CORS 설정에 재설정에도 되지 않았던 경험을 떠올렸을때, 이번에는 조금 다른 방식이 필요하다는 생각이 들었다. 내가 지금 지향하는 것은 빠른 배포 및 트러블 슈팅이기에, 다른 방법을 찾아보다가 redis를 사용해서 세션을 서버가 아닌 다른 메모리에 저장하는 방법을 선택했다.
그래서 며칠 동안 또 redis 설정을 했다. redis 설정은 다시 정리해서 올려보아야겠다.
redis 설정하면서 이번에도 느낀건 챗지피티만으로는 모든 것을 해결할 수가 없다는 것이다.
모르는 부분을 챗지피티만을 사용해서 해결하려고 하면 어느 순간 분명히 길을 잃는다. 내가 처음해보는 것들은 차라리 같은 시도를 해본 다른 블로그들을 참고해서 첫 토대를 잡고, 고쳐나가는 것만 챗지피티를 사용하는 편이 성공률이 높은 것 같다.
3차 배포후, redis에 세션이 잘 만들어져서 저장은 되지만, 다음 api에서 그 세션을 읽어오지 못해서 계속해서 세션을 생성하기만 하는 문제 발생.....이 과정에서 수많은 CookieFilter의 수정과, RedisConfig 수정과... swagger와 버전 안맞아서 버전 바꾸었다가 다시 되돌리기도 하고.. 몇번이나 EC2에 배포에 재배포를 했는지 모르겠다. 이 과정에서 자동배포라인을 구축하면 초기단계에 빠른 배포 및 추가개발에 좋겠다는 생각을 몇 번이나 한 것 같다.
그리고 n차 배포후에, 쿠키가 전달되지 않는 것이 결국은 도메인 불일치로 인한 문제라는 것을 알게되었고 (request header에 set-cookie헤더가 절대절대 붙지않았다...그게 제일 필요한데ㅠㅠ) 프론트와 백을 같은 도메인으로 통합해서 cors 문제 자체를 없애버리는 방식을 택했다.
비록 vercel을 활용한 프론트엔드의 간단배포는 물건너가서, 코드 수정하면 또 재배포해주어야하지만..
그래도 이제 안정적으로 배포에 성공했다.
그리고 도메인 이름도 vercel.app같은게 붙지 않으니 진짜 하나의 웹페이지같은 느낌을 준다.
가비아에서 도메인을 하나 샀는데, ~.site 사용료가 2500원이었다. ㅋㅋ 그래서 앞에 wherethereis라는 도메인명을 붙여서 사주었다 ㅋㅋㅋㅋ
nGrinder 테스트를 진행하면서 테스트 인원이 단 1명일때에는 코드가 정상적으로 돌아가지만, 인원이 조금만 다수가 되어도 (심지어 5명일때에도) 테스트가 진행되다가 1분이 넘어가면 Connection Refused 에러가 뜨면서 테스트 자체가 어려워졌다.
이런저런 원인을 찾아 해결해보았음에도 해결되지 않았고, 마지막 원인으로 생각되는 것은 커넥션 누수
커넥션 누수를 해결하기 전에 왜 커넥션 누수가 발생하는지 정리해두려고 한다.
Connection Pool이란?
커넥션 풀은 데이터베이스 커넥션을 매번 새로 열고닫는 비용을 줄이기 위해서 미리 일정 수의 커넥션을 만들어두고 재사용하는 저장소이다. 즉 앱 시작시 미리 n개의 연결을 만들어두고, 웹 애플리케이션에서 요청이 오면 그 중 하나를 사용하고 끝나면 반납받는 시스템이라고 한다.
Connection Pool의 작동 구조는?
서버 실행시 커넥션 풀이 커넥션을 미리 만들어둔다.
사용자가 요청을 보내면 커넥션 풀에서 하나 대여한다(getConnection)
쿼리 실행 후 완료되면 반납(close())
반납된 커넥션은 다음 요청에서 재사용된다.
커넥션 누수가 발생하는 이유?
커넥션을 빌린 후 반납하지 않으면, 계속 대여상태로 남고, 새 요청은 커넥션을 못받게 된다.
내가 커넥션 누수가 발생했다고 결론을 내린 이유는,
1. MySQL에서 sleep상태인 커넥션이 굉장히 많았고,
2. 일정 횟수 이상의 테스트를 진행한 후에는 "Too many connections, Connection is not available"에러가 발생했기 때문이다.
실제로 MySQL에서 "show processList"를 쳐보면 다음과 같이 sleep중인 수많은 processList 들을 볼 수 있었다.
스크롤이 엄청 작다....정말 많은 processList들이 sleep상태에 있음을 볼 수 있다. 100개 이상이다....
실제로 오류 해결을 위해서 챗지피티의 도움을 받았을 때에도, 위 두 가지 오류가 발생한 경우 100%의 확률로 커넥션 누수가 발생한 것일 수 있다고 말한다.
이는 애플리케이션 로직에서 커넥션 풀을 빌려서 쓴 후 반납하지 않았기 때문인데, 내부에서 커넥션 풀이 점점 고갈되어 남은 커넥션이 없기 때문이다.