순회 – 그래프에서의 BFS

인프런의 영리한 프로그래밍을 위한 알고리즘 강좌를 보고 작성한 문서입니다.


그래프 순회

순회(traversal)

  • 그래프의 모든 노드들을 방문하는 일

대표적 두 가지 방법

  • BFS (Breadth-First Search, 너비우선순회)
  • DFS (Depth-First Search, 깊이우선순회)

너비우선순회 (BFS)

BFS 알고리즘은 다음 순서로 노드들을 방문

BFS

큐를 이용한 너비우선순회

큐BFS

큐BFS2

큐BFS3


수도코드

BFS_수도코드


BFS와 최단경로

  • S에서 Li에 속한 노드까지의 최단 경로의 길이는 i이다.

    (여기서 경로의 길이는 경로에 속한 에지의 개수를 의미한다.)

  • BFS를 하면서 각 노드에 대해서 최단 경로의 길이를 구할 수 있다.

BFS_최단경로

입력 : 방향 혹은 무방향 그래프 G = (V, E), 그리고 출발 노드 s ∈ V

출력 : 모든 노드 v에 대해서

  • d[V] = s로 부터 v까지의 최단 경로의 길이(에지의 개수)
  • π[V] = s로부터 c까지의 최단경로상에서 v의 직전 노드(predecessor)

    BFS_수도코드2

  • 약간 변경한 버젼(π[s]가 아니라 π[u]다.)

    BFS_수도코드3


각 노드 v와 π[V]를 연결하는 에지들로 구성된 트리

  • BFS 트레이서 S에서 V까지의 경로는 s에서 v까지 가는 최단경로

  • 어떤 에지도 2개의 layer를 건너가지 않는다.
    (동일 레이어의 노드를 연결하거나, 혹은 1개의 layer를 건너간다.)

    BFS_트리


너비우선순회: 최단 경로 출력하기

너비우선순회_최단_경로_출력


너비우선순회 (BFS)

  • 그래프가 disconnected이거나 혹은 방향 그래프라면 BFS에 의해서 모든 노드가 방문되지 않을 수도 있음

  • BFS를 반복하여 모든 노드 방문

    BFS-ALL( G )
    {
      while there exists unvisited node v
        BFS(G, V);
    }
    
그래프(graph) 개념과 표현

인프런의 영리한 프로그래밍을 위한 알고리즘 강좌를 보고 작성한 문서입니다.


그래프

(무방향) 그래프 G = (V, E)

  • V : 노드(node) 혹은 정점(vertex)

  • E : 노드쌍을 연결하는 에지(edge) 혹은 링크(link)

  • 개체(object)들 간의 이진관계를 표현

  • n=|V|, m=|E|

    그래프1

방향 그래프와 가중치 그래프

방향_그래프

방향그래프(Directed Graph) G = (V, E)

  • 에지 (u, v)는 u로부터 v로의 방향을 가짐

가중치(weighted) 그래프

  • 에지마다 가중치(weight)가 지정

그래프의 표현

인접행렬 (adjacency matrix)

그래프의_표현

인접리스트 (adjacency list)

그래프의_표현2

  • 정점 집합을 표현하는 하나의 배열과
  • 각 정점마다 인접한 정점들의 연결 리스트

방향 그래프

  • 인접행렬은 비대칭

  • 인접 리스트는 m개의 노드를 가짐

    방향_그래프_표현

가중치 그래프의 인접행렬 표현

에지의 존재를 나타내는 값으로 1대신 에지의 가중치를 저장

에지가 없을 때 혹은 대각선:

  • 특별히 정해진 규칙은 없으며, 그래프와 가중치가 의미하는 바에 따라서

  • 예: 가중치가 거리 혹은 비용을 의미하는 경우라면 에지가 없으면 ∞, 대각선은 0

  • 예: 만약 가중치가 용량을 의미한다면 에지가 없을때 0, 대각선은 ∞
    (대각선은 자기자신을 의미)


경로와 연결성

  • 무방향 그래프 G = (V, E)에서 노드 u와 v를 연결하는 경로(path)가 존재할 때 v와 u는 서로 연결되어 있다고 말함

  • 모든 노드 쌍들이 서로 연결된 그래프를 연결된(connected) 그래프라고 한다.

  • 연결요소 (connected component)

    경로와_연결성

26일 한일

