생각을 개발하자, 박진형

[rails] 레일즈 기본편 - 뷰 본문

Likelion/rails

[rails] 레일즈 기본편 - 뷰

imjinbro imjinbro 2017.01.31 11:05

[레일즈 뷰]




- 도서관 예시 : 다시 도서관 이야기로 돌아가서 우리가 도서관에 가서 도서 대여/반납 서비스를 이용하려고 한다. 도서관에 직접갔다면 도서 대여/반납 서비스 코너가 있어야 할 것이고, 홈페이지를 통해 빌린다면 홈페이지 내에 도서 대여/반납 페이지가 개설되어 있어야한다. 개설을 하기위해서는 MVC 모두 필요하지만 도서를 대여하고 반납하는 입장의 우리는 M(모델)과 C(컨트롤러)에 대해서 알 필요 없다. 우리는 V(뷰)를 통해서 도서 대여/반납 서비스를 접할 것이기 떄문이다.
여러분들이 보는 네이버의 메인 페이지, 이외의 페이지들도 마찬가지이다. 레일즈 구조에서는 views 폴더 하위에 V 파일들이 모두 있다.

- 레일즈의 뷰 파일 : 레일즈의 뷰파일은 파일이름.html.erb 로 되어있다. html은 앞서 배웠던 것처럼 V의 골격을 구성해주는 언어이다. 뒤에 붙은 .erb는 html 파일에 루비 코드를 얹어서 사용한다는 의미에 붙은 이름이다.


그래서 파일이름.html.erb 이다. 

- 파일이름.html.erb 로 정의되어있는 이유 : 그렇다면 파일이름은 왜이렇게 저장되어있을까? 가령 우리가 계속해서 들었던 도서관 예시를 보겠다. 도서관 사서 기능 즉 도서 대여/반납 기능을 만들기위해 우리는 컨트롤러를 생성하였다. 이 컨트롤러의 이름은 librarian이다. 사서만 있으면 되는가? 사서가 하는 일들이 있을 것이다. 도서 대여 요청을 받아들이는 일, 도서를 찾아오는 일, 도서를 반납해주는 일 등 각각의 일들이 있는데 이 일들에 대한 정의는 librarian 이라는 컨트롤러 파일에 들어있다(액션메서드, 컨트롤러 파일 내에 정의된 def). 이러한 일들에 대응하는 뷰 파일들이 존재해야한다. 그래야 클라이언트인 우리가 도서관 대여/반납 페이지에 들어가서 필요한 서비스를 요청하지 않겠는가? 컨트롤러 액션에 대응하는 뷰 파일들을 views > librarian 폴더(컨트롤러를 생성하면 폴더는 컨트롤러의 이름에 맞게 자동생성됨, 레일즈의 장점) 내에 만들어줄 것이다. 뷰 파일의 이름은 액션메서드이름.html.erb로 만들면된다. 

- html.erb에서 erb 역할 : 보통 html 파일은 <태그> 겹겹이 쌓여있는 구조체이다. 기본 골격 즉 구조체는 변하지 않는다. 우리학교 도서관 홈페이지를 들어가서 MyLibrary 메뉴에 가본다. 본인이 빌린 책의 목록이 나올 것이고, 대여 기간 등이 나와있을 것이다. html의 역할은 대여 책 목록, 남은 대여기간 등을 표시하기위해 필요한 표를 만드는 역할이다. erb가 뜻하는 루비 코드가 얹어진다는 것은 책 목록, 남은 대여기간은 컨트롤러에서 루비코드로 계산을 하여 html로 만든 표에 그 결과를 넣는다는 것이다. 대여 기간과 책 목록은 항상 변해야하는데, html로는 그것을 표현할 수 없다. 도서관 홈페이지에 로그인한 우리의 정보를 가지고 도서 대여 데이터가 저장된 곳에 가서 대여 목록을 조회하고 기간을 산정하여 보여주는 것은 레일즈 내에서 루비코드로 계산해서 보여주는 수 밖에…. 레일즈는 html에 루비코드를 적절해서 혼용하여 쓰라고 파일 환경까지도 만들어준다. 그만큼 편하다. (계속해서 편함을 강조한다. 물론 다른 루비와 같은 서버언어가 가지고 있는 프레임워크들도 이러한 기능들이 있다.)

- html.erb에서 erb 역할2 : 루비를 통해 계산한 결과를 쉽게 보여주는 것 이외에 erb 파일이기때문에 편하게 할 수 있는 것이 있다. 뷰 헬퍼라는 기능들인데 천천히 뒤에서 살펴볼 것이다. 레일즈를 사용함에 있어서 반드시 사용해야하는 것은 아니지만, 레일즈만을 위한 약속된 코드 사용이기때문에 레일즈 개발자라면 이런 방법들도 알아야한다. 왜냐하면 혼자서 개발할 것이 아니기때문에 레일즈 개발자들과 대화를 위해서 혹은 같이 개발을 하기위해서 서로 통용되는 약속 쯤은 알고 사용해야한다. 

