카테고리:

업데이트:

1. 서론

지난주에 주말을 신나게 보낸 후 월요일 아침, 나는 커피를 한잔 뽑은 후에 오늘 하루 해야할 일을 정리하고 있었다.

그런데 갑자기 멀리 계시던 앱 개발자 유진님께서 다급하게 내 자리로 오셨다.

관리툴 계정 비밀번호가 90일이 지나서 비밀번호를 변경하려고 하는데 변경이 안돼요!

원래라면 유진님 바로 옆자리의 나와 같은 서비스를 담당하시는 지우님께 물어보셨을 것 같은데 지우님께서 마침 휴가셨다.

유진님의 표정을 보니 뭔가 엄청 심각해보이시고 무척 급하고 중요한 일을 하셔야 하는데 해당 이슈로 그 일을 못하시고 있는 것 같아 얼른 처리해드린다고 했다.

2. 문제 파악

일단 유진님께서 말씀해주셨던 이슈 상황을 재현해보기로 했다.

먼저, 개발 DB에서 내 계정의 최근 비밀번호 변경 날짜를 90일 이후로 변경한 후 로그인했고, 90일이 지난 계정이므로 자연스럽게 비밀번호 변경 페이지로 이동했다.

그 후, 기존과 다른 비밀번호를 입력하여 비밀번호 변경을 시도했다.

띠용? 이게 뭐지?

비밀번호 변경을 하면 자연스럽게 로그인 처리가 되어 관리툴 메인 페이지로 이동해야 하는데 이상한 오류가 발생했다.

그래서 오류 원인을 파악하기 위해 서버 로그를 확인했는데 서버 로그에는 아무런 로그가 찍혀있지 않았다. 대신 Chrome 개발자 도구에는 다음과 같이 CORS 에러와 함께 preflight 라는 호출을 한번 더 하고 있었다.

3. 삽질의 시작

일단, 유진님께서 급하게 작업을 하셔야 하니 유진님 계정 비밀번호 변경 기한을 최근으로 변경해드려 정상적으로 로그인 되도록 설정해드렸다.

급한 불을 먼저 껐고 이슈를 해결해보기 위해 사투를 벌이기 시작했다.

🏃‍♀️ 에러에는 로그만한 것이 없지 !!

어떤 에러인지 파악하기 위해 에러가 발생하는 API 군데군데 로그를 집어놓고 재배포를 진행했다. 하지만, 아무런 로그가 찍히지 않았다…

🚩 CORS 에러 ??

어떤 에러인지 서버 로그에는 찍히지 않는 상황이라 개발자 도구의 결과만을 가지고 CORS 에러로 인한 이슈라는 가설을 세웠다.

CORS 정책은 같은 출처에서만 리소스를 공유할 수 있는 정책인데 우리 관리툴 Front-End는 React, Back-End는 Spring을 사용하고 있고 프록시가 아닌 다른 도메인으로 되어 있었기에 이 부분을 주의깊게 살펴보았다.

코드를 살펴보니 클라이언트 Origin이 AWS Parameter Store에 등록되어 있는 도메인 값과 매핑되면 리소스 공유가 허용되도록 되어 있었다. 그래서 React와 Spring이 다른 서버여도 CORS 정책에 위반되지 않았다.

🚩 preflight ??

그러면 또 다른 문제였던 preflight 문제가 아닐까라는 생각을 가졌고 이번에는 preflight로 인한 이슈라는 가설을 세웠다.

그전에 preflight라는 용어를 처음 보게 되어 검색해보았다.

preflight는 서버로 요청 보내기 전에 지금 보내는 요청이 유효한지 확인하기 위해 자체적으로 OPTIONS 메서드 예비 요청을 보내는 것이였다. 그래서 별다른 문제를 찾을 순 없었다.

4. 해결

도대체 왜!!!!!

나는 하루 종일 해당 이슈만 보고 있어 심적으로 너무 지쳐있었다.

그래서 시니어 개발자이신 진호님과 옆자리 승원님께 현재 이슈를 공유드렸고 그 자리에서 진호님께서는 다음과 같이 말씀하셨다.

서버 로그도 안찍힌다면 설마 WAF ??

WAF라는 것을 들어본 적은 있는데 사용해보지 않아서 진호님과 함께 AWS WAF의 Regex pattern sets 부분을 보았다. 해당 서비스에서는 서버로 오는 요청 URL 매핑을 확인했고 해당 URL이 없는 경우, Block 처리를 하고 있었다. 실제로 비밀번호 변경 부분이 Block 되어 있었고, Regex pattern sets에 URL이 누락되어 있었다.

그래서 비밀번호 변경 API URL을 추가하니 귀신같이 정상적으로 작동되었다.

허탈 그 잡채…. 😥

5. 의문점

나는 해결을 했지만 두 가지 의문점이 있었다.

첫째, 처음부터 누락되어 있었다면 개발 시에도 정상적으로 작동되지 않았을텐데 왜 최근에야 발견이 되었을까?

둘째, 라이브 서버는 정상적으로 작동되는데 왜 개발 서버만 정상적으로 작동되지 않았을까?

이러한 의문점을 해결하기 위해 진호님께 여쭤보았다.

첫 번째 질문에 대한 답은 최근에 AWS WAF의 Regex pattern sets를 추가하였기 때문에 누락된 것이였고, 두 번째 질문에 대한 답은 힌트만 주셨다.

그 힌트는 AWS WAF의 Web ACLs에 있는 로드밸런서였고 왜 이 로드밸런서로 인해 라이브 서버와 개발 서버의 결과가 다른지 이해하기 위해서 승원님과 함께 곰곰히 생각해보았다. 그러다가 승원님께서 답을 알게 되어 공유해주셨다.

현재 우리 관리툴 Back-End 서버는 개발 서버와 라이브 서버 배포 형태가 다르다.

개발 서버에서는 앱 API와 관리툴 API가 함께 존재하는 반면, 라이브 서버는 두 개가 분리되어 배포되고 있다. 현재 WAF는 개발 서버 그리고 앱 API 로드밸런서만 적용이 되어 있었기 때문에 앱 API와 관리툴 API가 함께 있는 개발 서버에서는 WAF에 Block 되었고, 분리되어 있는 라이브 서버는 WAF에 영향을 받지 않기 때문에 정상적으로 작동되었던 것이다.

6. 느낀점

한 번 삽질을 하니 새로운 개발 지식이나 원래 알고 있던 지식에 대해 조금 더 자세히 알게 되었다.

개발자라면 어쩔 수 없이 삽질을 경험하게 되는데 그것을 싫어하기보다는 새로운 지식을 얻게 되는 과정이라고 생각하면 스트레스는 물론 쌓이겠지만 그 스트레스에서 조금이라도 벗어날 수 있다고 생각한다.

또한, 혼자 해결할 수 있는 일보다 여럿이 함께 해결할 수 있는 일들이 더 많은 것과 팀원들 간 공유가 중요하다는 것을 깨달은 하루였다.

번외로, 그 다음날 지우님께 이러한 이슈를 공유드렸더니 바로 WAF 문제라는 것을 알고 계셨다… 😥

            
              📕 개인 기록용 블로그입니다.
              😊 오타나 잘못된 정보가 있을 경우 댓글이나 메일로 말씀해주시면 바로 수정하겠습니다! 😊
          

댓글남기기