- 면접

  • 대기 시간이 좀 생겨서 자바스크립트를 깨우치다 잠시 읽음
    • 프로토타입 부분 간단히 학습

26일 느낀점

  • 이전 스코프 때도 그렇고 프로토타입을 보면서 느낌점이 해당 두 개념도 중요하지만 체이닝이 상당히 중요하다는 생각이 들었다. 일찍 도착해서 30분 가냥 대기 시간이(혼자 있었다) 생겼는데 뭔가 오버하는 것 같아 말까 싶기도 하다가 핸드폰 보고 있기도 뭐 해서 잠시 봤다. 해당 책이 ES3 문법인데 그런 부분에 대한 언급이 한두 번씩 있다 보니까 ES6 문법은 어떨지 호기심이 생기긴 한다. 3월에 무엇을 할까 생각을 해둬야 할 것 같다.

  • 담담한 내 성향이 면접 때는 단점이 될 수도 있겠다는 생각이 들었다. 그러한 성향 덕분에 공부를 하면서 쉽게 지치지 않고 해 나갔고, 에러 발생이나 어려운 내용을 학습할 때에도 소위 멘탈이 깨지는 것 없이 해결책을 찾아 나갔었는데 일반적인 신입의 열정과 패기가 부족한 모습을 보이는 것 같다. 아마 내가 학습하는 것을 보고서 열정적으로 한다고 생각하는 사람들도 있었지 않을까 싶다. 사실 나는 그저 내가 재미를 느끼는 분야를 그냥 계속 공부했을 뿐이다. 잘 하고 싶었고 열심히 하고 싶었고 공부하는 게 재밌었을 뿐이다. 그러다 보니 스스로 공부하는 것에 대해서 당연하게 생각했다.

    직장이 생겨서 직장을 목표로 공부를 한 게 아니기 때문에 취직 후에도 자신의 성장을 위해 노력하는 것에 대해서도 당연하다는 생각조차 크게 안 들 정도 계속해 나갈 생각이었다. 그러다 보니 아무 색 없이 당연한 대답들만 한 것 같다. 특히나 지금은 글을 작성하면서 생각을 일부 정리하면서 적으니 조금은 더 내 생각을 전할 수 있는 말로 수정을 해나가지만 해당 자리에서는 정말 뻔한 소리만 했던 것 같다. 도리어 스스로도 뻔한 것 같아 어설프게 살을 붙이려고 했던 것 같다. 그런 뻔한 소리는 무언가를 보여줄 수 있는 사람이 아니라면 색을 잃는다고 생각한다. 기술 면접이었다면 기술적인 질문에 내가 대답을 잘 하는 것으로 보여 줄 수 있다. 그러나 기술 면접이 아닌 자리에서는 아무런 신뢰성이 없는 말이 되는 것 같다.

    최대한 꾸밈없이 진솔한 모습을 보여주고 싶었던 것이 열정이 부족한 모습을 보여 주는 것 같다. 게다가 신입으로서의 대답이 아닌 개발자로서 질문의 요구 사항을 분석하고 냉정히 대답 한 부분도 있다.(그래도 내 답변에 좀 더 세부적인 설명을 덧붙였어야 한다고 생각하긴 한다.) 내가 말을 조금만 더 잘 했다면 진솔한 모습에서도 그런 열정을 보여 줬었을 수도 있을까 싶은데.. 사실 스스로 오늘 일에 대한 핑계를 대는 것 같은데 결론적으론 아직은 스스로가 어리숙 한 것 같다. 면접이라는 자리가 결국 나 자신을 어필해야 하는 자리인데 그런 부분이 부족했던 것 같다. 이 부분은 요번 주말쯤 해서 잘 생각해 봐야겠다.


27일 한일

- 면접

27일 느낀점

  • 자료구조, 알고리즘 위주의 면접으로 전체적으로 나쁘진 않았던 것 같긴 한데 대답 못한 부분과 와서 생각해보니 잘 못 대답 한 부분도 있었던 것 같다. 그래도 기술 면접은 이전과 마찬가지로 알고 있는 부분에 한해서는 다 대답해서 완벽하진 못했지만 스스로 아는 선에 한해선 나쁘진 않았다고 본다. 해당 회사의 기준에 부합했느냐는 별개의 문제니까. 그리고 두 번의 기술 면접을 경험하고 한 번에 경영진 면접을 진행하고 보니까 무엇을 고려해 봐야 할지 조금 더 내 생각이 생기고 있는 것 같다.

  • 요즘 학습을 제대로 못 하고 있는데 약간 좀이 쑤신다. 면접을 보고 그러다 보니 제대로 집중은 안되고 이 부분은 3월 계획을 잘 세워야 할 것 같다.


