퍼스널 칸반으로 생산성과 효율성 높이기

💡 이 글은 필자가 구상하고 있는 지라(JIRA)관련 포스트 중에 하나입니다. "퍼스널 칸반"이라는 책 내용이 좋아서 팀원들에게 소개하려고 작성한 글입니다. 그래서 설명 중간중간 현실에 존재하는 지라 프로젝트의 차트를 참고 삼아 붙여넣었습니다. 지라는 제가 좋아하는 도구라서 본질을 설명하기 위한 도구일 뿐이니 큰 의미를 두지 마세요!     

<퍼스널 칸반>은 린(Lean)이라는 경영 개념의 원칙과 기법을 바탕으로 한다. 이는 좋은 의사결정을 통해 가치를 창출하는 것이 중요하며, 좋은 의사결정을 위해서는 정보를 쉽게 접근할 수 있어야 한다는 것을 의미한다.

정보 접근성이 높아지면 사람들은 더 존중받는 느낌을 받고, 존중받는 팀은 쉽게 동기부여된다. 동기부여된 팀은 그렇지 못한 팀에 비해 불필요한 소통 비용도 줄어든다.

내 경험으로 볼 때, 정보를 공개하는 것만으로도 정보 접근성이 높아진다. 하지만 개인이 감당하기 어려울 만큼 정보가 넘쳐나면 필요한 정보에 접근할 확률은 오히려 떨어진다. 따라서 정보 접근성은 단순히 정보를 공개하는 것에서 그치지 않고, 핵심 정보를 쉽게 파악할 수 있도록 명확하고 체계적으로 구성되어야 한다.

이런 의미에서 정보를 한눈에 파악할 수 있도록 시각화하는 것은 중요하다. 시각화를 통해 정보를 구조적으로 파악하게 되면, 문제가 쉽게 드러나고 해결책도 찾기 쉬워진다.

칸반의 두가지 규칙

  1. 업무 시각화 → 지라 보드 만들기
  2. 진행중인 업무의 수 제한 → WIP(Work In Process) Limit

업무 시각화가 필요한 이유

그동안 해야 할 일을 엑셀 표와 같은 목록으로 관리했다면 이제 칸반으로 바꿔보자. 단순한 할일 목록을 칸반으로 전환할 때는 각각의 일들이 어떤 흐름을 가지는지 생각해봐야 한다. 완료 여부에만 관심을 갖는 할일 목록에 비해 칸반은 고려해야 할 포인트가 많다.

우선, 일감이 어디서 시작되고 어떤 흐름을 거쳐 완료되는지 알아야 한다. 이를 워크플로우(workflow)라고 부른다. 칸반은 이 업무 흐름을 구체화하고 가시화하는 것부터 시작한다. 그리고 그 흐름을 들여다보면 생각보다 많은 맥락과 정보를 알 수 있다.

업무 흐름을 관찰하다보면 충분히 알수 있는 정보들

  • 누가 무엇을 원하는지
  • 누가 무엇을 하고 있는지
  • 어떻게 그것을 하는지
  • 누구와 그것을 하는지
  • 무엇을 완료 했는지
  • 무엇을 아직 끝내지 못했는지
  • 얼마나 빨리 일을 처리 했는지
  • 무엇이 병목을 만드는지
  • 언제 그리고 왜 꾸물거리는지
  • 언제 그리고 왜 어떠한 특정 활동으로 인해 불안해 하는지
  • 무엇을 약속할 수 있는지
  • 무엇을 거절할 수 있는지

시각화된 칸반 보드는 마치 차량의 계기판처럼 필요한 정보를 한눈에 알수있다. 현재 상황을 정확히 파악하면 더 나은 의사결정도 할 수 있다. 의사결정은 경영진만 하는 것이 아니다. 우리는 매일 주어진 업무 중에서 오늘 가장 먼저 처리할 일을 선택하는 의사결정을 한다.

