Skip to content

웹사이트 생성

Kotlin과 Ktor로 웹사이트 만들기

코드 예제: tutorial-server-web-application

사용된 플러그인:

Static Content
스타일시트, 스크립트, 이미지 등과 같은 정적 콘텐츠를 제공하는 방법을 알아봅니다.
,
Thymeleaf
필수 의존성: io.ktor:%artifact_name%

이 튜토리얼에서는 Kotlin과 타임리프(Thymeleaf) 템플릿을 사용하여 Ktor로 상호작용 가능한 웹사이트를 구축하는 방법을 배웁니다.

이전 튜토리얼
Kotlin과 Ktor를 사용하여 백엔드 서비스를 빌드하는 방법을 배우며, JSON 파일을 생성하는 RESTful API 예제를 다룹니다.
에서는 JavaScript로 작성된 단일 페이지 애플리케이션(SPA)에서 사용할 RESTful 서비스를 만드는 방법을 배웠습니다. 이 방식은 매우 인기 있는 아키텍처이지만, 모든 프로젝트에 적합한 것은 아닙니다.

다음과 같이 모든 구현을 서버에 유지하고 클라이언트에는 마크업만 보내고 싶을 때가 많습니다:

  • 단순함 – 단일 코드베이스를 유지할 수 있습니다.
  • 보안 – 공격자에게 힌트를 줄 수 있는 데이터나 코드가 브라우저에 배치되는 것을 방지합니다.
  • 지원 가능성 – 레거시 브라우저나 JavaScript가 비활성화된 브라우저를 포함하여 최대한 광범위한 클라이언트를 지원할 수 있습니다.

Ktor는

여러 서버 페이지 기술
HTML/CSS 또는 JVM 템플릿 엔진으로 구축된 뷰를 사용하는 방법을 알아봅니다.
과 통합하여 이 접근 방식을 지원합니다.

사전 준비 사항

이 튜토리얼은 독립적으로 진행할 수 있지만, RESTful API 생성 방법을 배우기 위해

이전 튜토리얼
Kotlin과 Ktor를 사용하여 백엔드 서비스를 빌드하는 방법을 배우며, JSON 파일을 생성하는 RESTful API 예제를 다룹니다.
을 먼저 완료하는 것을 강력히 권장합니다.

IntelliJ IDEA를 설치하는 것을 권장하지만, 원하는 다른 IDE를 사용해도 무방합니다.

Hello Task Manager 웹 애플리케이션

이 튜토리얼에서는

이전 튜토리얼
Kotlin과 Ktor를 사용하여 백엔드 서비스를 빌드하는 방법을 배우며, JSON 파일을 생성하는 RESTful API 예제를 다룹니다.
에서 만든 할 일 관리(Task Management) 애플리케이션을 웹 애플리케이션으로 전환해 보겠습니다. 이를 위해 여러 Ktor
플러그인
플러그인은 직렬화, 콘텐츠 인코딩, 압축 등과 같은 공통 기능을 제공합니다.
을 사용합니다.