28일 한일

- 2월 마지막 코드스쿼드 출석

  • 마지막 송별회

28일 느낀점

  • 요번 주는 마저 나올 것 같긴 하지만 일단 공식적으로 마지막 날. 취직을 하고 마무리했으면 더 좋았겠지만 일단 이제는 옛날과 달리 스스로의 길을 찾아갈 능력은 생긴 것 같다. 매일 10~22시까지 월~토 있었던 곳이다 보니 아직은 실감이 안 나는 것 같다. 일단 과정은 마무리했으니 앞으로도 힘내보자.

  • 나와 카우가 오늘 마지막 날이라 브라이언도 방문하여 백엔드 사람들과 송별회. 다들 잘 되길.


01일 한일

- 자바스크립트를 깨우치다 읽는 중

  • 프로토타입과 체인

- 구글 애널리틱스

01일 느낀점

  • 자바스크립트에 체인을 보면서 DOM 구조의 느낌이 강한 언어라고 생각했는데 상속 체인을 보니까 또 좀 다른 느낌이다. 뭔가 다르다. 자바스크립트 확실히 재밌는 언어인 것 같긴 한데 신경 써야 할 부분이 많은 복잡한 존재인 것 같다.

  • 2017년 회고는 초보 개발자 모임에 소개돼서 많았으며(소셜 페이지를 통해 들어온 인원과 일치한다. 이번 주가 아니라 이번 달이라면 해당 페이지가 압도적이다) 개인적으로 가장 애착이 가는 포스팅은 4번 wi fi에 대한 포스팅이다. 실제로 나도 해당 문제로 한동안 골머리 썩이기도 했고 같은 증상을 겪는 사람이 있으면 해결 하길 바라는 마음으로 써서 많은 도움이 되었길 바란다. 일단 워낙에 블로그에 들어오는 인원이 적어 제대로 된 분석은 무의미하지만 무언가를 해결할 때 필요한 정보를 원하는 사람들이 많이(?) 찾는 것 같다. 블로그를 통해서 지식의 전달 보다 검색해서 들어오시는 분들이 가진 문제가 해결되길 바라는 마음으로 작성했는데 얼마나 도움이 되었을지는 알 수 없지만 만약 한 분이라도 그런 분이 있었으면 좋겠다.


02일 한일

  • 코드스쿼드로 공부 하러 간 마지막 날
    • 아마도 주말에 개방 되면 취직 해서도 지속적으로 공부 하러 갈 것 같지만…

02일 느낀점

  • 일단 공식적인(?) 코드스쿼드로 공부하러 가는 과정은 마무리되었다. 취직이 아직 안된 점은 아쉽지만 코드스쿼드를 통해서 스스로 길을 헤쳐나가는 방법을 찾은 것 같다. 아직은 스스로가 부족한 부분들도 있고 신입의 입장에서 나를 보여줄 수 있는 스펙적인 요소도 약하다.(스펙이 개발 능력을 보여주는 지표라고 생각 하진 않지만 간접적인 징표가 될 수 있다는 건 맞는다고 생각한다…) 그러다 보니 취직을 소위 말해서 잘 되지 않을 수도 있다. 그런 경우 아쉽긴 하겠지만, 코드스쿼드를 통해 내가 얻은 것은 취직하는 방법이 아닌 좋은 개발자가 되는 길을 찾아가는 능력이라고 생각한다. 지금 당장은 미약할 수 있지만 1년, 2년 그리고 수년이 흘러서는 좋은 개발자 혹은 능력 있는 개발자가 되어 있을 것이라고 생각한다. 당연히 자연스럽게 그런 개발자가 되는 것이 아니라 지금까지 했던 노력처럼 꾸준히 공부해 나가도록 해야 할 것이다. 열심히 노력도 해야겠지만 안주하지 말자.

    현재 내가 생각 하는 좋은 개발자는 품질 좋은 소스코드를 짜는 것이다. “좋은” 답은 없기때문에 차후 계속 변해 갈 것이다. 그렇기때문에 조금은 추상적일 수도 있는 이 목표가 어느 상태에 안주하지 않고 계속 성장 해 나가는 동력이 되지 않을까 싶다.


