본문 바로가기

기타

[개인기록] gps 기반 출퇴근 시스템 간편 일지(3)

지난 기록

12월 초에 mvp를 만들어서 매니저님께 말씀드린 후에 팀장님 포함 보임자 회의 시에 계획을 설명해달라고 하셨다. 팀장님도 긍정적으로 검토하신다고 하셔서 그냥 들어가는 것보다는 바쁘신 분들에게 정리하여 말씀드리기 위해 ppt까지 만들었는데, 업무 때문에 계속 바쁘셔서 회의에 참석할 수 없었다ㅠ 서비스 고도화 프로젝트가 곧 오픈하는 건이 있었는데 그 일 때문에 바쁘신거겠지.. 이해하였다.

회의날에 안부르시길래 매니저님께 슬쩍 다시 말씀드렸는데 회의가 너무 오래걸려서 깜빡했다고 미안하다고 하셨다. 그 다음날 회의에 부르겠다고 하셨는데 또 안 부르셔서.. 흐음.. 긍정적으로 생각하지 않으시는데 에둘러 거절하시는건가.. 하였다. 그래도 포기할 수 없어서 로비에서 서성이는 팀장님이 보이시길래 일부러 어슬렁거리다가 화장실에 같이 따라 들어가서 손을 씻으며 인사를 드렸다. '~서비스 제안에 대해 혹시 매니저님께서 따로 말씀 안하셨을까요...?' 하고 조심스럽게 말씀드리니 '맞다~' 하시면서 간단하게 대화를 할 수 있었다.

어떻게 기획하게 되었는지, 서버 구성은 어떻게 했는지 등.. 내가 대강 계기와 해결해야 할 문제를 말씀드리니 내 개인적인 생각으로는 팀장님도 진행 의지가 있으시다고 느꼈다(나만 그렇게 느낀건가ㅠ). 이후에 매니저님이 오셔서 이야기하였는데, 정말 업무가 바빠서 그런 것이라고, 프로젝트 오픈 끝나고 여유 생기면 회의 때 부르겠다고 하셨다. 그 사이 커뮤니티(회사에서 개별적으로 팀을 꾸려 사내에서 필요한 백오피스를 사이드 프로젝트 식으로 만드는 활동이다) wrap-up이 있을 예정이라고 알고 있었는데, 내가 진행하는 것도 해당 활동의 일환으로 생각할 수 있으니 해당 회의에서 한 번에 진행하는 것은 어떻냐고 제안드렸고 좋은 생각이라고 해주셨다. 아마 12월 말 즈음에 회의 참석이 가능하지 않을까 싶다.

트러블 슈팅

회의 때까지 시간이 좀 있으니 mvp를 좀 디벨롭 해보려고 하고 있다. 로그인을 fake token으로 대체하고 있었는데, 로그인 기능을 만들 예정이고, 프론트를 react로 만들면서 대강 동작하게만 만들어놔서 routing 시에 문제점이 있었다.

nginx로 reverse proxy 띄워놓고 static resource는 build 디렉토리의 위치와 연결시켜두고, api는 url path 규칙에 따라 api 서버를 호출하게 구성해두었다. 그런데 nginx의 try_files 설정이 작동하지 않아 domain의 path를 못 찾고 nginx에서 404를 리턴하고 있었다. domain root path만 찾으면 우선 동작은 했기 때문에 놔뒀었는데, 출근 페이지에서 새로고침 시 404가 나오는 현상이 맘에 들지 않았다. location scope에서 파일 경로를 찾고 못 찾으면 root path의 index.html 파일을 serve 하는 설정인데, 결국은 경로를 못 찾아서 404를 리턴하는 것이었다.

nginx access log, error log(/var/log/nginx)를 살펴보니 directory 경로를 못 찾는 문제가 있었다.(No such file or directory) 결국 경로를 못 찾았거나 경로를 찾았더라도 파일을 못 찾았다는 것인데, root path에서 정상적으로 serving이 되었으니 결국 nginx try_files 설정의 문제가 아닐까 추측했다.

요즘 gpt에 의존하는 경향이 있어서 그냥 긁어서 gpt에 물어봤는데, 여러가지 사항들을 이야기해주었다. 최초 /etc/nginx/sites-available/default 파일의 설정은 아래와 같았다. 최초 설정에서 ssl, location 설정 등만 바꾸었기 때문에 기본 주석도 안 지운 상태로 지저분하게 되어 있었다. 그나마 조금 지운 것이 아래와 같은 내용이다.