칸반보드는 차량의 계기판 처럼 현재 상황과 맥락을 보여주는 현황판 역할을 한다.

개인이 업무를 선택하는 기준은 다양하다. 회사의 업무뿐만 아니라 공과금을 납부하거나, 잠시 자리를 비우고 산책을 하거나, 아이를 목욕시키는 일도 매일 같이 주어진다. 이러한 일들은 상황과 맥락에 따라 우선순위가 변한다.

우리는 상황에 따라 진행할 업무를 선택한다.

특히 기한이 정해진 일(예: 고정된 날짜, 두 번째 그래프)은 정해진 날짜 안에 완료해야만 의미가 있다. 예를 들어, 크리스마스 이벤트 광고를 여름에 집행하는 것은 아무런 효과가 없다. 크리스마스 이벤트는 반드시 크리스마스 시즌에 맞춰 진행해야 한다. 숙제를 미리 한다고 항상 좋은 것은 아니다. 숙제를 하는 동안 꼭 봐야 할 경기를 놓칠 수도 있다.

시간에 따라서 일(업무)의 영향력이 달라지는 대표적인 4가지 유형

공과금을 납부하는 일(두 번째 그림)도 납부 기한을 넘기면 연체료가 발생하지만, 납부 기한 전까지는 추가 비용이 발생하지 않기 때문에 우선순위를 미뤄둘 수 있다. 일찍 해결한다고 보상이 주어지지 않는 숙제는 밀리고 밀려 한 번에 해결하는 경우가 많다.

시간에 따라서 발생하는 지연비용도 업무 유형에 따라 다양하다.

따라서 우리는 업무의 영향력, 시급성, 지연 비용등을 모두 고려해 최선의 의사결정을 해야한다.

칸반으로 일 하기

STEP1. 업무가 시작되어 완료될때까지의 가치 흐름을 만들자.

TODO → DOING → DONE

아주 단순한 흐름

보통 대부분의 일들은 단순한 흐름을 가진다. 하지만 일에 따라서 그 과정은 더 길어질수도 더 복잡해질수도 있다. 채용과정을 생각해보자.

일반적인 채용 프로세스

채용 과정에서 지원자가 오퍼를 수락하는 행위 외에도 여러 가지 이유로 이탈할 수 있다. 채용 프로세스를 시각화하면 지원자가 어느 단계에서 이탈했는지 쉽게 알 수 있어 프로세스 개선이 한결 수월해진다. 위에서 표현된 채용 과정의 흐름은 크게 성공(Accepted)과 실패(Rejected)로 나뉘지만, 더 복잡하게 표현할 수도 있다. 또한, 동일한 업무 흐름을 가지더라도 가치 흐름은 개인의 관심사에 따라 다르게 표현될 수 있다.

예를 들어, 채용 과정에서 면접관으로 참여하는 사람이라면 오퍼를 조율하는 과정보다 인터뷰와 인터뷰 후의 논의 과정에 더 의미를 두게 된다. 따라서 아래와 같은 가치 흐름을 만들 수 있다.

지원자 → 인터뷰 → 디브리핑 → 완료

실무에서 쓰이는 스토리 워크플로우

한동안 내가 몸담았던 회사에서는 위와 같은 워크플로우를 이용해 스토리를 정의했다. 꽤나 복잡하지만, 개발자인 내가 관심 있는 영역과 프로덕트 매니저, 디자이너, QA가 보는 관점에 따라 가치 흐름은 다를 수 있다. JIRA에서는 서로 다른 관점의 가치 흐름을 각기 다른 보드로 표현할 수 있다.

이제 업무 흐름을 칸반 보드에 올려보자. 다양한 방향으로 확장되는 업무 흐름도 칸반 보드 위에 올리면 단순해진다. 즉, 왼쪽에서 시작해 오른쪽으로 흘러가는 단방향으로만 표현되는데, 이 흐름이 단순하기 때문에 조절도 쉽다.

