μ΄μ νμ΅μμ postgres μ€μΉλ₯Ό μλ£νλ€.
β μ€μΉ νμΈ
powershell> psql -U postgres
psql (17.4)
λμλ§μ λ³΄λ €λ©΄ "help"λ₯Ό μ
λ ₯νμμμ€.
μ λ ₯νμ λ λ²μ μ΄ νμΈλλ©΄ μ μ€μΉλ κ²μ΄λ€.
β ROLE(user) λͺ©λ‘ μΆλ ₯
\du
postgres=# \du
λ‘€ λͺ©λ‘
λ‘€ μ΄λ¦ | μμ±
----------+------------------------------------------------
j797 | μνΌμ μ
memo_app |
postgres | μνΌμ μ , λ‘€ λ§λ€κΈ°, DB λ§λ€κΈ°, 볡μ , RLS ν΅κ³Ό
β μνΌμ μ κΆνμ ROLE μμ±
CREATE ROLE postgres WITH LOGIN SUPERUSER PASSWORD 'password';
CREATE ROLE
postgres=# \du
λ‘€ λͺ©λ‘
λ‘€ μ΄λ¦ | μμ±
----------+------------------------------------------------
j797 | μνΌμ μ
juyoung | μνΌμ μ
memo_app |
postgres | μνΌμ μ , λ‘€ λ§λ€κΈ°, DB λ§λ€κΈ°, 볡μ , RLS ν΅κ³Ό
β λ°μ΄ν°λ² μ΄μ€ λͺ©λ‘ μ‘°ν
\l
postgres=# \l
λ°μ΄ν°λ² μ΄μ€ λͺ©λ‘
μ΄λ¦ | μμ μ£Ό | μΈμ½λ© | λ‘μΌμΌ μ 곡μ | Collate | Ctype | λ‘μΌμΌ | ICU λ£° | μ‘μΈμ€ κΆν
-----------+----------+--------+---------------+---------+-------+--------+--------+-----------------------
memo | j797 | UTF8 | libc | ko-KR | ko-KR | | |
memo_app | memo_app | UTF8 | libc | ko-KR | ko-KR | | |
postgres | postgres | UTF8 | libc | ko-KR | ko-KR | | |
template0 | postgres | UTF8 | libc | ko-KR | ko-KR | | | =c/postgres +
| | | | | | | | postgres=CTc/postgres
template1 | postgres | UTF8 | libc | ko-KR | ko-KR | | | =c/postgres +
| | | | | | | | postgres=CTc/postgres
(5κ° ν)
γ°οΈ μ μ
powershell> psql -U username
βΉοΈ μ λͺ λ Ήμ΄λ λ΄λΆμ μΌλ‘ μλμ κ°λ€. μλ΅λ d μ΅μ μ λ΄λΆμ μΌλ‘ d username μΌλ‘ ν΄μλλ€.
psql -U username -d username -h localhost -p 5432
β μ μ νμΈ
select current_user;
current_user
--------------
postgres
(1κ° ν)
select current_database();
current_database
------------------
postgres
(1κ° ν)
β λ°μ΄ν°λ² μ΄μ€ μμ±
CREATE DATABASE username OWNER username;
β ν μ΄λΈ μμ±
psql -U username -d dbname -h localhost -p 5432
dbname=> CREATE TABLE table_name (
id SERIAL PRIMARY KEY,
title VARCHAR(100) NOT NULL,
content TEXT NOT NULL
)
CREATE TABLE
β ν μ΄λΈ λͺ©λ‘, λ·° λͺ©λ‘ μ‘°ν
-- ν
μ΄λΈ λͺ©λ‘
\dt
\dt public.*
-- λ·° λͺ©λ‘
\dv
\dv public.*
β ν μ΄λΈ, λ·° μμ
-- ν
μ΄λΈ μμ
DROP TABLE IF EXISTS sales;
-- λ·°(View) μμ
DROP VIEW IF EXISTS daily_sales;
β sql μ’ λ£
\q
projectμμ DataSource μ€μ μ ν΄ μ£Όμ΄μΌ νλ€.
1οΈβ£ application.properties > application.yml λ‘ λ³κ²½