03일 한일

  • 자소서 및 포트폴리오 일부 수정

03일 느낀점

  • 아무리 생각해도 우분투 용 ms word가 없는 게 이해가 안 된다…ㅜㅜ 기본 제공되는 LibreOffice가 있긴 하지만 불편한 점이 있어서 ms 워드 쪽이 편한데 그러다 보니 옛날 윈도우 노트북까지 두 개를 챙겨야 해서 너무너무 불편하다. 역시 실생활에서 우분투만 사용하면 이런 식으로 고생하는 경우들이 생기는 것 같다ㅜㅜ

  • 브라이언이랑 얘기하다 한동안 공부할 내용이 조금 나왔다. 이전 작업했던 로또에 Nginx를 적용하는 것과 노골 라스의 리액트 강의를 한번 보고 싶었는데 이번 기회에 봐야겠다. 그리고 다음 주부터 레벨 4 때 했던 내용들 복습을 다시 해야겠다.


04일 한일

  • 경기 창조경제혁신 센터에서 공부
    • 앞으로 매일 이곳으로 공부 하러 갈 계획

04일 느낀점

  • 2월 들어서 생각했지만 오늘을 마지막으로 매일 작성하는 TIL은 멈출 계획이다. 이전 코드스쿼드를 다니는 기간에 작성한 TIL은 그날 배운 내용을 작성하거나 학습적인 고민이 들어 있어서 많은 도움이 됐다고 생각한다. 당시 작성항 고민들은 나중에 공부하는 누군가가 공부하면서 느끼는 고민들이 다른 사람들도 마찬가지이고 그걸 견디며 공부하면서 성장한다는 면을 보여주고 싶었지만 최근 들어서는 그것조차 희미하다. 아무리 생각해도 편히 잔디 심기용 작성으로 밖에는 생각되지 않는다. 결론적으로는 나한테도 도움이 안 되고 다른 사람도 얻어 갈 것이 없는 TIL이다. 그런 이유로 매일 작성하는 TIL은 안 할 계획이다. 매일 안 한다는 것이기 때문에 경우에 따라서는 작성하는 날도 있을 것이다.

    요즘 취업 준비로 인해 공부에 집중이 안 된다는 이유로 학습을 제대로 못하고 있던 면이 있었는데 일일커밋은 계속 유지하고 싶은 욕심(?)이 있기 때문에 TIL을 작성하지 않는다면 강제적으로도 매일 한 가지의 유의미한 학습을 할 것이다. 일단은 이전부터 틈틈이 보고 있던 인프런 알고리즘 강의라든지 생각해 둔 3월 학습을 진행하며 블로그에 글을 올릴 생각이다. 일일커밋을 떠나서도 공부를 하겠지만 매일 공부하는 동기 부여로서 나쁘진 않다고 생각한다. 나한테도 도움이 되는 방향이 될 것이라고 생각한다.

19일 한일

- 초보 개발자 모임의 뉴스레터에 2017년에 작성한 TIL이 소개 됨

- 자바스크립트를 깨우치다 읽는 중

