트러블슈팅
문제 상황
사이트에 연결할 수 없음
ec2-43-201-66-33.ap-northeast-2.compute.amazonaws.com에서 연결을 거부했습니다.
AWS EC2에 중지해두었던 인스턴스를 다시 시작했는데 접속이 되지 않는 문제가 발생했다. 분명히 기존에 잘 작동하던 인스턴스였는데, 브라우저에서 “사이트에 연결할 수 없음” 오류가 떴다.
원인 추정과 해결 과정
1. AWS 인스턴스 상태 확인
AWS 관리 콘솔에서 인스턴스 상태는 실행 중으로 정상적으로 표기되었고, 상태 검사도 통과된 상태였다. 인스턴스 자체의 상태는 문제가 없는 듯 보였다.
2. 포트 설정 확인
80번과 8080번 포트의 인바운드 규칙이 제대로 열려 있는지 확인했으며, 설정은 이상 없었다.
3. SSH 접속 시도
chmod 400 test-server.pem
ssh -i test-server.pem ec2.compute.amazonaws.com
터미널에서 SSH 접속을 시도했다.
Permission denied (publickey,gssapi-keyex,gssapi-with-mic).
그러나 “Permission denied (publickey,gssapi-keyex,gssapi-with-mic)”라는 오류가 발생했다.
4. Pem 키 권한 문제 확인
chmod 777 test-server.pem
키 파일 권한 문제를 의심해 다음 명령어로 권한을 최대로 설정했다. 하지만 오히려 “권한이 너무 느슨하다”는 로그가 출력했다. 찾아보니 AWS에서는 보안상 Pem 키의 권한을 400
으로 설정해야 한다.
5. Pem 키 위치 문제
해당 경로에서도 잘 실행이 되었지만, 혹시 몰라서 키 파일을 다른 상위 경로로 옮겨보았다. 여전히 Permission denied
오류가 발생했다.
6. SSH 디버그 옵션 사용
ssh -i test-server.pem -v ec2-43-201-66-33.ap-northeast-2.compute.amazonaws.com
SSH 접속 시 -v
옵션을 사용해 디버그 정보를 확인했다. 디버그 레벨에 따라 -v
, -vv
, -vvv
를 사용해 정보 양을 조절할 수도 있다고 한다.
jisuyang@ec2-43-201-66-33.ap-northeast-2.compute.amazonaws.com
디버그 정보를 살펴보니, 내가 입력하지 않은 내 이름이 서버 주소 앞에 붙는 것을 확인할 수 있었다. 그래서 이 부분을 더 조사해보았다.
SSH 명령에서는 기본적으로
사용자이름@서버주소
로 사용을 한다. 사용자 이름이 생략된 경우, 로컬 시스템의 사용자 이름이 원격 서버의 사용자 이름과 같다고 판단을 한다. 그래서 내 로컬 시스템의 사용자 이름을 따라 내 이름이 붙었던 것이다.
7. 사용자 이름 명시 후 접속 성공
ssh -i test-server.pem -v ec2-user@ec2-43-201-66-33.ap-northeast-2.compute.amazonaws.com
AWS EC2 인스턴스의 기본 사용자 이름 ec2-user
를 명시한 후 다시 접속을 시도하니 성공했다.
8. 서버 프로세스 실행
java -jar ‘.jar’
서버 접속 후 확인해보니, 인스턴스 재시작 시 리눅스가 재부팅되면서 애플리케이션 서버가 종료된 상태였다. 서버를 다시 실행하고 나니 브라우저에서도 정상적으로 접속할 수 있었다.
결론
서버에 접속을 하는 과정에서 새로운 문제가 생겼었지만 근본적으로 접속을 할 수 없었던 문제의 원인은 서버를 켜지 않은 것이었다. 인스턴스를 실행시킬때 자동으로 서버가 켜졌다고 가정을 해버린 것이다. 어떻게 보면 당연한 것인데 바로 생각을 못했다는게 바보같고 웃기기도 했다.
TIL
테스트 정리 포스팅
테스트 관련 질문
단위 테스트와 통합 테스트의 차이점은 무엇인가요?
단위 테스트는 개별 클래스나 메서드의 기능을 검증하는데 중점을 둡니다. 그래서 빠르고 특정 기능에 집중할 수 있도록, 목 객체를 사용해 외부 의존성을 제거하고 대상 코드만 검증합니다. 반면에 통합 테스트는 여러 컴포넌트가 함께 동작하는지 확인하는게 목적입니다. 실제 데이터베이스와 외부 API를 사용하기 때문에 테스트 시간이 오래 걸리고, 설정이 복잡할 수 있습니다.
의존성이 있는 객체나 외부 API를 사용하는 메서드를 어떻게 테스트할 수 있을까요?
Mock 객체를 사용해 의존성을 분리하여 실제 호출을 피하고 독립적인 테스트가 가능합니다. 예를 들어, Mockito로 데이터베이스나 API를 Mocking하면, 외부 장애에 영향받지 않고 테스트 속도도 빨라집니다.
그렇다면 Mock 객체를 사용할 때 주의해야 할 점이 있다면 어떤게 있을까요?
Mock 객체는 실제 동작을 대신하는 가짜 객체이기 때문에 실제 환경과는 조금 다르게 작동할 수 있습니다. 그래서 테스트가 잘 통과해도, 실제 환경에서는 예상치 못한 문제가 발생할 수 있습니다. 그리고 너무 많이 Mock을 사용하게 되면 테스트가 코드에 강하게 의존하게 되어, 코드가 변경될 때 테스트 코드도 자주 수정해야하는 번거로움이 발생할 수 있습니다.
외부 API와 상호작용을 테스트하기 위해 Mock 보다 유리한 다른 방식이 있을까요?
실제 API와 통신하는 방식은 실제 데이터를 확인할 수 있어서 유용할 때가 많습니다. 하지만 네트워크 상태나 API 서버에 상태에 따라 테스트가 불안정해 질 수 있다는 단점이 있습니다. 그래서 Mock 서버나 가상화된 API 환경을 사용하면 일관된 응답을 제공 받아 안정적으로 테스트할 수 있습니다. 또는 API 호출의 응답을 미리 기록해두는 방식(Stub)을 사용하면 실제 API를 사용하지 않고도 비슷한 테스트를 할 수 있습니다.
테스트 커버리지가 높다고 해서 코드 품질이 보장되는 것은 아닌데, 그 이유는 무엇일까요?
단순히 테스트 커버리지는 코드의 실행 범위만을 축정합니다. 그래서 로직의 정확성까지 보장하는 것은 아닙니다. 코드 품질을 높이려면 의미 있는 테스트가 작성되어야하고, 중요한 로직이 제대로 동작하는지 확인해야합니다.
그러면 의미 있는 테스트가 무엇인가요?
테스트의 목적과 검증하는 내용을 명확히 이해하고, 실제로 코드 품질에 기여할 수 있는지를 고민하여 작성한 테스트인 것 같습니다. 전에 사용자가 입력한 데이터를 검증하는 테스트 코드를 작성한 적이 있습니다. 단순히 메서드 호출을 확인하는 것 대신, 다양한 입력 데이터가 예외 처리나 에러 메시지의 정확성을 검증하는 테스트를 추가했었습니다. 그때 잘못된 입력 데이터에 대한 처리가 올바르게 동작한다고 확신할 수 있었습니다.
테스트 코드에서 가독성을 높이기 위해 어떤 점들을 고려하시나요?
메서드 이름을 통해 테스트 의도를 명확하게 표현하고, 각 테스트가 독립적이고 일관성 있게 작성합니다. 예를 들어, Arrange-Act-Assert 구조로 작성해 테스트 코드의 흐름이 쉽게 읽힐 수 있도록 했습니다.
가독성 이외에 테스트 코드 작성 시 고려하는 다른 중요한 요소가 있을까요?
테스트 코드 설계 원칙(F.I.R.S.T)에 따르는 것이 중요한 것 같습니다. 빨리 작동할 수 있어야하고, 독립적으로 실행할 수 있어야 하며, 반복적으로 같은 결과를 반환할 수 있어야합니다.
실제 운영 환경과 테스트 환경의 차이로 인해 발생할 수 있는 문제는 어떤 것들이 있을까요? 이를 어떻게 대비하고 있나요?
운영 환경에서는 데이터베이스 속도가 다르거나, 네트워크 지연 때문에 연결 오류가 발생할 수 있습니다. 그래서 최대한 실제와 유사한 QA 환경을 구축해 운영 환경에서 문제가 생기지 않도록 테스트 하려고 합니다.
테스트 환경에서 운영 환경과 비슷하게 세팅해도 완전히 같지 않을 때 발생할 수 있는 문제가 있을까요?
운영 환경과 테스트 환경의 데이터가 다르기 때문에, 실제로 비슷한 샘플 데이터를 사용해본 적이 있습니다. 그래서 운영 환경에서 발생할 수 있는 성능 문제를 미리 발견할 수 있었습니다.