์ธ๋ํ ์ฐ
์๋ฐ ์ธ์ด๋ก ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ฐ๋ฐํ๋ ๊ฒฝ์ฐ์ ๋๋ถ๋ถ ์คํ๋ง ํ๋ ์์ํฌ ๋๋ ์คํ๋ง ๋ถํธ ํ๋ก์ ํธ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์์ํ๊ธฐ ๋๋ฌธ์ ์ง์ ์๋ฐ ์๋ธ๋ฆฟ์ ์์ฑํ์ฌ ์ํ์น ํฐ์บฃ์ด๋ ์ธ๋ํ ์ฐ์ ๊ฐ์ ์น ์ ํ๋ฆฌ์ผ์ด์ ์๋ฒ๋ฅผ ์คํํ์ฌ ๋ฐฐํฌํด๋ณด๋ ๊ฒฝํ์ ํ๋ ์ ์ ๊ฐ๋ฐ์๊ฐ ๋ง์ง ์์ ๊ฒ ๊ฐ๋ค. ๊ทธ๋์ ์ด๋ณด ๊ฐ๋ฐ์๋ค์ ์ํด ๊ทธ๋๋ค ํ๋ก์ ํธ๋ก ์ธ๋ํ ์ฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ถ๊ฐํ๊ณ ๊ฐ๋จํ๊ฒ Hello World๋ฅผ ์ฐ์ด๋ณด๋ ๊ฒ์ ๊ณต์ ํ๊ณ ์ ํ๋ค.
์ธํ ๋ฆฌ์ ์ด ์ปค๋ฎค๋ํฐ ์๋์ ์ค์นํ๊ธฐ
์ธํ ๋ฆฌ์ ์ด ์ปค๋ฎค๋ํฐ ์๋์ ์ ์คํ๋ง์ ๋ํ ์ ์ฉํ ๊ธฐ๋ฅ์ ์ง์ํ์ง๋ ์์ง๋ง ๋ฉ์ด๋ธ์ด๋ ๊ทธ๋๋ค ํ๋ก์ ํธ์ ๋ํด์๋ ์ง์ํ๊ณ ์๋ค. ๋น๋ ์์คํ ์ Gradle๋ก ์ ํํ๊ณ Download JDK๋ฅผ ํตํด์ Temurin 17์ ์ ํํ์ฌ ๋ค์ด๋ก๋ ํ์. ๊ทธ๋ฌ๋ฉด JUnit์ด ๊ธฐ๋ณธ์ ์ผ๋ก ํฌํจ๋ ๊ทธ๋๋ค ํ๋ก์ ํธ๊ฐ ์์ฑ๋๋ค.
์ธ๋ํ ์ฐ ํจํค์ง ์ถ๊ฐํ๊ธฐ
๋ฉ์ด๋ธ ์ค์ ์ ์ฅ์์ ๋ฑ๋ก๋์ด ์๋ ํจํค์ง ์ค์์ undertow-core์ undertow-servlet ๋ชจ๋์ ์ถ๊ฐํ์.
dependencies {
implementation 'io.undertow:undertow-core:2.3.4.Final'
implementation 'io.undertow:undertow-servlet:2.3.4.Final'
}
Hello World ํธ๋ค๋ฌ ์์ฑํ๊ธฐ
์ธ๋ํ ์ฐ ๊ณต์ ๋ฌธ์์ ๋ฐ๋ผ ๊ธฐ๋ณธ์ ์ผ๋ก ์์ฑ๋์ด์๋ Main ํด๋์ค๋ฅผ ์์ ํด์ Hello World๋ฅผ ์ถ๋ ฅํ๋ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ์์ฑํด๋ณด์. ๊ทธ๋ฆฌ๊ณ Main ํด๋์ค ์ข์ธก์ ํ์๋ ํ์ดํ๋ฅผ ๋๋ฌ์ ๋๋ฒ๊ทธ ๋ชจ๋๋ก ์ ํ๋ฆฌ์ผ์ด์ ์ ์คํํ์. ํนํ ๋ฐฑ์๋ ๊ฐ๋ฐ์๋ผ๋ฉด ๋ฌด์กฐ๊ฑด ๋๋ฒ๊ทธ ๋ชจ๋๋ก ์คํํ๋ ์ต๊ด์ ๋ค์ฌ์ผํ๋ค.
package org.example;
import io.undertow.Undertow;
import io.undertow.util.Headers;
public class Main {
public static void main(String[] args) {
Undertow server = Undertow.builder()
.addHttpListener(8080, "localhost")
.setHandler(exchange -> {
exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, "text/plain");
exchange.getResponseSender().send("Hello World");
System.out.println("Hello World");
})
.build();
server.start();
}
}
์ธ๋ํ ์ฐ HTTP ํธ๋ค๋ฌ ๊ต์ฒดํ๊ธฐ
ํฌ๋กฌ ๋ธ๋ผ์ฐ์ ๋ฅผ ์คํํด์ localhost:8080์ ์ ๋ ฅํ๋ฉด Hello World๊ฐ ์ถ๋ ฅ๋๋ค. ๊ทธ๋ฌ๋, ์ธํ ๋ฆฌ์ ์ด ์ฝ์์ ํ์๋ ๊ฒ์ ์ดํด๋ณด๋ฉด Hello World๊ฐ ๋๋ฒ ์ถ๋ ฅ๋ ๊ฒ์ด๋ค. ์ฐ๋ฆฌ๋ ๋ธ๋ผ์ฐ์ ๋ก ํ๋ฒ ์ ๊ทผํ์ ๋ฟ์ธ๋ฐ ์ ๋๋ฒ ์ถ๋ ฅ๋๋์ง ์์ํ ๊ฒ์ ์ธ์งํด์ผํ๋ค. ์ด๋ฌํ ์ ๊ทผ์ ๋ฌธ์ ํ์ ์ ์์์ ์ด๋ค. (์์ง์ ์ต์์น ์๊ฒ ์ง๋ง) F12๋ฅผ ๋๋ฌ ๊ฐ๋ฐ์ ๋๊ตฌ๋ฅผ ํ์ํ ํ Network ํญ์ ๋๋ฅธ ๋ค F5๋ฅผ ๋๋ฌ์ ํ์ด์ง๋ฅผ ์๋ก๊ณ ์นจ ํด๋ณด๋ฉด localhost ์ด์ธ์ favicon.ico๋ผ๋ ๊ฒ์ด ์์์ ํ์ธํ ์ ์๋ค. ์ด ํ๋น์ฝ์ด๋ผ๋ ๊ฒ์ ์น ์ฌ์ดํธ ํญ ์ผ์ชฝ์ ํ์๋๋ ์์ ๋ก๊ณ ๋ฅผ ์๋ฏธํ๋ค. ๊ทธ๋ฌ๋๊น, ๋ธ๋ผ์ฐ์ ๋ ํ๋น์ฝ ํ์๋ฅผ ์ํด ์๋์ผ๋ก ์ถ๊ฐ ์์ฒญํ๊ณ ์๋ ๊ฒ์ด๋ค. ๋ ์์ธํ๊ฒ ์ดํด๋ณด๋ฉด ์ฐ๋ฆฌ๊ฐ ์์ฑํ ์ฝ๋๋๋ก text/plain ํ์ ์ Hello World๊ฐ ์ ๋ฌ๋์์์ ํ์ธํ ์ ์์ ๊ฒ์ด๋ค.
package org.example;
import io.undertow.Handlers;
import io.undertow.Undertow;
import io.undertow.util.Headers;
public class Main {
public static void main(String[] args) {
Undertow server = Undertow.builder()
.addHttpListener(8080, "localhost")
.setHandler(Handlers.path()
.addExactPath("/", exchange -> {
exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, "text/plain");
exchange.getResponseSender().send("Hello World");
System.out.println("Hello World");
}))
.build();
server.start();
}
}
๊ฒฐ๊ตญ, ๊ธฐ์กด ์ฝ๋์ ํธ๋ค๋ฌ๋ ๋ชจ๋ ์์ฒญ์ ๋ํด Hello World๋ฅผ ์ถ๋ ฅํ๋ ์ ํ๋ฆฌ์ผ์ด์ ์ด ๋ ๊ฒ์ ์๋ฏธํ๋ค. ์ด๊ฒ์ ๋ฉ์ธ ์์ฒญ์ ๋ํด์๋ง Hello World๋ฅผ ์ถ๋ ฅํ ์ ์๋๋ก ํธ๋ค๋ฌ๋ฅผ ๊ต์ฒดํด๋ณด์. ์์ ๊ฐ์ด PathHandler๋ฅผ ์ฌ์ฉํ๋ฉด ํน์ ๊ฒฝ๋ก๋ฅผ ์ฒ๋ฆฌํ ํธ๋ค๋ฌ๋ฅผ ๋ณ๋๋ก ๋ฑ๋กํ ์ ์๊ฒ ์ ๊ณตํ๋ค. ์คํ์ค์ธ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ข ๋ฃํ ํ ๋ค์ ์์ํด๋ณด๋ฉด favicon.ico์ ๋ํด์๋ ์์ฒญ์ ์ฒ๋ฆฌํ์ง ์์ 404๋ผ๋ ์๋ฏธ๋ก ๋นจ๊ฐ์์ผ๋ก ํ์๋์๊ณ ์ธํ ๋ฆฌ์ ์ด ์ฝ์์๋ ์๋ํ ๊ฒ์ฒ๋ผ Hello World๊ฐ ๋จ ํ๋ฒ ์ถ๋ ฅ๋จ์ ์ ์ ์๋ค.
์ธ๋ํ ์ฐ ์๋ธ๋ฆฟ ์ปจํ ์ด๋๋ก ์ ํํ๊ธฐ
์์ , Hello World ์ถ๋ ฅ์ ์ธ๋ํ ์ฐ์ ์ฝ์ด ๋ชจ๋์ ์ฌ์ฉํ์ฌ ์ฒ๋ฆฌํ๋ ํธ๋ค๋ฌ๋ฅผ ๋ฑ๋กํ์ ๋ฟ์ด๋ค. ์ฐ๋ฆฌ๋ ์ฒ์์ ์๋ธ๋ฆฟ ๋ชจ๋๊น์ง ์ถ๊ฐํ์ผ๋ฏ๋ก ์๋ฐ ์๋ธ๋ฆฟ์ ์ฌ์ฉํ๋ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ผ๋ก ์ ํํด๋ณด์. ์ธ๋ํ ์ฐ ์๋ธ๋ฆฟ ๋ชจ๋์ ์ฌ์ฉ๋ฒ๋ ๊ณต์ ๋ฌธ์๋ฅผ ์ฐธ๊ณ ํ๋ฉด ๋๋ค. ์ด๋์ ๋ ๋์น์ฑ ์ฌ๋๋ค์ด ์๋ค๋ฉด MVC ํจํด์ ๋ค์ด๋ดค๊ฑฐ๋ DispatcherServlet์ ์ฉ๋๋ฅผ ์๋ ๊ฒ์ผ ๊ฒ์ด๋ค. ํ์ฌ๋ ๋ณธ๋ ์ฉ๋๊ฐ ์๋ Hello World๋ฅผ ์ถ๋ ฅํ๊ธฐ ์ํ ์๋ธ๋ฆฟ์ด๊ธฐ์ ๋ชฐ๋ผ๋ ๋๋ฏ๋ก ๊ถ๊ธํ ์ฌ๋๋ค๋ง ์ฐพ์๋ณด์.
package org.example;
import io.undertow.Handlers;
import io.undertow.Undertow;
import io.undertow.servlet.Servlets;
import io.undertow.servlet.api.DeploymentInfo;
import io.undertow.servlet.api.DeploymentManager;
import jakarta.servlet.ServletException;
public class Main {
public static void main(String[] args) throws ServletException {
DeploymentInfo deployment = Servlets.deployment()
.setClassLoader(Main.class.getClassLoader())
.setContextPath("/")
.setDeploymentName("main.war")
.addServlets(Servlets.servlet("DispatcherServlet", DispatcherServlet.class)
.addMapping("/"));
DeploymentManager manager = Servlets.defaultContainer().addDeployment(deployment);
manager.deploy();
Undertow server = Undertow.builder()
.addHttpListener(8080, "localhost")
.setHandler(Handlers.path()
.addExactPath("/", manager.start()))
.build();
server.start();
}
}
package org.example;
import io.undertow.util.Headers;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
public class DispatcherServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.addHeader(Headers.CONTENT_TYPE.toString(), "text/plain");
resp.getWriter().println("Hello World");
}
}
์์ ์ฝ๋์ ๋ฌธ์ ์ ์ ๋์คํจ์ฒ์๋ธ๋ฆฟ์ด ๋ณธ ์ฉ๋๊ฐ ์๋๋ฏ๋ก ์๊ฐ์ด ๋ง๋ค๋ฉด ๋ณธ์ธ์ด ์๊ฐํ๋ ๋ฐฉ์๋๋ก ๊ณ ์ณ๋ณด๋ ๊ฒ๋ ์ถ์ฒํ๋ค. ๋ง์ ์ ์ ๊ฐ๋ฐ์๋ค์ด ์คํดํ๋ ๊ฒ์ ํจ์จ์ ์ธ ๊ด์ ์์ ์ฝ๋ ์์ฑ์ ๋ํด ์ ๋ต์ด ์๋ค๋ ๊ฒ์ด๋ผ๊ณ ์๊ฐํ๋ค๋ ๊ฒ์ผ์ง ๋ชจ๋ฅด๊ฒ ๋ค. ์ ์ฉํ ์ ๋ณด์ผ์ง๋ ๋ชจ๋ฅด๊ฒ ์ผ๋ ๋๊ตฐ๊ฐ์๊ฒ๋ ๋์์ด ๋๋ ๊ธ์ด์์ผ๋ฉด ํ๋ค.