- 뷰파일 구조 알기 
    1) 뷰 파일은 views 폴더 하위 디렉토리에 위치한다. 내가 만들고자하는 홈페이지가 예를 들어 음식점 홈페이지를 만드려고 한다. 음식점 홈페이지에 넣을 첫번째 기능으로 음식점 예약 기능을 만드려고 하는데, 기능을 만들기 위해 reservation이라는 컨트롤러를 만든다. 컨트롤러 생성과 동시에 views 폴더 하위에 방금 만든 컨트롤러의 이름과 똑같은 reservation 폴더가 생긴다. 앞서도 설명했지만 예약 기능 아래에도 예약을 신청하는 것, 예약을 확인하는 것, 예약을 변경하는 것, 예약을 철회하는 페이지가 있어야한다. 예약이라는 기능 아래(컨트롤러) 여러 액션들이 있는 것이다. 컨트롤러에 이 액션들이 메서드(def)로 정의되어있고, 액션을 실제 클라이언트(예약을 하는 주체들)에게 보여줘야하는데 액션(메서드) 대응하는 뷰파일이 필요한 것이다. 각각의 액션 뷰 파일들이 방금 생긴 reservation 폴더 아래에 위치해야한다. 뷰 파일의 이름은 reservation 컨트롤러에 정의되어 있는 액션이름과 같아야한다.
가령, 예약 신청/확인/변경/철회 페이지를 만들 때 액션은 각각 def new/show/update/delete로 정의를 한다. 


views>reservation 폴더 내 뷰 파일들은 new/show/update/delete.html.erb로 생성하면 각각의 액션에 대한 뷰가 대응된다.
(기본적인 게시판 구조 : CRUD에 대해서 포스팅할 것이다)

    2) 위에서 설명한 사용자정의 폴더 뿐만 아니라 이미 만들어져있는 폴더와 파일(html.erb)이 있다. views > layouts > application.html.erb 는 어느 한 기능(예를 들어 도서관 대여/반납 서비스)에 국한되는 레이아웃이 아니라 웹어플리케이션에 공통으로 적용되는 레이아웃에 대한 파일이다. 레이아웃의 이름은 레이아웃 템플릿이라고 하는데, 지금은 기억해두지 말자. 적용되는 것을 원치않을 때 파일을 삭제하거나 이름을 변경하면 된다고 한다. 웹어플리케이션에 공통적으로 적용되는 뷰 파일이 있다는 것은 공통적으로 적용되는 컨트롤러도 존재한다는 뜻이다. 컨트롤러도 controllers > application_controller.rb가 있다. 공통 컨트롤러 파일은 모든 페이지에서 공통적으로 동작할 연산식을 넣어두고 사용할 수 있다.

- 뷰파일 이용하기 : html.erb의 특징을 이용하여 페이지를 만들어볼 것이다.
    1) 홈페이지 내 음식점 예약 기능 액션들을 만들기위해 컨트롤러를 만든다(사실상 큰 카테고리를 만드는 것과 똑같다) : rails g controller reservation (아직 엔터를 입력하지 않는다)
    2) 여기서 잠깐! 엔터 입력을 하기 전에 reservation 뒤에 더 적는다. 더 적는 이유는 뷰 파일과 컨트롤러 내 액션을 내가 직접 만들고 입력하지 않아도 rails g 기능을 통해 편하게 만들고 자동 입력할 수 있기 때문에서다
        : rails g controller reservation new show update delete (라고 입력을 하고 엔터를 땅친다. 그러고 난 후 앞서 언급했던 컨트롤러 파일 위치, 뷰 파일 위치를 관찰한다. 하나하나씩 살펴본다.)
    3) 컨트롤러 파일(reservation_controller.rb)을 살펴보니 new/show/update/delete 액션들이 내가 직접 파일에 쓰지 않았지만 생성된 것을 볼 수 있다.
뷰 파일도 마찬가지이다. views > reservation 폴더에 가보니 new/show/update/delete.html.erb 파일들이 내가 직접 만들지 않았지만 생성된 것을 볼 수 있다. 레일즈의 약속된 기능들을 사용하면 내가 직접 만들지 않고 파일을 수정하지 않아도 내가 사용하려는 방식에 맞게 알아서 세팅이 되는 것을 볼 수 있다.
    4) 그렇다면 컨트롤러 액션과 뷰가 연결되었는지 확인해봐야한다 : config > routes.rb 로 간다. 이 또한 내가 직접 입력하지않았지만 레일즈의 약속된 기능에 의해 기본적으로 설정해줘야하는 연결은 설정되어있다.
    5) 이제 액션과 그에 맞는 뷰가 서로 연결되어 있는 것까지 확인했다. html.erb 파일의 특징이자 장점인 html 코드 내에 루비 코드를 삽입해볼 것이다.
        html 파일에 루비 코드를 삽입하기 이전에 왜 루비코드를 삽입해야하는지 다시 짚어보자
        => 우리학교 도서관 홈페이지로 간다. 로그인을 하고 MyLibrary > 대출 목록 메뉴로 간다. 들어가보면 내가 책을 빌렸다면 책의 목록과 대여 기간이 나올 것이고, 책을 빌리지 않았으면 표가 비어있을 것이다. html은 대여를 했는지 안했는지, 대여한 목록이 무엇인지, 기간이 언제까지인지 알아올 수 없다. 이러한 역할을 하는 것은 V(뷰)에서 하는 것이 아니라 도서 목록과 학생 정보가 저장되어있는 곳을 관리하는 곳인 M(모델)과 V를 연결해주는 C(컨트롤러)에서 하는 역할이다.
