웹사이트 생성
Kotlin과 Ktor로 웹사이트 만들기
코드 예제: tutorial-server-web-application
사용된 플러그인:
이 튜토리얼에서는 Kotlin과 타임리프(Thymeleaf) 템플릿을 사용하여 Ktor로 상호작용 가능한 웹사이트를 구축하는 방법을 배웁니다.
다음과 같이 모든 구현을 서버에 유지하고 클라이언트에는 마크업만 보내고 싶을 때가 많습니다:
- 단순함 – 단일 코드베이스를 유지할 수 있습니다.
- 보안 – 공격자에게 힌트를 줄 수 있는 데이터나 코드가 브라우저에 배치되는 것을 방지합니다.
- 지원 가능성 – 레거시 브라우저나 JavaScript가 비활성화된 브라우저를 포함하여 최대한 광범위한 클라이언트를 지원할 수 있습니다.
Ktor는
사전 준비 사항
이 튜토리얼은 독립적으로 진행할 수 있지만, RESTful API 생성 방법을 배우기 위해
IntelliJ IDEA를 설치하는 것을 권장하지만, 원하는 다른 IDE를 사용해도 무방합니다.
Hello Task Manager 웹 애플리케이션
이 튜토리얼에서는
기존 프로젝트에 이러한 플러그인을 수동으로 추가할 수도 있지만, 새 프로젝트를 생성하고 이전 튜토리얼의 코드를 점진적으로 통합하는 것이 더 쉽습니다. 필요한 모든 코드를 과정 중에 제공하므로 이전 프로젝트를 따로 준비해 둘 필요는 없습니다.
Ktor Project Generator로 이동합니다.
Project artifact 필드에 프로젝트 아티팩트 이름으로 com.example.ktor-task-web-app 를 입력합니다.

다음 화면에서 Add 버튼을 클릭하여 다음 플러그인을 검색하고 추가합니다:
- Static Content
- Thymeleaf
플러그인을 추가하면 프로젝트 설정 아래에 세 개의 플러그인이 모두 표시됩니다. 
Download 버튼을 클릭하여 Ktor 프로젝트를 생성하고 다운로드합니다.
- IntelliJ IDEA 또는 원하는 IDE에서 프로젝트를 엽니다.
- src/main/kotlin 으로 이동하여 model 이라는 하위 패키지를 생성합니다.
- model 패키지 안에 새로운 Task.kt 파일을 생성합니다.
Task.kt 파일에 우선순위를 나타내는
enum과 할 일을 나타내는data class를 추가합니다:kotlin다시 한번 말씀드리지만,
Task객체를 생성하여 클라이언트가 표시할 수 있는 형식으로 전달하고자 합니다.다음 내용을 기억하실 것입니다:
- 요청 처리 및 응답 생성튜토리얼에서는 할 일을 HTML로 변환하기 위해 직접 작성한 확장 함수를 추가했습니다.Kotlin과 Ktor를 사용하여 할 일 관리 애플리케이션을 빌드하면서 라우팅, 요청 처리 및 매개변수의 기초를 배웁니다.
- RESTful API 만들기튜토리얼에서는Kotlin과 Ktor를 사용하여 백엔드 서비스를 빌드하는 방법을 배우며, JSON 파일을 생성하는 RESTful API 예제를 다룹니다.
kotlinx.serialization라이브러리의Serializable타입을Task클래스에 어노테이션으로 추가했습니다.
이번 경우에는 할 일의 내용을 브라우저에 출력하는 서버 페이지를 만드는 것이 목표입니다.
- src/main/kotlin 에 있는 Routing.kt 파일을 엽니다.
.configureRouting()함수에 아래와 같이/tasks라우트를 추가합니다:kotlin서버가
/tasks에 대한 요청을 받으면 할 일 목록을 생성한 다음 타임리프 템플릿으로 전달합니다.ThymeleafContent타입은 트리거할 템플릿 이름과 페이지에서 접근할 수 있는 값들의 테이블을 인자로 받습니다.- src/main/kotlin 에 있는 Thymeleaf.kt 파일을 엽니다.
다음과 같은
.configureThymeleaf함수를 볼 수 있습니다:kotlin타임리프 플러그인 초기화 시, Ktor는 서버 페이지를 찾기 위해 templates/thymeleaf 폴더 안을 살펴봅니다. 정적 콘텐츠와 마찬가지로 이 폴더가 resources 디렉토리 안에 있을 것으로 예상하며, .html 접미사를 기대합니다.
이 경우,
all-tasks라는 이름은 다음 경로와 매핑됩니다:src/main/resources/templates/thymeleaf/all-tasks.html- src/main/resources 로 이동하여 새로운 templates/thymeleaf 디렉토리를 생성합니다.
- src/main/resources/templates/thymeleaf 안에 새로운 all-tasks.html 파일을 생성합니다.
all-tasks.html 파일을 열고 아래 내용을 추가합니다:
htmlIntelliJ IDEA에서 실행 버튼 (
) 을 클릭하여 애플리케이션을 시작합니다.
브라우저에서 http://0.0.0.0:8080/tasks로 이동합니다. 아래와 같이 표에 모든 현재 할 일이 표시되는 것을 확인할 수 있습니다:

모든 서버 페이지 프레임워크와 마찬가지로, 타임리프 템플릿은 정적 콘텐츠(브라우저로 전송됨)와 동적 콘텐츠(서버에서 실행됨)를 혼합하여 사용합니다. 만약 Freemarker와 같은 다른 프레임워크를 선택했더라도 약간 다른 구문으로 동일한 기능을 구현할 수 있었을 것입니다.
GET 라우트 추가하기
이제 서버 페이지를 요청하는 과정에 익숙해졌으므로, 이전 튜토리얼의 기능을 이 프로젝트로 계속 옮겨보겠습니다.
Static Content 플러그인을 포함했으므로, Routing.kt 파일에 다음 코드가 있을 것입니다:
이는 예를 들어 /static/index.html에 대한 요청이 다음 경로의 콘텐츠를 제공함을 의미합니다:
src/main/resources/static/index.html이 파일은 생성된 프로젝트에 이미 포함되어 있으므로, 추가하려는 기능의 홈 페이지로 사용할 수 있습니다.
src/main/resources/static 내의 index.html 파일을 열고 그 내용을 아래 구현으로 바꿉니다:
htmlIntelliJ IDEA에서 재실행 버튼(
)을 클릭하여 애플리케이션을 다시 시작합니다.
브라우저에서 http://localhost:8080/static/index.html로 이동합니다. 할 일을 조회, 필터링 및 생성할 수 있는 링크 버튼과 세 개의 HTML 폼이 표시되어야 합니다:

name또는priority로 할 일을 필터링할 때 GET 요청을 통해 HTML 폼을 전송한다는 점에 유의하세요. 이는 매개변수가 URL 뒤의 쿼리 스트링(query string)에 추가됨을 의미합니다.예를 들어
Medium우선순위의 할 일을 검색하면 서버로 전송되는 요청은 다음과 같습니다:http://localhost:8080/tasks/byPriority?priority=Medium
할 일 저장소(repository)는 이전 튜토리얼과 동일하게 유지할 수 있습니다.
model 패키지 안에 새로운 TaskRepository.kt 파일을 만들고 아래 코드를 추가합니다:
- src/main/kotlin 의 Routing.kt 파일로 이동합니다.
현재 버전의
.configureRouting()을 아래 구현으로 대체합니다:kotlin위 코드는 다음과 같이 요약할 수 있습니다:
/tasks에 대한 GET 요청 시, 서버는 저장소에서 모든 할 일을 가져와 all-tasks 템플릿을 사용하여 브라우저로 보낼 다음 뷰를 생성합니다./tasks/byName에 대한 GET 요청 시, 서버는queryString에서name매개변수를 가져와 일치하는 할 일을 찾고, single-task 템플릿을 사용하여 브라우저로 보낼 다음 뷰를 생성합니다./tasks/byPriority에 대한 GET 요청 시, 서버는queryString에서priority매개변수를 가져와 일치하는 할 일들을 찾고, tasks-by-priority 템플릿을 사용하여 브라우저로 보낼 다음 뷰를 생성합니다.
이 모든 것이 작동하려면 추가 템플릿을 추가해야 합니다.
- src/main/resources/templates/thymeleaf 로 이동하여 새로운 single-task.html 파일을 생성합니다.
single-task.html 파일을 열고 다음 내용을 추가합니다:
html동일한 폴더에 tasks-by-priority.html 라는 새 파일을 만듭니다.
tasks-by-priority.html 파일을 열고 다음 내용을 추가합니다:
html
저장소를 만들었으므로 이제 GET 요청에 대한 라우트를 구현할 수 있습니다.
POST 요청 지원 추가
다음으로, /tasks에 POST 요청 핸들러를 추가하여 다음 작업을 수행하겠습니다:
- 폼 매개변수에서 정보를 추출합니다.
- 저장소를 사용하여 새 할 일을 추가합니다.
- all-tasks 템플릿을 재사용하여 할 일을 표시합니다.
- src/main/kotlin 의 Routing.kt 파일로 이동합니다.
.configureRouting()메서드 내에 다음post요청 라우트를 추가합니다:kotlinIntelliJ IDEA에서 재실행 버튼(
)을 클릭하여 애플리케이션을 다시 시작합니다.
- 브라우저에서 http://0.0.0.0:8080/static/index.html로 이동합니다.
Create or edit a task 폼에 새 할 일 상세 정보를 입력합니다.

Submit 버튼을 클릭하여 폼을 제출합니다. 그러면 전체 할 일 목록에 새 할 일이 추가된 것을 볼 수 있습니다:

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