server {
    #listen 80 default_server;
    #listen [::]:80 default_server;

    # SSL configuration
    listen 443 ssl default_server;
    listen [::]:443 ssl default_server;
    ssl on;

    ssl_certificate /etc/letsencrypt/live/{domain}/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/{domain}/privkey.pem;

    root /var/www/html;

    # Add index.php to the list if you are using PHP
    index index.html index.htm index.nginx-debian.html;

    server_name _;

    location / {
      # First attempt to serve request as file, then
      # as directory, then fall back to displaying a 404.
      root /svc/front/build;
      index index.html
      try_files $uri $uri/ /index.html;
    }

    location /api {
      proxy_pass http://127.0.0.1:8080;
      proxy_set_header Host $host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Forwarded-Proto $scheme;
    }
}

 

기본 주석에 적혀있듯이, location scope에서 nginx는 요청에 대해 파일로 시도하고, 그 다음 요청된 경로를 디렉토리로 시도하고 둘 다 실패하면 /index.html로 요청 처리하도록 설정한다. 예를 들어 요청 url이 'www.mydomain.com/app.js'라면 파일을 찾고, 디렉토리라면 디렉토리 내의 'index.html'을 반환한다. 디렉토리는 root 설정처럼 /svc/front/build다. 둘 다 실패하면 $uri 경로로 들어올 경우에 root 디렉토리의 /index.html을 반환한다.

gpt에서는 nginx 설정 점검, 권한 확인, react router 확인, 404 error page 확인 등을 알려주고, nginx reload, test, curl 명령에 의한 확인까지 알려주었다. 아무리 생각해도 root directory를 찾은걸보니 try_files 설정만 잘못된 것 같아서 의미 없는 행위인 것 같긴 했는데 하라는 대로 따라해보았다. server 블록의 root 설정이 기본값으로 사용되니 이를 제거하라고도 해보고, ssl_on은 최신 nginx에서 필요 없으니 빼보라고도 했다. 결론은 가설대로 모두 정답은 아니었다.

그렇게 gpt와 티격태격(gpt한테 이건 이러해서 정상적인 설정인데 그건 잘못된 것이 아니라고! 이런 설정이 혹시 잘못된건 아닐까?등의 질문을 던졌다..)하고 있다가, 결국 발견하고 말았다.. 오탈자가 있었다는 것을.. location 블록의 두번 째 줄에 'index index.html'을 설정해두었는데, 요청 경로가 디렉토리면 해당 디렉토리의 index.html을 찾으라는 명령어다. 그런데.. 세미콜론을 빼먹었다.. 결국 세미콜론 붙이고 nginx reload하니 정상적으로 routing되었다.(으악)

교훈(GPT야, 그럴 수 있어..)

gpt한테 다른 설정은 문제 없고 오탈자 문제였잖아!라고 따지니 항상 하는 그 말.. 죄송하다는 말과 함께 니 말이 맞다는 답변을 준다.. 문제가 무엇인지 가설을 설정하고, 해당 가설이 맞는지를 검증하는 과정까지는 맞았는데 오탈자 가설을 내가 너무 간과했었다.(자기 검열의 맹점이 역시나..) 내가 만든건 내가 오류 검증을 하기가 매우 어렵나보다.. 처음에 오탈자 있는지 계속 확인했는데도 발견을 못했다.

오늘의 교훈은 돌다리도 다시 두들겨보자. gpt 정말 좋지만 무조건적인 신뢰는 하지 말자(너 오늘 신뢰 -1점). 그래도 물어보면서 nginx 세부 설정들의 동작 방식이나 개념을 배울 수 있었던 것 같다. 불필요한 설정이나 주석들도 자신있게 지울 수 있었다. 운영 업무를 하다보면 다른 사람이 만들어 놓은 소스를 고치는 것이 쉽지 않은 일인데, '왜 이 코드를 짰을까'에 근거와 동작방식을 내가 잘 모르는 경우가 많기 때문이다. 그런 의미에서 다시금 그냥 동작하는 것에 대해서 한 번 더 고민해봐야겠다는 생각을 한다. 이유없이 존재하는 것은 없다.