Spark ์์ํ๊ธฐ
์น ํ๋ก๊ทธ๋๋ฐ ์
๋ฌธ์ ์ํด Java
์ ๊ฐ๋จํ ์น ํ๋ ์์ํฌ์ธ Spark
๋ฅผ ์์๋ณด์.
์ฐ์ ์ธํ
๋ฆฌ์ ์ด์์ gradle
ํ๋ก์ ํธ๋ฅผ ์์ฑํ๋ค.
๋น๋๊ฐ ์๋ฃ๋๋ฉด build.gradle
์ด๋ผ๋ ํ์ผ์ด ์์ฑ๋๋ค.
Spark
๋ฅผ ์ ์ฉํ๊ธฐ ์ํด build.gradle
์ dependency ๋ฅผ ์๋์ ๊ฐ์ด ์ถ๊ฐํ๋ค.
dependencies {
implementation "com.sparkjava:spark-core:2.9.3" // add to build.gradle (for Java users)}
}
๊ณต์ Spark
๋ฌธ์์๋ compile
ํค์๋๋ฅผ ์ฌ์ฉํ๋ผ๊ณ ๋ช
์๋์ด ์๋ค.
Gradle 7.0
๋ฒ์ ๋ถํฐ implementation
ํค์๋๋ฅผ ๋์ ์ฌ์ฉํ๊ฒ ๋ ๋ณ๊ฒฝ๋์๋ค.
์ด์ Spark
๋ฅผ ์ฌ์ฉํ ์ค๋น๊ฐ ์๋ฃ ๋์๋ค.
import static spark.Spark.*;
public class HelloWorld {
public static void main(String[] args) {
get("/users", (req, res) -> "Hello World");
}
}
main
์ ์์ ๊ฐ์ ์ฝ๋๋ฅผ ์ถ๊ฐํ์ฌ ์คํํด๋ณด์.
์คํ์ด ์ฑ๊ณต๋ ์ดํ ๋ธ๋ผ์ฐ์ ๋ฅผ ํตํด localhost:4567/users
์ ์ ์ํด๋ณด์.
์ฑ๊ณต์ ์ผ๋ก Hello World
๊ฐ ์ถ๋ ฅ๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
GET ์ฌ์ฉ๋ฒ
public class HelloWorld {
public static void main(String[] args) {
get("/users", (req, res) -> "Hello World");
}
}
์ ์ฝ๋๋ HTTP
๋ฉ์๋์ธ GET
์ Spark
์์ ์ฌ์ฉํ๋ ๋ฒ์ด๋ค.
์์ ์ธ๊ธํ localhost:4567/hello
์ ์๋ฏธ๋ถํฐ ์ดํด๋ณด์.
localhost
์์ 4567๋ฒ ํฌํธ์ /hello
์ ์ ์ํ๋ค๋ ์๋ฏธ๋ค.
Spark
์ ๊ธฐ๋ณธ ํฌํธ ๋ฒํธ๋ 4567 ์ด๊ณ port()
๋ฅผ ํตํด ํฌํธ ๋ฒํธ๋ฅผ ๋ณ๊ฒฝํ ์ ์๋ค.
public static void get(final String path, final Route route) {
getInstance().get(path, route);
}
์ด๋ฒ์ get()
๋ฉ์๋์ ๋ด๋ถ๋ฅผ ์ดํด๋ณด์.
parameter ๋ก path
์ route
๋ฅผ ๋ฐ๊ณ ์๋ค.
ํธ์ถํ๋ ๋ฉ์๋๋ฅผ ๋ค์ ์ดํด๋ณด๋ฉด path
๋ โ/users"
์์ ์ ์ ์๊ณ , route
๋ ๋๋ค์์ด argument ๋ก ์ฃผ์ด์ง๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
์ด๋ฅผ ํตํด get()
๋ฉ์๋๊ฐ URL path ๋ฅผ ์ฒซ๋ฒ์งธ argument ๋ก ๋ฐ๊ณ ํด๋น ์ฃผ์์ ์ํ๋๋ ํ์๋ฅผ ๋๋ค์์ผ๋ก ํํํ๊ณ ์๋ค๋ ๊ฒ์ ์์ธกํ ์ ์๋ค.
public class HelloWorld {
public static void main(String[] args) {
get("/users/:name", (req, res) -> "Hello " + req.params(":name"));
}
}
๋ค๋ฅธ get()
์ฌ์ฉ ์์๋ฅผ ๋ณด์.
์ด๋ฒ์ path
๊ฐ์ "/users/:name"
์ ์ ๋ฌํ๋ค.
๋ธ๋ผ์ฐ์ ์์ localhost:4567/users/meatsby
๋ฅผ ํธ์ถํ์ ๋, :name
๊ฐ์ meatsby ๊ฐ ํ ๋น๋๋ค.
req.params()
๋ฉ์๋๋ฅผ ํตํด ์ ๋ฌ๋ฐ์ ๊ฐ์ ์๋ก์ด ๋ฌธ์์ด์ ์ถ๊ฐ์์ผ localhost:4567/users/meatsby
์ฃผ์์์ โHello meatsbyโ ๋ฅผ ์ถ๋ ฅํ๊ฒ ๋๋ค.
public class HelloWorld {
public static void main(String[] args) {
get("/users", (req, res) -> "Hello " + req.queryParams("name") + " ๋์ด๋ " + req.queryParams("age"));
}
}
๋ ๋ค๋ฅธ get()
์ฌ์ฉ ์์๋ฅผ ๋ณด์.
๋ธ๋ผ์ฐ์ ์์ localhost:4567/users?name=meatsby&age=26
๋ฅผ ํธ์ถํ๋ค.
?name=meatsby&age=26
์ด ๊ตฌ๋ฌธ์ ์ฟผ๋ฆฌ์คํธ๋ง์ด๋ผ๊ณ ๋ถ๋ฆฌ๋๋ฐ, name
๊ฐ์ meatsby ๋ฅผ age
๊ฐ์ 26 ์ ์ ๋ฌํ๊ฒ ๋ค๋ ์๋ฏธ๋ฅผ ๊ฐ๊ณ ์๋ค.
์ฟผ๋ฆฌ์คํธ๋ง์ผ๋ก ์ ๋ฌ๋ ๊ฐ๋ค์ req.queryParams()
๋ฉ์๋๋ฅผ ํตํด name
๊ฐ๊ณผ age
๊ฐ์ ๋ฐ์ ์ ๋ฌ๋ฐ์ ๊ฐ์ ์๋ก์ด ๋ฌธ์์ด์ ์ถ๊ฐ์์ผ localhost:4567/users?name=meatsby&age=26
์ฃผ์์์ โHello meatsby ๋์ด๋ 26โ ์ ์ถ๋ ฅํ๊ฒ ๋๋ค.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Sign Up</title>
</head>
<body>
<h1>Sign Up</h1>
<form action="/users">
Name : <input type="text" name="name">
<br>
<br>
Age : <input type="text" name="age">
<br>
<br>
<input type="submit" value="Sign Up">
</form>
</body>
</html>
์ด๋ฒ์ ์ ์ html
์ ์ถ๊ฐํด ์ฌ์ฉ์ ์
๋ ฅ์ UI ๋ก ๋ฐ์๋ณด์.
form.html
์ resources.static
์ ์ถ๊ฐํ๋ฉด localhost:4567/form.html
์ ํตํด ์๋ก์ด UI ๊ฐ ์ถ๋ ฅ๋๋ค.
form.html
๋ด๋ถ์ input
ํ๊ทธ๋ฅผ ํตํด ๋ฐ์ดํฐ๊ฐ ์๋ฒ๋ก ์ ๋ฌ๋๋ค.
๊ฐ ๋ธ๋ก์ ๋ฐ์ดํฐ๋ฅผ ์ง์ด๋ฃ๊ณ ๋ฒํผ์ ํด๋ฆญํ๋ฉด URL ์ด redirect ๋๋ ๊ฒ์ ๋ณผ ์ ์๋ค.
์ด๋ form
ํ๊ทธ์ action
์ ํตํด ํด๋น ๋ฐ์ดํฐ๋ฅผ ์ ๋ฌํ ์ฃผ์๋ฅผ ๋ช
์ํ ์ ์๋ค.
์ด์ ๋ฐ์ดํฐ๋ action
์ด ๊ฐ๋ฆฌํค๋ /users
์ฃผ์๋ฅผ ๊ฐ๊ณ ์๋ main
์ get()
๋ฉ์๋์ ์ ๋ฌ๋๋ค.
์ ๋ฌ๋ name
๊ณผ age
๋ฅผ route
๋๋ค์์ ์ ์ฉ๋์ด ๊ธฐ์กด์ localhost:4567/users?name=meatsby&age=26
๋ฅผ ํธ์ถํ๋ ํ๋ฉด์ผ๋ก ์ด๋ํ ์ ์๋ ๊ฒ์ ๋ณผ ์ ์๋ค.
๋ง์ฝ ํด๋น ์น์ฌ์ดํธ๊ฐ ํ์๊ฐ์ ์ ๊ดํ ์น์ฌ์ดํธ์ด๊ณ ์ ๋ ฅ๋ฐ๋ ๋ฐ์ค์ ๋น๋ฐ๋ฒํธ๋ฅผ ์ ๋ ฅํ๋ค๊ณ ๊ฐ์ ํ์ ๋, url ์ ๋น๋ฐ๋ฒํธ๊ฐ ๊ทธ๋๋ก ๋ ธ์ถ๋๋ ๊ฒ์ ๋ณด์์ ๋ฌธ์ ๊ฐ ์์ ๊ฒ์ด๋ค.
์ด ๋ ์ ์ฉํ ์ ์๋ ๊ฒ์ด POST
๋ฉ์๋์ด๋ค.
POST ์ฌ์ฉ๋ฒ
public class HelloWorld {
public static void main(String[] args) {
post("/users", (req, res) -> "Hello " + req.queryParams("name") + " ๋์ด๋ " + req.queryParams("age"));
}
}
post()
์ฌ์ฉ๋ฒ์ ๊ฐ๋จํ๋ค. ์์ ๋์จ ๊ฒ ์ฒ๋ผ get()
๋ฉ์๋๋ฅผ post()
๋ก ๋ณ๊ฒฝํด์ฃผ๋ฉด ๋๋ค.
์ด๋ด ๊ฒฝ์ฐ ๊ฐ์ ๋ฐฉ๋ฒ์ผ๋ก ๋ธ๋ผ์ฐ์ ์์ ๋ฐ์ดํฐ๋ฅผ ์ ๋ฌํด๋ url ์ parameter ๊ฐ ๋ ธ์ถ๋์ง ์๋๋ค.
<form action="/users" method="post">
๋ค๋ง ์ฃผ์ํ ์ ์ form
ํ๊ทธ์ ๊ธฐ๋ณธ ๋ฉ์๋๋ get
์ด๊ธฐ ๋๋ฌธ์ post
๋ก ๋ณ๊ฒฝํด์ค์ผํ๋ค.
template engine ์ฌ์ฉ๋ฒ
template engine ์ด๋?
template engine ์ html
ํ์ผ์ ๋์ ์ผ๋ก ๋ง๋ค ๋ ์ฌ์ฉํ๋ ๋๊ตฌ์ด๋ค.
localhost:4567/form.html
- ์ฌ์ฉ์ ์ ๋ ฅ์ ๋ฐ๋ ์ ์ html
localhost:4567/users
- ์ ๋ ฅ๋ฐ์ ๊ฒฐ๊ณผ๋ฅผ ๋ณด์ฌ์ฃผ๋ ๋์ html
template engine ์ ์ฐ๋ ์ด์
public class HelloWorld {
public static void main(String[] args) {
post("/users", (req, res) -> {
return "<html>" +
"<body>" +
// ...
"</body>" +
"</html>";
}
}
}
์ฌ์ฉ์์ ์
๋ ฅ์ ๋ฐ๋ผ ๋ฌ๋ผ์ง๋ localhost:4567/users
๋ฅผ html
๋ก ํํํ๊ณ ์ ํ๋ค.
์ด๋ฅผ ์ํํ๊ธฐ ์ํด์ ์ ์ฝ๋์ ๊ฐ์ด route
์ ๋๋ค์ ๋ฐ๋์ html
ํ๊ทธ๋ฅผ ๋ฌธ์์ด๋ก ๋ฃ์ด์ฃผ๋ฉด๋๋ค.
ํ์ง๋ง ์ด๋ ๊ต์ฅํ ๋ถํธํ๊ณ ๋นํจ์จ์ ์ธ ๋ฐฉ๋ฒ์ด๋ค.
์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ์กด์ฌํ๋ ๊ฒ์ด template engine ์ธ๋ฐ, html
ํ์ผ ๊ฒฝ๋ก๋ฅผ argument ๋ก ๋ฐ์ ์ ์ฝ๋์ ๊ฐ์ ํจ๊ณผ๋ฅผ ๋ด์ค ์ ์๊ฒ ๋ง๋ค์ด ์ค๋ค.
dependency ์ ์ฉ
dependencies {
implementation "com.sparkjava:spark-template-handlebars:2.7.1"
}
Spark
์์ ์ง์ํ๋ ๋ค์ํ template engine ์ค์ handlebars ๋ฅผ ์ฌ์ฉํ๋ค.
template engine ์ ํ์ฉํ๊ธฐ ์ํด build.gradle
์ ์์ ๊ฐ์ ์ฝ๋๋ฅผ ์ถ๊ฐํด์ค๋ค.
render ๋ฉ์๋ ์ถ๊ฐ
public static String render(Map<String, Object> model, String templatePath) {
return new HandlebarsTemplateEngine().render(new ModelAndView(model, templatePath));
}
main
์ ์์ ๊ฐ์ ๋ฉ์๋๋ฅผ ์ถ๊ฐํด์ค ๋ค template engine ์ ํ์ฉํ์ฌ ๋ฐ์ดํฐ๋ฅผ ์ถ๋ ฅํ ์ ์๋ค.
public static void main(String[] args) {
staticFiles.location("/static");
post("/users", (req, res) -> {
Map<String, Object> model = new HashMap<>();
model.put("name", req.queryParams("name"));
model.put("age", req.queryParams("age"));
return render(model, "result.html");
});
}
render()
๋ฉ์๋๋ Map<String, Object>
ํ์์ผ๋ก ๊ตฌ์ฑ๋์ด ์๋ model
์ ์ธ์๋ก ๋ฐ๋๋ค.
model
์ key = template ์์ ์ฌ์ฉํ๋ ๋ณ์{{name}}
model
์ value =post
์์ฒญ์ผ๋ก ๋ฐ์ ๊ฐโmeatsbyโ
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Sign Up</title>
</head>
<body>
<h1>Sign Up Result</h1>
Name : {{name}}, Age : {{age}}
<br>
</body>
</html>
render()
๋ฉ์๋์ ์ฌ์ฉํ result.html
์ ์์ ๊ฐ์ด ๋ง๋ค์ด ์ค๋ค.
Spark
์์ ๋์ html
ํ์ผ์ ํญ์ resources.templates
๋ก ์ ๊ทผํ๊ฒ ๋ ์ค์ ๋์ด ์๊ธฐ ๋๋ฌธ์ result.html
์ ๊ผญ ํด๋น ๋๋ ํ ๋ฆฌ์ ์์น์์ผ์ผ ํ๋ค.
handlebars ๋ Mustache ๋ฌธ๋ฒ์ ์ฌ์ฉํ๋๋ฐ, {{name}}
์ model
์์ ํค๊ฐ์ด name
์ธ ๊ฐ์ ๊ฐ์ ธ์จ๋ค.
java bean ๊ณผ handlebars ๋ฐ๋ณต๋ฌธ
java bean ์ด๋?
java bean ์ด๋, ๊ธฐ๋ณธ ์์ฑ์๊ฐ ์๊ณ , iv ๋ฅผ ๊ฐ์ง๊ณ ์์ผ๋ฉฐ, iv ์ ๋ํ getter ์ setter ๊ฐ ์กด์ฌํ๋ ํด๋์ค๋ค.
handlebars ๋ฐ๋ณต๋ฌธ
public static void main(String[] args) {
staticFiles.location("/static");
List<User> users = new ArrayList<>();
post("/users", (req, res) -> {
User user = new User(req.queryParams("name"), req.queryParams("age"));
users.add(user);
Map<String, Object> model = new HashMap<>();
model.put("users", users);
return render(model, "result.html");
});
}
main
์ด User.java
๋ผ๋ java bean ํด๋์ค๊ฐ ์๊ธฐ๊ณ post
์์ฒญ์ผ๋ก ์ ๋ฌ๋ ์ธ์๋ค์ ํตํด user
๋ฅผ ์์ฑํ์ฌ ๋ฆฌ์คํธ์ ๋ด์ template ์ ๋๊ฒจ์ฃผ๋ ๋ฉ์๋๋ก ๋ณ๊ฒฝ๋์๋ค.
์ด๋ด ๊ฒฝ์ฐ result.html ์ ์ด๋ป๊ฒ ๋ณํด์ผ ํ ๊น?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Sign Up</title>
</head>
<body>
<h1>Sign Up Result</h1>
{{#users}}
Name : {{name}}, Age : {{age}}
<br>
{{/users}}
</body>
</html>
๊ฐ๋จํ๋ค. {{#users}}
์ {{/users}}
์ฝ๋ ์ฌ์ด์ ์๋ ๊ตฌ๋ฌธ์์ ์์ฐ์ค๋ฝ๊ฒ ๋ฐ๋ณต๋ฌธ์ ๋์ user
๋ฆฌ์คํธ์์ ํ๋ ์ฉ ์ถ๋ ฅํ๋ค.
๋ด๋ถ์ {{name}}
๊ณผ {{age}}
๋ ์ฌ์ค {{user.name}}
๊ณผ {{user.age}}
์ด์ง๋ง, {{#users}}
์ {{/users}}
์๊ฒ ๊ฐ์ธ์ ธ ์๊ธฐ ๋๋ฌธ์ ์๋ต์ด ๊ฐ๋ฅํ๋ค.
์ฌ๊ธฐ์ {{user.name}}
์ user.getName()
๊ณผ ๊ฐ๋ค.