기존 프로젝트에 이러한 플러그인을 수동으로 추가할 수도 있지만, 새 프로젝트를 생성하고 이전 튜토리얼의 코드를 점진적으로 통합하는 것이 더 쉽습니다. 필요한 모든 코드를 과정 중에 제공하므로 이전 프로젝트를 따로 준비해 둘 필요는 없습니다.

  1. Ktor Project Generator로 이동합니다.

  2. Project artifact 필드에 프로젝트 아티팩트 이름으로 com.example.ktor-task-web-app 를 입력합니다. Ktor Project Generator 프로젝트 아티팩트 이름

  3. 다음 화면에서 Add 버튼을 클릭하여 다음 플러그인을 검색하고 추가합니다:

    • Static Content
    • Thymeleaf

    Ktor Project Generator에서 플러그인 추가하기 플러그인을 추가하면 프로젝트 설정 아래에 세 개의 플러그인이 모두 표시됩니다. Ktor Project Generator 플러그인 목록

  4. Download 버튼을 클릭하여 Ktor 프로젝트를 생성하고 다운로드합니다.

  1. IntelliJ IDEA 또는 원하는 IDE에서 프로젝트를 엽니다.
  2. src/main/kotlin 으로 이동하여 model 이라는 하위 패키지를 생성합니다.
  3. model 패키지 안에 새로운 Task.kt 파일을 생성합니다.
  4. Task.kt 파일에 우선순위를 나타내는 enum과 할 일을 나타내는 data class를 추가합니다:

    kotlin

    다시 한번 말씀드리지만, Task 객체를 생성하여 클라이언트가 표시할 수 있는 형식으로 전달하고자 합니다.

    다음 내용을 기억하실 것입니다:

    • 요청 처리 및 응답 생성
      Kotlin과 Ktor를 사용하여 할 일 관리 애플리케이션을 빌드하면서 라우팅, 요청 처리 및 매개변수의 기초를 배웁니다.
      튜토리얼에서는 할 일을 HTML로 변환하기 위해 직접 작성한 확장 함수를 추가했습니다.
    • RESTful API 만들기
      Kotlin과 Ktor를 사용하여 백엔드 서비스를 빌드하는 방법을 배우며, JSON 파일을 생성하는 RESTful API 예제를 다룹니다.
      튜토리얼에서는 kotlinx.serialization 라이브러리의 Serializable 타입을 Task 클래스에 어노테이션으로 추가했습니다.

    이번 경우에는 할 일의 내용을 브라우저에 출력하는 서버 페이지를 만드는 것이 목표입니다.

  5. src/main/kotlin 에 있는 Routing.kt 파일을 엽니다.
  6. .configureRouting() 함수에 아래와 같이 /tasks 라우트를 추가합니다:

    kotlin

    서버가 /tasks에 대한 요청을 받으면 할 일 목록을 생성한 다음 타임리프 템플릿으로 전달합니다. ThymeleafContent 타입은 트리거할 템플릿 이름과 페이지에서 접근할 수 있는 값들의 테이블을 인자로 받습니다.

  7. src/main/kotlin 에 있는 Thymeleaf.kt 파일을 엽니다.
  8. 다음과 같은 .configureThymeleaf 함수를 볼 수 있습니다:

    kotlin

    타임리프 플러그인 초기화 시, Ktor는 서버 페이지를 찾기 위해 templates/thymeleaf 폴더 안을 살펴봅니다. 정적 콘텐츠와 마찬가지로 이 폴더가 resources 디렉토리 안에 있을 것으로 예상하며, .html 접미사를 기대합니다.

    이 경우, all-tasks라는 이름은 다음 경로와 매핑됩니다: src/main/resources/templates/thymeleaf/all-tasks.html

  9. src/main/resources 로 이동하여 새로운 templates/thymeleaf 디렉토리를 생성합니다.
  10. src/main/resources/templates/thymeleaf 안에 새로운 all-tasks.html 파일을 생성합니다.
  11. all-tasks.html 파일을 열고 아래 내용을 추가합니다:

    html
  12. IntelliJ IDEA에서 실행 버튼 (IntelliJ IDEA 실행 아이콘) 을 클릭하여 애플리케이션을 시작합니다.

  13. 브라우저에서 http://0.0.0.0:8080/tasks로 이동합니다. 아래와 같이 표에 모든 현재 할 일이 표시되는 것을 확인할 수 있습니다:

    할 일 목록을 표시하는 웹 브라우저 창

    모든 서버 페이지 프레임워크와 마찬가지로, 타임리프 템플릿은 정적 콘텐츠(브라우저로 전송됨)와 동적 콘텐츠(서버에서 실행됨)를 혼합하여 사용합니다. 만약 Freemarker와 같은 다른 프레임워크를 선택했더라도 약간 다른 구문으로 동일한 기능을 구현할 수 있었을 것입니다.

GET 라우트 추가하기

이제 서버 페이지를 요청하는 과정에 익숙해졌으므로, 이전 튜토리얼의 기능을 이 프로젝트로 계속 옮겨보겠습니다.

Static Content 플러그인을 포함했으므로, Routing.kt 파일에 다음 코드가 있을 것입니다:

kotlin

이는 예를 들어 /static/index.html에 대한 요청이 다음 경로의 콘텐츠를 제공함을 의미합니다:

src/main/resources/static/index.html