지라에서 업무흐름을 가치 흐름으로 변환하기 위해선 적절한 컬럼을 찾아 배치해야한다.

STEP2. 백로그를 만들자.

백로그는 내가 해야 하는 모든 유형의 일을 의미한다. 해야 할 일을 놓치지 않기 위해 백로그에 일감을 쌓기만 하고 구체화하는 과정을 생략하는 경우가 많다. 그러나 백로그를 관리한다는 것은 단순히 일감을 쌓는 행위가 아니라 일감을 구체화하는 행위를 의미한다.

백로그를 관리하다 보면 모호하게 정의된 일감과 명확하게 정리된 일감이 함께 존재하게 된다. 그리고 그 사이의 경계를 만들 필요가 생길 것이다. 예를 들어, 단순히 쌓아놓은 일감, 구체화가 필요한 일감(플래닝), 그리고 구체화된 일감(할일)을 구분하고 싶을 수 있다.

지라의 백로그는 메뉴가 분리되어 있다. 백로그를 사용하려면 원하는 상태값을 드래그엔 드랍해서 백로그로 옮겨둔다.

위와 같이 지라 칸반은 백로그에 워크플로우 상태를 적절히 배치하면 아래와 같이 백로그 작업에 집중할수있도록 별도의 백로그 화면을 제공한다.

백로그 작업이란 모호함을 구체화하는 과정이다. 버전 태깅과 기한 설정, 담당자 지정과 인수테스트 작성 등이 백로그 작업이다.

백로그 작업이 필요한 이유

구조적 명확성이 우리 행동에 미치는 영향을 측정하기 위한 실험이 있다. 아래 3개의 학급에 각각 다른 형태의 과제 마감일을 지정해주었고 과제 제출일이 늦어지면 감점을 받는다. 다음중 가장 높은 점수를 받은 그룹은 어떻게 될까?

  1. 고정된 마감일을 지정해준 학급
  2. 학생들이 개별적으로 마감일을 지정하도록 허용한 학급
  3. 특정한 마감일이 없이 학기 중에 언제든 과제 제출을 허용한 학급

실험 결과
1번 > 2번 > 3번 순으로 좋은 점수를 받았다. 이 실험이 주는 의미는 마감일이 중요하다는 것이 아니다. 마감일은 명확성을 대표하는 하나의 지표일 뿐이다.

우리 업무는 기한이 정해진 일감과 정해지지 않은 일감이 늘 혼재되어 있다. 이 혼재된 일감 중에서 모든 일에 기한을 정하는 것이 목표가 되어서는 안 된다. 모든 일감에 기한이 정해진 시스템은 우리에게 일을 수동적으로 하도록 강요하고, 과도한 기한 설정은 의욕을 저하시킬 수도 있다. 우리가 칸반으로 일을 하는 이유는 기한이 있던 없던 적절하게 조절하여 능동적으로 일을 하기 위함이다. 즉, 수동과 능동의 적절한 균형을 지속적으로 찾아야 한다.

결론
백로그는 일감을 쌓는것이 목적이 아니다. 백로그에 쌓인 일감을 구체화하고 일을 시작할수 있는 상태로 만드는 것이 목적이다.

백로그(Backlog) → 준비(Ready) → 할일 → 진행중 → 완료

STEP3. 진행중 업무의 개수를 제한하자

제이가르니크(Bluma Zeigrnik) 효과에 따르면 사람은 완료된 것보다 중단되거나 미완료된 생각이나 행동을 기억할 확률이 90%나 더 높다고 한다. 이는 우리 뇌가 의미를 처리하기 위해 패턴을 찾는 경향이 있어 빠진 정보에 집착한다는 것을 의미한다. 그래서 완료되지 않은 일감의 수가 증가할수록 우리 뇌는 미완료 된 일감을 끝내기 위해 관심의 경쟁을 하게 되는데, 결국엔 어느 하나 제대로 집중하지 못하고 잡념에 빠져 있는 나를 발견하게 된다. 즉, 생산성 자체를 떨어트린다.