2οΈβ£ application.yml λ¬Έλ² λ³κ²½ ν datasource μΆκ°
spring:
application:
name: memo_app
datasource:
url: jdbc:postgresql://localhost:5432/memo_app
username: memo_app
password: password
driver-class-name: org.postgresql.Driver
μ§μ μ μΈ μ 보λ νκ²½λ³μλ‘ λΉΌ μ£Όκ±°λ μ€μ νμΌλ‘ λΉΌμ gitignoreμ λ°λ‘ μΆκ°ν΄ μ£Όλ κ²μ΄ μ’λ€.
3οΈβ£ μ΄μ JdbcTemplate μ νμ©ν μ μλ€.
query(), update() κ°μ λ©μλλ‘ λ°λ³΅ μ½λλ₯Ό μ€μ¬μ€μμ½:
λ¨ λͺ μ€μ μ€μ λ§μΌλ‘λ, μ€νλ§μ΄
DataSourceβJdbcTemplateλΉμ μμ±ν΄ μ£Όλ©°, λΉμ¦λμ€ λ‘μ§μλ§ μ§μ€ν μ μκ² ν΄μ€λ€.
serviceμ μν μ΄ db-controller μ€κ³λ°μ μμ΄μ μ΄ νλ‘μ νΈμμλ μλ΅νμλ€.
λ°μ΄ν°λ² μ΄μ€μμ ν
μ΄λΈμ λΆλ¬μ μλ° μΈμ€ν΄μ€μ λ§€ννλ€.
λλ€μμΌλ‘ κ°λ¨νκ² λ§€νν μ μλ€.
// Repository
private final RowMapper<Memo> memoRowMapper = (resultSet, rowNum) ->
new Memo(
resultSet.getInt("Id"),
resultSet.getString("title"),
resultSet.getString("content")
);
repository
public List<Memo> findAll() {
return jdbcTemplate.query(
"SELECT * FROM memo ORDER BY id DESC",
memoRowMapper
);
}
controller
@GetMapping("/")
public String listMemos(Model model) {
model.addAttribute("memos", memoRepository.findAll());
return "memo-list";
}
html
<ul>
<li th:each="memo: ${memos}">
<div>
<h3 th:text="${memo.title}"></h3>
<p th:text="${memo.content}"></p>
</div>
</li>
</ul>
repository
public void save(String title, String content) {
jdbcTemplate.update(
"INSERT INTO memo (title, content) VALUES (?, ?)",
title, content
);
}
controller
@PostMapping("/add")
public String addMemo(
@RequestParam String title,
@RequestParam String content
) {
memoRepository.save(title, content);
return "redirect:/";
}
html
<form class="add-form" th:action="@{/add}" method="post">
<input type="text" name="title" placeholder="μ λͺ©μ μ
λ ₯νμΈμ" required/>
<br/>
<textarea name="content" placeholder="λ΄μ©μ μ
λ ₯νμΈμ" required></textarea>
<br/>
<button type="submit">λ©λͺ¨ μΆκ°</button>
</form>
html
<form th:action="@{/delete}" method="post" style="display:inline;">
<!-- Model memoμ idκ°μ hiddenμΌλ‘ λ겨주기 μν input -->
<input type="hidden" name="id" th:value="${memo.id}"/>
<button type="submit">μμ </button>
</form>
controller
@PostMapping("/delete")
public String deleteMemo(
@RequestParam int id
) {
memoRepository.delete(id);
return "redirect:/";
}
repository
public void delete(int id) {
jdbcTemplate.update(
"DELETE FROM memo WHERE id = ?",
id
);
}
html
<a class="btn" th:href="@{'/edit/' + ${memo.id}}">μμ </a>
controller
@GetMapping("/edit/{id}")
public String editForm(
@PathVariable int id,
Model model
) {
model.addAttribute("memo", memoRepository.findById(id));
return "memo-edit";
}
repository
public Memo findById(int id) {
return jdbcTemplate.queryForObject(
"SELECT * FROM memo WHERE id = ?",
memoRowMapper,
id
);
}
html
<h1>λ©λͺ¨ μμ </h1>
<form th:action="@{/edit}" method="post">
<input hidden="hidden" name="id" th:value="${memo.id}" />
<input type="text" name="title" th:value="${memo.title}" required />
<br />
<textarea name="content" th:text="${memo.content}" required></textarea>
<br />
<button type="submit">μμ μλ£</button>
<a href="/" class="cancle">μ·¨μ</a>
</form>
controller
@PostMapping("/edit")
public String editMemo(
@RequestParam int id,
@RequestParam String title,
@RequestParam String content
) {
memoRepository.update(id, title, content);
return "redirect:/";
}
repository
public void update(int id, String title, String content) {
jdbcTemplate.update(
"UPDATE memo SET title = ?, content = ? WHERE id = ?",
title, content, id
);
}