이 파일은 생성된 프로젝트에 이미 포함되어 있으므로, 추가하려는 기능의 홈 페이지로 사용할 수 있습니다.

  1. src/main/resources/static 내의 index.html 파일을 열고 그 내용을 아래 구현으로 바꿉니다:

    html
  2. IntelliJ IDEA에서 재실행 버튼(IntelliJ IDEA 재실행 아이콘)을 클릭하여 애플리케이션을 다시 시작합니다.

  3. 브라우저에서 http://localhost:8080/static/index.html로 이동합니다. 할 일을 조회, 필터링 및 생성할 수 있는 링크 버튼과 세 개의 HTML 폼이 표시되어야 합니다:

    HTML 폼을 표시하는 웹 브라우저

    name 또는 priority로 할 일을 필터링할 때 GET 요청을 통해 HTML 폼을 전송한다는 점에 유의하세요. 이는 매개변수가 URL 뒤의 쿼리 스트링(query string)에 추가됨을 의미합니다.

    예를 들어 Medium 우선순위의 할 일을 검색하면 서버로 전송되는 요청은 다음과 같습니다:

    http://localhost:8080/tasks/byPriority?priority=Medium

    할 일 저장소(repository)는 이전 튜토리얼과 동일하게 유지할 수 있습니다.

    model 패키지 안에 새로운 TaskRepository.kt 파일을 만들고 아래 코드를 추가합니다:

    kotlin

    저장소를 만들었으므로 이제 GET 요청에 대한 라우트를 구현할 수 있습니다.

  1. src/main/kotlinRouting.kt 파일로 이동합니다.
  2. 현재 버전의 .configureRouting()을 아래 구현으로 대체합니다:

    kotlin

    위 코드는 다음과 같이 요약할 수 있습니다:

    • /tasks에 대한 GET 요청 시, 서버는 저장소에서 모든 할 일을 가져와 all-tasks 템플릿을 사용하여 브라우저로 보낼 다음 뷰를 생성합니다.
    • /tasks/byName에 대한 GET 요청 시, 서버는 queryString에서 name 매개변수를 가져와 일치하는 할 일을 찾고, single-task 템플릿을 사용하여 브라우저로 보낼 다음 뷰를 생성합니다.
    • /tasks/byPriority에 대한 GET 요청 시, 서버는 queryString에서 priority 매개변수를 가져와 일치하는 할 일들을 찾고, tasks-by-priority 템플릿을 사용하여 브라우저로 보낼 다음 뷰를 생성합니다.

    이 모든 것이 작동하려면 추가 템플릿을 추가해야 합니다.

  3. src/main/resources/templates/thymeleaf 로 이동하여 새로운 single-task.html 파일을 생성합니다.
  4. single-task.html 파일을 열고 다음 내용을 추가합니다:

    html
  5. 동일한 폴더에 tasks-by-priority.html 라는 새 파일을 만듭니다.

  6. tasks-by-priority.html 파일을 열고 다음 내용을 추가합니다:

    html

POST 요청 지원 추가

다음으로, /tasks에 POST 요청 핸들러를 추가하여 다음 작업을 수행하겠습니다:

  • 폼 매개변수에서 정보를 추출합니다.
  • 저장소를 사용하여 새 할 일을 추가합니다.
  • all-tasks 템플릿을 재사용하여 할 일을 표시합니다.
  1. src/main/kotlinRouting.kt 파일로 이동합니다.
  2. .configureRouting() 메서드 내에 다음 post 요청 라우트를 추가합니다:

    kotlin
  3. IntelliJ IDEA에서 재실행 버튼(IntelliJ IDEA 재실행 아이콘)을 클릭하여 애플리케이션을 다시 시작합니다.

  4. 브라우저에서 http://0.0.0.0:8080/static/index.html로 이동합니다.
  5. Create or edit a task 폼에 새 할 일 상세 정보를 입력합니다.

    HTML 폼을 표시하는 웹 브라우저
  6. Submit 버튼을 클릭하여 폼을 제출합니다. 그러면 전체 할 일 목록에 새 할 일이 추가된 것을 볼 수 있습니다:

    할 일 목록을 표시하는 웹 브라우저

다음 단계

축하합니다! 할 일 관리자(Task Manager)를 웹 애플리케이션으로 다시 빌드하고 타임리프 템플릿 사용법을 배웠습니다.

다음 튜토리얼
콘텐츠를 주고받기 위해 웹소켓의 기능을 활용하는 방법을 알아봅니다.
로 이동하여 웹소켓(Web Sockets)을 사용하는 방법을 알아보세요.