저글링의 예를 들어보자. 처음엔 두개를 가지고 던지고 받다가 익숙해지면 점차 갯수를 늘려가게 된다. 그리고 결국 아무리 연습해도 도달하지 못하는 개수에 도달하게 되는데 개인마다 그 한계는 다를수 있지만 한계치를 넘으면 저글링 자체를 하지 못한다.

진행중인 업무를 제한(WIP Limit, Working In Process Limit)해서 동시에 처리하는 일을 막으면 아이러니하게 저글링 자체를 못하는 상황을 막기 때문에 더 많은 업무를 완수할수있다. 결과적으로 생산성이 높아지는 효과를 얻게 될것이다.

이렇게 내가 지금 해야하는 일에만 집중하게 만들면 불필요한 일을 안하게 되어 결과적으로 더 많은 일을 할수있고 효율적으로 일할수 있다.

JIRA 에서는 Min, Max 값을 조절해 WIP Limit을 조절할수있다.

칸반으로 일 할땐 생산성과 효율성 그리고 효과성을 모두 개선의 대상으로 두고 회고를 통해 균형을 찾아야한다.

생산성, 효율성, 그리고 효과성에 대한 바른 이해

생산성(productivity) – 얼마나 많은 일을 완료했는지에 관한 것(꼭 필요한 일이었는지와는 무관)

누적흐름도표가 가파르게 우상향으로 올라가면 팀의 생산성이 증가하고 있다고 볼수있다.

지라의 누적흐름도표는 우리가 얼마나 많은 일을 완료 했는지 쉽게 확인할수 있다. 그리고 도표의 기울기가 가파를수록 생산성이 높음을 의미하지만 이 지표 하나로 우리가 얼마나 효율적이고 효과적으로 일 했는지는 알수 없다.

효율성(efficiency) – 일을 얼마나 쉽게 완수 했는지에 관한 것(최대의 효과/결과를 얻는 데에도 도움이 되었는지와는 무관)

컨트롤 차트의 빨간색 기준은 전체 기간의 산술적 평균으로 이슈 하나가 끝나는데 얼마나 걸리는지를 알수있다.

지라의 컨트롤 차트는 우리가 이슈 하나를 완료하는데 얼마나 시간을 들이고 있는지 알수있다. 파란색 롤링 평균이 아래로 내려가거나 빨간색 평균 이하로 내려가면 효율적으로 일 하고 있음을 의미한다.

효과성(effectiveness) – 적합한 일(right work)을 적시(right time)에 완수 했는지에 관한 것(지속 반복이 가능한지는 또 다른 문제임)

칸반보드의 스윔레인과 필터과 그리고 자동화를 이용해 내가 해야하는 일을 효과적으로 선택할 수 있다.

지라 칸반보드는 스윔레인과 필터 그리고 자동화를 통해 다양하게 시각화를 할수있다. 시각화된 일감은 어떤 일이 구체화가 필요한지, 얼마나 지연되고 있는지, 내가 일할 여력이 있는지 다른 누군가가 나의 도움이 필요한 상황은 아닌지 다양한 정보를 파악하고 효과적으로 의사결정을 할수 있도록 도와준다.

STEP4. 일감을 당겨오기(pull)

당김(pull)은 내가 작업할 준비가 되었을때만 일감을 진행중 칸으로 끌어오는 것을 의미한다. 효과적으로 일하려면 현재 나의 상황에서 적합한 일의 우선순위를 따져서 당겨와야한다. 그리고 일감을 당길때는 WIP 제한 이상으로 당겨서는 안된다.

  • 어떤 것이 가장 급한 작업인가?
  • 회의 가기전 30분 동안 할수있는 일이 무엇인가?
  • 어떤 작업들을 함께 묶어 일괄 처리 할수 있을까?
