헐레 벌떡 nginx rewrite, redirect 써보기

원래는 긴급하게 작업을 해야 할 이유가 거의 없긴 하지만, 갑자기 오늘 불현듯이 인프라 설정을 바꿔야 했는데, 그 이유는 현재 서비스 중인 프로젝트의 플랫폼이 레거시와 2년전의 신규 플랫폼, 다시 최신의 플랫폼 총 3가지를 쓰고 있는데, 아무래도 서비스가 워낙 많고, 플랫폼 전환 하려면, 일정을 받아야 하는데, 그게 마음대로 쉽지 않다 보니 2년전의 플랫폼도 어느새 레거시가 되었다.

그런 작업을 계속 해오고 있는데, 오늘 작은 실수를 발견 하게 되어, 긴급하게 처리를 하게 되었다.

그 처리는 특정한 uri path로 접근을 하지 못하게 막거나? 아니면, 정상적인 경로로 이동 시켜야 하는 일이었다.

사실, nginx에서는 그게 그렇게 어렵진 않은데, 중요한 부분은 nginx를 빌드 하여 사용하는 경우 기본 모듈에 rewrite가 없고, rewrite 모듈을 사용하려면, 해당 모듈에서 참조하는 pcre 의존 모듈이 필수적으로 필요하니, 꼭 참고 해야 한다. (nginx-rewrite)

중요한건 사실 uri path가 그렇게 어렵진 않은데, 순간적으로 당황하고, 뭔가 요즘 들어 항상 루즈한 루틴에 살았는데, 갑작스레 긴박함 + 재미가 있었다. (팀원들 여러명이 이렇게 하는 게 좋겠다. 저렇게 하는게 좋겠다. 하는 이야기를 자주 하는데, 그런 재미가 긴박할 수록 더 재미나고, 성장을 하게 만든다.)

문제는 위에서도 말했다시피, 단순한 경로 실수인데, 이를 고치기 위해 처리 하는 방법은 총 세가지다.

  1. 특정 패턴에 맞춰서 해당 경로의 요청이 오면, 404 not found를 리턴 한다. (사용자는 에러 페이지를 보게 된다.)
  2. 경로가 잘못 되었더라도, 정상적인 경로로 rewrite해준다.
  3. 경로가 잘못 되었으니, 정상적인 경로로 redirect한다.

우리는 1번을 처음에 말하고 있었지만, 그럼에도 불구하고, 서비스 개발자는 사용자 친화적이어야 하고, 친절함을 베푸는 것이 좋다고 팀장님이 말씀하셨고, 우리는 2번, 3번으로 방향을 전환했다.

2번의 방법으로 해결 한다고 생각 하자. 예시는 다음과 같다.

문제의 경로

  • 사용자가 http://seungdols.dev/new-board/1로 인입을 하면 안된다고 해보자. (정상적인 경로는 /board/:boardNumber

    • 즉, new-board/:boardNumber의 경로로 오게 된다. 이 경로를 막고 원래 페이지로 보내보자.

rewrite의 해결 방법

rewrite regex replacement [flag];

위의 형식으로 작성을 하면 된다. 해당 구문이 나올 수 있는 곳은 server, location, if 구문 안에서 나올 수 있다.

플래그는 아래와 같다.

  • last

    • 현재 블록 안에서 rewrite 작업을 하고, 다음 작업 처리를 진행 한다.
  • breeak

    • 현재 블록 안에서 rewrite 작업을 한 뒤에, 처리를 종료 한다. 하지만, rewrite 다음에 rewrite가 아닌 다른 작업까지는 실행 한다. (무한 반복 실행을 방지함.)
  • redirect

    • 302 temporary redirect를 하게 된다.
  • permanent

    • 301 permanent redirect를 하게 된다.

사실 위의 플래그를 잘 모르고, 처음에 아래와 같이 작성 했었다.

사실 break는 대충 감으로 넣었는데, 막상 다시 집에 돌아와 보니 flag만 바꿔도 되는건데 착각 했다.

이 부분은 밑에서 다시 토로 하도록 하겠다!

해결은 아래와 같이 했다.

rewrite ^/new-board/(.*)$ /board/$1 break;

위 처럼 하게 되면, 사용자가 다음과 같이 접속 해도, 정상적인 페이지가 나온다. 하지만, 문제는 uri path가 잘못된 경로인데, 여전히 그대로 남아있게 된다. 이는 잘못된 주소를 계속 인입 하게 만드는 경향 있다.

그래서 rediect하는 방법으로 정했는데, 왜 flag를 제대로 못봤을까? ㅠㅠ 그래서 아래 방법으로 처리 했다.

location redirect의 방법

location ~ regex pattern {
  return [redirect code] redirect path;
} 

위와 같이 작성하면 되는데, redirect code는 301, 302로 하면 된다.

301과 302의 차이는 브라우저 캐싱을 하는지? 안하는지?의 차이이다. 선택적으로 하면 되는데, 나는 302로 결정 하고, 아래와 같이 해결 했다.

location ~ ^/new-board/(.*)$ {
  return 302 $scheme://$host/board/$1;
}

위 처럼 작성 해서 해결 했는데, 사실 위의 rewriteflag만 제대로 봤어도, flag만 보고 해결 했을 텐데 좀 아쉬웠다.

그래도 이렇게 기억에 남아서 정리를 하게 되었다.

역시 공부를 해야 되는 구나 싶었다. 물론, 이렇게 또 한번 공부 하게 되었다.

간만에 그래도 재밌게 긴급하게 처리 했다.

참고


[Seungdols]
Written by@[Seungdols]
I'm interested in talking to other developers. So, I write a post on my blog.

GitHubTwitter