19일 느낀점

  • 명절 때 창천향로님의 “스프링부트로 웹 서비스 출시하기” 시리즈에 7번째인 Nginx부분을 내가 작업하던 프로젝트에 적용하는 과정을 포스팅을 하고 해당 부분에 대한 문의를 했었는데 그러다 내 작년 회고를 보셨는지 페이스북 페이지와 메일링 내용에 포함이 되었다. 아무래도 내가 쓴 글이 널리 퍼지니까 신기하기도 하고 아직은 부끄럽기도 하다. 사실 해당 글이 내 스스로에 대한 회고도 있지만 어떻게 노력을 해 나갔는지 상세하게 적어나가면서 다른 분들한테도 자극이 되는 글이 되길 바랬다. 많은 분들이 봐 주신 것 같은데 그런 분들이 조금이라도 있고 열심히 노력하셔서 잘 되신다면 좋을 것 같다. 근데 아무래도 설득력이 있으려면 나부터 잘 돼야 할 것 같은데 흐음… 계속 힘내보자.

  • 자바스크립트는 철저히 사용자 입장으로 간단한 DOM 조작, AJAX 처리만 가능 한 정도로 학습을 했지 제대로 공부했다고는 할 수 없는 상태다.(15퍼즐 정도까지만 겨우 만드는 실력) 정확히는 this, 클로저, 호이스팅(맞나?) 이런 개념들이 있고 많이들 헷갈려 한다는 것만 주워들은 상태다. 아무리 백엔드 분야를 공부하기로 생각했어도 프론트적인 부분, 특히 자바스크립트는 일정 부분 공부해야겠다는 생각은 했지만 해야 할 것들이 한두 개가 아니니 우선순위를 높게 두진 않고 미뤄둔 부분이었는데 오늘부터 조금씩 학습해 나가고 있다. 그래도 너무 큰 욕심은 안 내고 있고 중요한 개념들만 무엇인지 익히는 정도가 목표다. 백과 프론트 당연히 완벽한 건 불가능하고 일정 수준까지라도 두 마리의 토끼를 다 잡기엔 현재의 내 능력도 그렇지만 결정적으로 시간이 부족하다. 선택과 집중이 필요한 부분이다.

  • 명절 때부터 살짝 느끼고는 있었는데 약간의 몸살기가 있는 것 같다. 책을 읽을 때 집중이 안 된다.(좋은 핑계 꺼리기 생긴듯??) 옛날 같았으면 절대 병원은커녕 약국도 안 갔을 것 같은데 컨디셜 조절을 해야 하는 상황이라 내일도 이러면 후딱 병원을 가봐야겠다.


20일 한일

- 자바스크립트를 깨우치다 읽는 중

20일 느낀점

  • 밤코 도중 너무 피곤해서 한 시간 조금 안되게 잔듯 하다 주말부터 몸 컨디션이 안 좋았는데 잠깐이긴 해도 오랜만에 낮잠(?)을 잔 덕분인지 컨디션이 좋아졌다.

21일 한일

- 자바스크립트를 깨우치다 읽는 중

  • this

    this 키워든느 함수를 포함하고 있는 객체에 대한 참조이다. 객체의 속성으로 포함된 함수(즉, 메소드)에서는 this를 사용해 “부모” 객체를 참조할 수 있다. 함수를 전역 스코프에서 정의했으면 this의 값응ㄴ 전역 스코프 객체(웹 브라우저의 window)가 된다.

    <!DOCTYPE html><html><meta charset="UTF-8"><body><script>
    
    var myObject1 = {
      name: 'myObject1',
      myMethod: function(){console.log(this);}
    };
    
    myObject1.myMethod();   //'myObject1'이 기록된다.
    var myObject2 = function(){console.log(this);};
    myObject2();    // Window가 기록된다.
    
    </script></body></html>
    
  • 함수 호이스팅

    함수는 실제로 함수가 정의되기 전에도 호출할 수 있다. 조금 이상하게 들리겠지만 이러한 특성을 익혀두어서 잘 활용하거나 최소한 이런 동작을 만났을 때 이유 정도는 알고 있어야 한다.

    <!DOCTYPE html><html><meta charset="UTF-8"><body><script>
    
    //예제 1
    var speak = function() {
      sayYo();    // sayYo()는 아직 정의되지 않았지만 호출할 수 있다. 'yo'가 기록된다.
      function sayYo() { console.log('Yo');}
    }();    // 함수 호출
    
    //예제 2
    console.log(sum(2, 2));   // 아직 정의되지 않은 sum()을 호출한다. 여기서도 호출이 가능하다.
    function sum(x, y) { return x + y;}
    
    </script></body></html>
    

    자바스크립트는 코드를 실행하기 전에 함수 선언문을 먼저 해석하고 먼저 실행 스택/컨텍스트에 추가한다. 그래서 어디서 코드를 실행하든 항상 함수가 정의된 듯 동작한다. 그러나 “함수 표현식”으로 정의된 함수는 호이스트(hoist)되지 않는다. “함수 선언문”만 호이스트된다.

21일 느낀점

  • 최근 자바스크립트에 대해 공부하면서 궁금했던 용어인 호이스팅에 대해 알게 됐다. 아주 간단히는 예전 해당 용어를 들었을 때 잠깐 보긴 했지만 지금 읽는 책의 구성을 따라 순차적으로 배워 나가다 보니까 좀 더 잘 이해가 되는 것 같다. 그러긴 해도 지금은 어디까지나 개념적인 부분만 글로 무엇이 있는지에 대해서 학습하는지라 자바스크립트를 잘 아냐고 하면 그건 별개의 문제일 것 같다. 단지 나중에 자바스크립트를 본격적으로 공부해야 할 경우나 기초적인 지식이 필요한 부분이 있을 때를 위한 대비의 의미가 크다.