퍼스널 칸반의 WIP 제한은 개인의 영역이지만 팀으로 움직일땐 WIP 제한은 합의가 필요하다.

퍼스널 칸반은 내 업무만 집중하기 때문에 WIP 설정에 자유도가 높지만 협업할때는 상호간의 합의가 반드시 필요하다. 일반적으로 WIP 제한은 협업자의 수 만큼으로 제한한다.

수용량과 쓰루풋에 대한 바른 이해

  • 수용량(capacity): 얼마나 많은 업무를 최대로 수용할 수 있는가? → 공간적 개념
  • 쓰루풋(throughput): 얼마나 많은 업무가 실제로 빠르게 처리되고 있는가? → 흐름의 개념
수용량은 정해진 크기에 무언가를 담는 개념으로 하루를 업무로 채울 수 있다.

우리에게 주어진 시간을 업무로 채우는 수용량의 개념으로만 생각해보면 하루 일과를 업무로 꽉 채우는 것이 가장 좋을 것이다. 하지만 업무는 채우기만 한다고 끝나는게 아니다. 채워진 업무를 완료해야 비로소 의미를 가진다. 따라서 우리 업무는 보유하는 것이 아니라 처리하는 흐름의 개념으로 이해해야한다. 즉, 수용량이 아닌 쓰루풋으로 바꿔야한다.

처리량(쓰루풋)은 도로에 비유할수있다. 양방향 4차선 도로에 상행선(좌 ← 우) 도로는 수용량이 높지만 흐름이 원활하지 않기 때문에 일정 시간동안 한 구간을 지나는 차량의 수는 많지 않다.

반면, 하행선(좌 → 우) 도로는 수용량은 적지만 흐름은 원활하다. 하지만 수용량 자체가 높지 않기 때문에 일정 시간동안 한 구간을 지나는 차량의 수(쓰루풋)는 많지 않다.

따라서 우리는 처리량을 높이기 위해 통행이 원활한 적절한 수용량을 찾아야한다. 우리의 하루 일과를 업무로 꽉 채우면 생각보다 많은 일을 완료하지 못한다. 도로에 적절한 공간이 있어야 통행이 되는 것처럼 우리의 업무 사이에도 적절한 여백과 휴식이 필요하다.

STEP5. 성찰(reflect)을 하자.

칸반은 흐름에 집중하기 때문에 일정기간이 지나면 반드시 오른쪽 끝에 그동안 내가 해온 업무들이 쌓인다.

지라에서 완료한 업무는 릴리즈 행위를 통해 한꺼번에 없애거나 자동으로 필터해서 없앨 수 도 있다.

일정기간 완료한 업무가 많다는 것은 내가 생산적으로 살았음을 의미하지만 효과적인지는 알수없다. 효과적으로 살아왔는지는 시간을 내어 스스로 질문해봐야한다.

  • 어떤 일을 특히 잘 했나?
  • 어떤 일을 행할 때 기분이 좋았나?
  • 어떤 일을 완료하기 어려웠나?
  • 적합한 일감을 골라서 적절한 시간 안에 처리했나?
  • 완료한 일이 어떤 의미가 있나?

셀프 회고는 주기적으로 하는 것이 좋다. 1주일이든 한달이든 자신만의 보드를 만들고 회고를 해보자. 지라 보드를 사용하면 자동으로 수집된 통계 데이터를 활용할 수 있어 감정적인 회고를 피하고 데이터 기반의 회고를 할수있다.

지라 보고서 활용하기

다양한 보고서를 활용해 데이터 기반으로 회고를 해보자! 프로젝트 회고와 관련된 내용은 다른 글에서 다룬다.

지라는 업무흐름(workflow)에 따라 가치흐름(보드)을 만들어 잘 사용하기만 하면 다양한 후행지표를 만들어준다. 대표적인 후행 지표가 누적흐름도표와 컨트롤 차트다. 이런 지표들은 결과를 수치로만 반영하기 때문에 일하면서 발생하는 수많은 맥락이 생략되어 있다. 따라서 지표가 이상하다 싶으면 회고 과정을 통해 그 속에 숨어있는 맥락을 찾아내야한다.