로그인 한 학생이 대여 도서 목록이 있는지 없는지 체크하고 뷰 파일에 이 사실을 표시해줌으로서 도서 대여 목록 페이지에 들어간 학생에게 정보를 알리는 것이다. 다시 말하자면 C가 감독역할을 하는 것이다. MVC가 유기적으로 동작을 하기때문에 할 수 있는 일이기는 하지만….
어찌됐건 우리는 도서 대여 과정에 필요한 정보 조회를 컨트롤러에서 할 것이고, 정보를 뷰에 표시해줄 것이다. 뷰 파일의 확장자는 .html.erb이다. 앞서 언급했듯이 이렇게 명명된 이유가 있다고 했다. 루비 코드를 뷰파일에서도 쓸 수 있게 하기위해서였다. 여기서 말하는 루비코드란 컨트롤러에서 요청을 받아들여 어떤 연산을 하고 다시 돌려주는 결과인 루비 코드를 말한다. 
    6) 컨트롤러 액션에서 루비코드 작성하고 뷰 파일에 표시하기 
        6-1) 학생이 도서대여목록 페이지로 들어가기를 요청했다. (=> /librarian/show : librarian이라는 컨트롤러에 show 액션 요청을 했고, show.html.erb 뷰 파일 보여주기를 요청했다)
        6-2) 도서대여목록 페이지(librarian_controller.rb / show.html.erb) 구성에 필요한 정보로 학생이 대출을 했는지, 안했는지 / 대출을 했다면 어떤 도서 목록이 있는지 / 도서 목록에 포함된 도서의 대여 기간은 언제까지인지이다.
        6-3) controllers > librarian_controller.rb 파일에서 def show 를 찾는다. 그곳에서 앞서 구성에 필요한 정보로 언급한 정보들을 위해 연산을 한다(이 과정은 더 배우고 난 뒤에….. 지금은 뷰의 개념과 컨트롤러-뷰 연동과정만)
연산된 결과에 이름을 붙인다. 이름을 붙이는 이유는 컨트롤러에서 연산을 다 해놓고 나온 결과를 뷰 파일에서 부르려고 하는데, 엄청나게 길면 그게 효율적일까?
실제로 긴 코드를 그냥 다 작성한다고하면 MVC 패턴따위는 필요없는 것이다. MVC 패턴이 있는 것은 역할 분담을 딱딱 해두고 고쳐야할 필요성이 있는 부분에 대해서 바로바로 고칠 수 있게 하기 위함도 있다.

이름만 붙이는게 아니라 레일즈의 또다른 약속된 코드를 사용해야한다. 이름 앞에 @를 붙이는 것이다. 레일즈에서는 이것을 @템플릿변수라고 하는데, 지금은 굳이 이름을 외우기보다 왜 @를 붙이는가에 대해서만 알면된다.


@는 레일즈 MVC 간의 약속이다. 컨트롤러에서 연산된 결과를 뷰에서 보여주기위해서는 @가 필요하다. 꼭 명심해두길… (루비를 배웠다면 인스턴스 변수 개념에 대해 배웠을 것이고, 컨트롤러는 하나의 클래스)
    6-4) 컨트롤러에서 연산된 결과(보여주기 원하는 결과)를 @이름에 담았다. 다음 과정은 이를 뷰 파일에서 보여주는 방법에 대해 설명한다.
        컨트롤러 액션에 맞는 뷰 파일(views > 컨트롤러이름과같은폴더명 > 내에 있는 파일)을 연다.
        여기서 또 다른 레일즈 약속이 등장한다. @이름을 쓰기위해서 html 태그와 같은 약속된 문법을 사용해야하는데, 이것의 형태는 <%= %> 다.
        사용방법 : <아무html태그> <%= @이름 %> </아무html태그> (아무 html태그는 진짜 아무거나 써서는 안되고 결과를 보여줘야하는데, 본인들이 생각해서 어떻게 보여줄지를 html로 짠 다음 거기에 루비 코드를 넣어라는 뜻이다)
        <%= %>를 쓰면 컨트롤러에서 연산된 결과를 뷰 파일에서도 쓸 수 있다. 연산 결과만을 무조건적으로 쓰지 않고, 때에 따라 컨트롤러에서 계산을 하지 못하고 뷰에서 어쩔 수 없이 계산을 해야하는 때가 있는데 그때도 쓴다. 뒤에서는 그런 방법들 까지도 짚어볼 예정이다.

        ( <% %> 와 <%= %>의 차이점 : 전자는 연산만 되고 출력되지 않는 코드를, 후자는 직접 출력되는 코드를 작성할 때 사용함)