22일 한일

- 자바스크립트를 깨우치다 읽는 중

22일 느낀점

  • 사실 얇은 책인데 잘 안 읽히고 있다. 뭔가 전부터 동물 책은 잘 안 읽히는 경향이 있긴 하지만 이번엔 어려워서라기보다는 취업 준비 관련해서 이런저런 생각을 정리하느라 집중이 덜 된 것 같다. 아무래도 집중이 덜 될 수 있는 시기이긴 하지만 공부하는 버릇이 흐트러지지 않게 조심하자. 공부가 잘 될 때도 있고 안될 때도 있는 건데 지금이 후자의 시기인 거뿐이니까.

23일 한일

- 네이버 오픈소스 세미나 참석

23일 느낀점

  • 오픈소스에 기여해 보고 싶다는 생각은 하고 있지만 스스로 허들을 만들고 어려운 일이라고 치부했던 것 같다. 그러다 오늘 세미나를 통해 그 허들을 낮추게 된 거 같다. 사실 겁먹은 이유 중에 컨트리뷰션이 거절당하면 어쩌지도 있었는데 아웃사이더님의 첫 컨트리뷰션 내용을 들으며 용기가 생겼다. 내 컨트리뷰션에 대한 응답이 없을 수도 거절당할 수도 있는 건 당연하다. 당연한 사실을 받아들이니까 확실히 편해진 것 같다.

    게다가 오픈소스가 너무 거대해서 구조를 이해하기 힘들 경우 취할 수 있는 조언으로 초기 버전을 본다던지 이해가 안 되는 코드 부분이 그렇게 짜인 순간 혹은 이슈를 확인하면 좋다는 것도 좋은 조언이 된 것 같다.

  • 네이버에 가기 전에 서현역에서 잠시 서점에 들렀다가 마틴 파울러의 리팩토링 책을 사버렸다… 봐야지 생각하고 사두고 아직 다 못 본 책이 많아서 더 안 사려고 했는데 충동구매…. 이놈의 책 욕심을 좀 버려야 하는데. 나중에 취업을 하고서 업무적으로 필요한 부분을 공부하느라 사는 책들 말고는 이미 충분히 좋은 책들을 많이 사뒀으니 사둔 책들부터 다 읽어보도록 해야겠다.


24일 한일

- 자바스크립트를 깨우치다 읽는 중

  • 스코프와 클로저

    자바스크립트에서는 var 키워드 없이 변수를 선언하면(설령 함수 스코프에서 선언했다 하더라도) 지역 스코프가 아닌 전역 스코프에 변수가 추가된다.

24일 느낀점

  • 스코프와 클로저에 대해서 봤는데 책에서도 언급했다시피 클로저는 단순화시켜서 간단히만 소개했다고 했는데, 일단은 저자가 원한 것처럼 간단한 개념 부분은 무엇인지 본 것 같은데 스코프도 그렇고 클로저도 실제 내가 자바스크립트로 코딩을 한다던지 다른 사람을 코드를 분석할 때 상당히 헷갈릴 것 같다.

25일 한일

- 경기창조혁신 센터에서 학습…까진 아니고 간단히 인터넷 자료들을 보면서 휴식

  • equals 관련
    String isNull = null;
    
    System.out.println("up");
    
    if ("문자열".equals(isNull)) {
    }
    
    System.out.println("middle");
    
    if (isNull.equals("문자열")) {
    }
    System.out.println("down");
    

    출력

    up
    middle
    Exception in thread "main" java.lang.NullPointerException
    	at mak.StringEquals.main(StringEquals.java:14)
    

    이전부터 "문자열".equals(isNull)isNull.equals("문자열") 중 어느 것이 나을까 고민하면서 전자의 형태를 따르고 있었다. 그러다 오늘 본 글 중 하나에서 나온 얘기가 후자 같은 경우는 예외가 발생해 버리기 때문에 전자가 좀 더 안전하다는 것이다. 생각해보니 맞는 것 같다. 차후 좀 더 생각해 볼 여지는 있겠지만 일단은 이와 같은 이유로 전자의 형태로 작성 할 것 같다.