평균 수명 보고서

미해결(Resolution is Empty)된 이슈의 평균 수명 ( 현재시간 – 생성시간 )

  • 완료된 이슈가 많을수록 미해결 평균 수명은 줄어든다.
  • 프로젝트에 남은 이슈가 해결되는데 필요한 평균 리드 타임으로 예상할수있다.
  • 리드타임이 줄어들수록 고객에게 전달되는 가치 전달주기는 짧다.
  • 그만큼 회고 주기가 짧아지고 개선할 수 있는 여지가 많아진다.
  • 이슈의 평균 수명은 이상적으로는 배포 주기와 비슷하거나 배포 주기보다 작아야한다.
  • 평균 수명이 리드타임을 훌쩍 뛰어넘는 방치된 이슈가 없는지 확인한다.
  • 방치된 이슈가 많으면 일은 많은 것 같은 착시를 불러 일으킨다.

생성대비 해결된 이슈 보고서

생성 대비 해결된 이슈 보고서: 생성된 이슈 갯수와 해결된 이슈 갯수의 차이

  • 백로그가 쌓이는 속도와 해결되는 속도를 비교해볼수있다.
  • 백로그가 쌓이는 속도와 해결되는 속도가 비슷하거나 해결속도가 높아야 팀이 건강해진다.
  • 백로그가 쌓이는 속도가 해결속도보다 높으면 해결을 위한 분석이 필요하다.
  • 해결 가속도(기울기)가 일정하면 팀이 안정적임을 의미한다. 일정한 기울기가 아니라면 분석이 필요하다.

참고 및 추천 서적

워드프레스 블로그에 SSL 적용하기

4년간 방치해둔 블로그를 버릴까도 생각했지만 회사도 그만둔 김에 놀면 뭐하나… 일단 시대에 맞게 HTTPS로 서빙을 해보기로 마음먹고 시도해봤다. 일단 내가 운영하는 워드프레스 서빙 환경은 다음과 같다.

  • AWS EC2에 도커 환경구성
  • AWS EC2에 Nginx 설치하고 여러 도커 컨테이너를 멀티 호스팅

일단 SSL 인증서가 필요하다. 무료 인증서를 받기 위해 EC2에 Certbot 을 설치한다.

  • sudo yum install epel-release
  • sudo yum install certbot python3-certbot-nginx

Let’s Encrypt 에서 SSL 인증서 받기

  • sudo certbot --nginx -d miconblog.com

이렇게 서트봇을 이용해 인증서를 발급받으면 알아서 nginx 설정까지 추가해준다. (우와! 똑똑하다!)

server {
  server_name miconblog.com;

  location / {
    proxy_pass http://127.0.0.1:8888;
    proxy_set_header X-Forwarded-For $remote_addr;
    proxy_set_header Host $http_host;
  }
	
  listen 443 ssl; # managed by Certbot
  ssl_certificate /etc/letsencrypt/live/miconblog.com/fullchain.pem; # managed by Certbot    
  ssl_certificate_key /etc/letsencrypt/live/miconblog.com/privkey.pem; # managed by Certbot    
  include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot    
  ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot}
}

server {
  if ($host = miconblog.com) {
    return 301 https://$host$request_uri;
  } # managed by Certbot
    
  server_name miconblog.com;
  listen 80;
  return 404; # managed by Certbot
}

이렇게 인증서를 설정하고 nginx 를 재시작하면 짜짠~ 하고 잘 될줄 알았다. ㅎㅎㅎ 재시작후 블로그를 접속하면 CSS가 제대로 로드되지 않고 다 깨진다. 거기에 더불어 어드민 페이지에 아예 접속을 못하는 문제가 더 치명적이다.

무엇이 문제일까?

요즘은 검색보다는 chatGPT를 이용해 검색하기 때문에 이와 관련된 질의를 던졌다.

SSL 설정이후에 워트프레스 사이트에 스타일 시트를 못가져오고 이런 에러를 내고 있어.
Mixed Content: The page at ‘https://miconblog.com/’ was loaded over HTTPS, but requested an insecure stylesheet ‘https://miconblog.com/wp-content/themes/sparkling/assets/css/bootstrap.min.css?ver=6.5.5’. This request has been blocked; the content must be served over HTTPS.

그래서 얻은 대답은 블로그 설정에 사이트 주소와 워드프레스 주소를 변경하라는 둥둥… 여러가지 답을 주지만 죄다 헛방.. 근본적인 이유를 다시 생각해봤다. 아무래도 어드민을 접속하지 못하는 이유와 CSS를 로드하지 못하는 문제는 같은 원인인것 같다. 즉, 서버 랜더링하는 루트페이지를 제외하고 나머지 모든 페이지 링크들이 모두 302 무한 리다이렉션 되면서 리소스를 가져오지 못하는게 진짜 문제인게 아닐까? 뭔가 설정이 잘못된것 같은데… 오래만에 서버 관리하려니 머리가 안돌아간다. 다시 GPT 에게 질문을 던졌다.

SSL 이 없던 워드프레스에 Let’s Encrpty 로 SSL 인증서를 발급받고, nginx 설정에 아래와 같이 추가됐는데, 그 이후부터 https://miconblog.com/wp-admin/ 이런 접근은 모두 302 에러가 반복되고 있어.
(… 설정을 추가해서 질문함 …)

앗!! 이번에는 제대로 답을 준것같다. 생각해보니 Certbot 이 만들어준 nginx 설정에 http로 접속 했을때 https 로 리다이렉션하게 되는데,.. 리다이랙션이 무한히 반복되는 느낌이다.

실제로 워드프레스 설정(wp-config.php)에도 아래와 같이 리버스 프록시를 썼을때 방어하는 내용이 있다. 즉, HTTP 접속을 HTTPS로 바꿀때 무한 루프에 빠지는 문제를 해결하기 리버스 프록시를 거치면서 설정한 헤더값을 본다는 내용이다.

// If we're behind a proxy server and using HTTPS, we need to alert WordPress of that fact
// see also http://codex.wordpress.org/Administration_Over_SSL#Using_a_Reverse_Proxy
if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
	$_SERVER['HTTPS'] = 'on';
}

그런데, 나는 HTTP_X_FORWARDED_PROTO 헤더를 리버스 프록시로 설정하지 않았다. ㅎㄷㄷㄷ

location / {
    proxy_pass http://127.0.0.1:8888;
    proxy_set_header X-Forwarded-For $remote_addr;
    proxy_set_header Host $http_host;
    proxy_set_header X-Forwarded-Proto $scheme;
}

nginx 설정에 간단히 한줄을 추가했더니 뚜뚱! 해결!
드디어 나도 HTTPS로 서빙한다. 야호~~~!

도커 컴포즈(Docker Compse)로 워드프레스 블로그 만들기

오랜전부터 운영해오던 블로그가 한번씩 죽을때마다 백업을 신경쓰지 않아서 이미지들을 죄다 날리곤 했었다. 이 문제 때문에 검색을 좀 해봤더니 Docker 볼륨과 Git 을 통해 손쉽게 백업 문제를 해결하고 있었다. 왜 이 생각을 못했지? ㅎㅎㅎ 머리가 굳었어!

일단 옆지기 블로그(janeisyoung.com)를 깃헙 페이지에서 해방 시켜주기로 했다.

서버 구성

AWS EC2 인스턴스 2개를 이용해 하나는 Docker 호스트로 쓰고 있고 다른 하나는 데이터베이스 전용으로 쓰고 있다. 따라서 지금부터 쓰는 글은 데이터베이스가 원격지에 있다는 가정하에 쓰는 글이다.