25일 느낀점

  • 오늘처럼 간단한 내용은 TIL에다가 올린 경우들이 있었는데 좀 더 정리해서 포스팅했으면 어땠을까 싶다. 그건 그렇고 오늘은 좀 쉬는 느낌으로 경기창조혁신 센터를 갔는데 저녁쯤부터 사람들이 없다 싶었더니 집 가서 보니 올림픽 폐막식… 스포츠를 많이 보는 편은 아닌데 이번 올림픽에선 컬링은 재밌게 본 것 같다.
EC2 인스턴스에 Nginx를 구축해 보자

시작하기에 앞서

작업하려는 구조는 이렇습니다.

하나의 EC2에 웹 서버와 WAS가 같이 있는 구조입니다.

Nginx_구조

이렇게 Nginx가 외부의 요청을 받아 뒷단 서버로 요청을 전달하는 행위를 리버스 프록시라고 합니다. 이런 리버스 프록시 서버(Nginx)는 요청을 전달하고, 실제 요청에 대한 처리는 뒷단의 웹서버들이 처리합니다. 대신 외부 요청을 뒷단 서버들에게 골고루 분배한다거나, 한번 요청왔던 js, image, css등은 캐시하여 리버스 프록시 서버에서 바로 응답을 주거나 등의 여러 장점들이 있습니다. 자세한 설명은 NginX로 Reverse-Proxy 서버 만들기 - Joinc를 참고하시면 좋습니다.

출처: http://jojoldu.tistory.com/267?category=635883 [기억보단 기록을]

학습 차원으로 Nginx를 설치하고 실행해 보는 것에 중점을 두고 진행 했습니다.

위에 보이는 것과 같이 사용자가 Nginx를 통해 80번 포트로 접속하면 동일 ec2 인스턴스 내의 8080번 포트의 웹 애플리케이션으로 연결되게 해 봅시다.


실습은 창천향로님의 Nginx를 활용한 무중단 배포 구축하기를 보고 무중단 배포를 제외 진행 하였습니다.

참고로, EC2 구성은

창천향로님 : AWS Amazon Linux EC2로 Centos 기반
저 : Ubuntu Server 16.04 LTS

워낙에 원글이 잘 되어있기 때문에 따라 하는 것은 위의 블로그를 추천하고

전 창천향로님과 조금은 다른 환경에서 작업하느라 오는 문제들에 대해 해결 한 부분 및 실습 과정을 복습하는 차원에서 작성했습니다.


설치


EC2에 접속해서 Nginx를 설치합니다.

sudo apt-get install nginx

참고로

service nginx start : 시작
service nginx stop : 정지
service nginx restart : 재시작
service nginx reload : 설정파일을 재로드
service nginx status : 현재 상태

설치가 완료되셨으면 아래 명령어로 nginx를 실행합니다.

sudo service nginx start

Nginx 잘 실행되었는지 아래 명령어로 확인해봅니다.

sudo service nginx status

Nginx_status

이제 접속해 봅니다.

Nginx_접속문제

?!

왠지 모르게 접속이 안됩니다. 설정들이 잘못되었나 계속 확인해보면서 저 화면만 한 삼십분 본 것 같군요…

당연히 따라 하기만 할 거였다면 포스팅을 안 했겠죠??

저 같은 경우 hosts 파일을 통해서 myec2라는 호스트 이름을 통해 ec2 인스턴스에 접근합니다.
그게 아니라면 EC2 Public DNS/IP를 통해 접속하시면 됩니다. (hosts 파일 수정 방법)


EC2 인스턴스의 80번 포트에 대한 접근 허용


생각해보니 제 ec2 인스턴스의 Security Group에 80번 포트에 대한 인바운드 규칙을 추가해준 기억이 없습니다….

Nginx_ec2상태

인바운드 규칙 보기를 눌러보시면

Nginx_인바운드

80번 포트에 대한 것은 없습니다.

만약 접속이 잘 되신 분이라면 80번 포트에 대한 접근이 허용되어 있었을 겁니다.

Nginx_http추가

80번 포트에 해당하는 HTTP 규칙을 추가합니다.

(나중에 확인해보니 창천향로님은 해당 시리즈 4번째 글에서 추가하셨더군요. 차근차근 따라 하는게 아니라 이렇게 하고 싶은 부분들만 자신의 환경에 맞춰서 할 때는 삽질이 필요하죠!!)

Nginx_접속완료

다시 접속해보니 이제 잘 되는군요.


Nginx와 스프링부트 프로젝트를 연결


자 그럼 다시 진행을 해 봅시다.

Nginx_창천향로님글

라는 군요.

sudo vi /etc/nginx/nginx.conf

Nginx_location_없음

아무리 눈을 씻고 찾아봐도 location / 이 존재하지 않습니다.

http 내부에 한번 server, location / 을 추가해서 진행해보니 안됩니다.(지금 보니 가능 할 것 같습니다)

이럴 때 필요한 것은 구글링!!

자료1자료2를 보니 /etc/Nginx/sites-available/default를 확인해 봐야 하겠군요.

sudo vi /etc/nginx/sites-available/default

Nginx_default_location

추가를 해줍니다.

현재 스크린샷에선 주석 처리를 안 했지만

#try_files $uri $uri/ =404;

위와 같이 주석 처리를 해 주시기 바랍니다. (try_files 관련 내용)


위에 밑줄 쳐둔 include /etc/Nginx/sites-enabled/*;로 되어 있는 부분 덕에 해당 내용이 추가되어서 되는 것 같은데 우리가 설정을 한 곳은 sites-available입니다.

왜 되는지 구글링을 하기 전에 파일 내용이 같길래 혹시나 확인해보니

Nginx_sites-enabled

심볼릭 링크라는 걸 알 수 있습니다. (간단히 바로 가기를 생각하시면 됩니다)

대강 찾아보니 데비안 계열에서는 sites-enabledsites-available를 활용하는 점에서 창천향로님이 사용하신 Centos와 조금 다른 부분이 있어 진행이 안됐더군요.

해당 내용은 여기를 참조하면 알 수 있는 것 같군요???


정말 접속


새로 설정한 내용들이 적용되게 Nginx를 재시작 한 다음

sudo service nginx restart

접속을 해봅니다.

Nginx_trello

성공!!

잘 안 보이긴 하지만 :8080 없이 접속된 것을 볼 수 있습니다.(http의 경우 기본값은 80번)

참고로 이제 80번 포트를 이용하여 Nginx를 통해 8080번 포트를 사용하는 웹 애플리케이션에 접속할 것이라 EC2 인스턴스에 8080 포트에 대한 인바운드 규칙을 제거해도 됩니다.

단, 어디까지나 하나의 EC2 인스턴스 내에 웹 서버와 was가 동시에 존재하기 때문에 가능하지 각자의 환경이나 설정에 따라 다릅니다.


요약


  1. 창천향로님의 글을 첫번재 포스팅부터 순서대로 따라하기만 하면 잘 된다.

  2. 만약 접속이 안되면 AWS EC2의 80번 포트에 대한 접근이 허용 되어있는지 확인 해 보자.

  3. Nginx에서 was로의 연결이 안되는 상황에다 우분투 사용자라면

     sudo vi /etc/nginx/sites-available/default
    

    에서 location을 변경 해 주자.


여담

사실 무중단 배포를 아직 안한 이유는….

Nginx_aws_bill

적은 돈이지만…. 잠시 보류 하기로 하였습니다.

창천향로님이 진행하는 예제에는 좀 가벼운 웹 애플리케이션을 이용하시는 것 같은데

저 같은 경우는 기존에 만들고 있던 프로젝트로 진행을 하다보니 s3에 업로딩 하고

ec2에 받아 와서 빌드하는 과정도 시간이 좀 걸려서 진행도 뚝뚝 끊기는데다가

돈도 과금이 되니 움찔하게 되는군요…방금 작업하는데도 조금씩 오르더군요.
(아직 월 말도 아니고ㅜㅜ)

이럴땐 작년 AWS한국 사용자모임 행사서 받았던 크레딧이 그립군요.

큰돈은 아니니 마저 진행을 해 볼 텐데 과금을 줄이기 위해 웹 애플리케이션을 좀 더 가벼운 녀석으로 바꾸거나 실패를 최소화해서 리소스를 덜 쓰는 방향으로 가야 할 것 같군요.


다만, 이전 TravisCI & AWS CodeDeploy로 배포 자동화 구축하기처럼 큰 문제없이 진행이 되면 따로 포스팅을 하진 않을 것 같습니다.