데이터베이스 설정

원격 서버에 SSH 접근한 후 블로그용 데이터베이스를 생성하고 이 데이터 베이스만 접근 가능한 유저를 만들어준다.

// 루트 권한으로 MySQL 로그인
> mysql -u root -p

// DB 생성 
mysql> create database janeisyoung;

// 유저 생성
> create user janeisyoung@'172.31.%' identified by '<PASSWORD>';

// 권한 지정
> grant all privileges on janeisyoung.* to janeisyoung@'172.31.%' identified by '<PASSWORD>' with grant option;

// 권한 확인
> show grants for 'janeisyoung'@'172.31.%';

참고로 데이터베이스로 쓰고 있는 인스턴스는 AWS EC2 간에 172로 시작하는 내부 IP를 통해서만 접근하도록 제한된 상태다.

도커 컴포즈 설정

version: "3.3"
services:
  wordpress:
    image: wordpress:latest
    ports:
      - "8889:80"
    restart: always
    environment:
      WORDPRESS_DB_HOST: <DB_HOST_IP>:<DB_PORT>
      WORDPRESS_DB_USER: janeisyoung
      WORDPRESS_DB_PASSWORD: <PASSWORD>
      WORDPRESS_DB_NAME: janeisyoung
    volumes:
      - ./html:/var/www/html

도커 호스트 서버에 접속해서 docker-compose.yml 파일을 만들고 실행한다.

> mkdir janeisyoung
> cd janeisyoung
> docker-compose up -d

컨테이너가 제대로 만들어졌는지 확인해보자.

> docker ps -a
CONTAINER ID  IMAGE             COMMAND                 CREATED        STATUS        PORTS                 NAMES
5c204cc3f0a8  wordpress:latest  "docker-entrypoint.s…"  3 minutes ago  Up 3 minutes  0.0.0.0:8889->80/tcp  janeisyoung

Nginx 멀티 호스팅

도커에는 이미 여러 컨테이너 서비스가 올라가 있다. 마찬가지로 이번에 추가한 블로그도 그 중에 하나로 8889번 포트를 통해서 도커 호스트와 통신한다. 그리고 도커 호스트로 들어오는 모든 요청은 Nginx 를 통해서 각각의 컨테이너 서비스로 연결된다.

file: /etc/nginx/conf.d/janeisyoung.com.conf
---- 
server {
  listen 80;
  server_name janeisyoung.com;

  location / {
    proxy_pass http://127.0.0.1:8889;
    proxy_set_header X-Forwarded-For $remote_addr;
    proxy_set_header Host $http_host;
  }
}

이제 Nginx 를 재시작한다.

> sudo systemctl restart nginx.service

도커 볼륨을 이용한 데이터 백업

앞에서 설정한 컴포즈를 실행하면 연결 해둔 볼륨(html 폴더)이 생기는데 이 폴더는 컨테이너 안쪽의 워드프레스 루트 폴더와 연동된다. 따라서 업로드한 모든 이미지와 설치한 테마, 플러그인 등등 모든 파일이 이 곳에 저장된다.

이제 도커 컨테이너가 어떤 이유로 죽더라도 내가 쓴글은 안전하게 DB에 저장되고 업로드한 모든 이미지는 볼륨 폴더에 저장되어있으므로 언제든 똑같이 되살릴수있다. 올레~ 그리고 이 볼륨 폴더를 git 연동해서 GitHub에 주기적으로 push 하면 서버를 이전할때도 손쉽게 이전할수있다.

물론 위에서 설정한 컴포즈 설정은 도커 명령어 한줄로도 가능하다.

docker run -d --name wordpress -v $(pwd)/html:/var/www/html -e WORDPRESS_DB_HOST=<DB_HOST>:3306 -e WORDPRESS_DB_USER=<DB_NAME> -e WORDPRESS_DB_PASSWORD='<DB_PASS>' -p 8888:80 wordpress:php7.4