πŸ’« Spring

βœ”οΈ Postgres user configure

이전 ν•™μŠ΅μ—μ„œ 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개 ν–‰)
  • ν˜„μž¬ μ ‘μ†λœ db
select current_database();
 current_database
------------------
 postgres
(1개 ν–‰)

βœ… λ°μ΄ν„°λ² μ΄μŠ€ 생성

CREATE DATABASE username OWNER username;

βœ… ν…Œμ΄λΈ” 생성

  • μ˜΅μ…˜μ„ μ λ‹Ήνžˆ μž…λ ₯ν•΄μ„œ user 선택을 ν•œλ‹€. -d λ―Έμž…λ ₯ μ‹œ dbname = username
psql -U username -d dbname -h localhost -p 5432
  • μ˜ˆμ‹œ) λ©”λͺ¨μž₯을 μœ„ν•œ id, title, content
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

βœ”οΈ postgres - spring project

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 을 ν™œμš©ν•  수 μžˆλ‹€.

  • JdbcTemplate 은 JDBC μƒμœ„ 래퍼(wrapper)
    • 컀λ„₯μ…˜ νšλ“Β·μžμ› λ°˜ν™˜μ„ μžλ™ 처리
    • query(), update() 같은 λ©”μ„œλ“œλ‘œ 반볡 μ½”λ“œλ₯Ό μ€„μ—¬μ€Œ
  • RowMapper 둜 κ²°κ³Ό 집합을 POJO둜 κ°„λ‹¨νžˆ λ§€ν•‘

μš”μ•½:

단 λͺ‡ μ€„μ˜ μ„€μ •λ§ŒμœΌλ‘œλ„, μŠ€ν”„λ§μ΄ DataSource β†’ JdbcTemplate λΉˆμ„ 생성해 μ£Όλ©°, λΉ„μ¦ˆλ‹ˆμŠ€ λ‘œμ§μ—λ§Œ 집쀑할 수 있게 ν•΄μ€€λ‹€.


πŸ“ Memo App

.git

service의 역할이 db-controller 쀑계밖에 μ—†μ–΄μ„œ 이 ν”„λ‘œμ νŠΈμ—μ„œλŠ” μƒλž΅ν•˜μ˜€λ‹€.

1️⃣ μΈμŠ€ν„΄μŠ€ λ§€ν•‘

λ°μ΄ν„°λ² μ΄μŠ€μ—μ„œ ν…Œμ΄λΈ”μ„ λΆˆλŸ¬μ™€ μžλ°” μΈμŠ€ν„΄μŠ€μ— λ§€ν•‘ν•œλ‹€.
λžŒλ‹€μ‹μœΌλ‘œ κ°„λ‹¨ν•˜κ²Œ λ§€ν•‘ν•  수 μžˆλ‹€.

// Repository
private final RowMapper<Memo> memoRowMapper = (resultSet, rowNum) ->
            new Memo(
                    resultSet.getInt("Id"),
                    resultSet.getString("title"),
                    resultSet.getString("content")
            );

2️⃣ λ©”λͺ¨ 리슀트 쑰회

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>

3️⃣ λ©”λͺ¨ μΆ”κ°€

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>

4️⃣ λ©”λͺ¨ μ‚­μ œ

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
        );
    }

5️⃣ λ©”λͺ¨ μˆ˜μ •

  • λ©”λͺ¨ λ¦¬μŠ€νŠΈμ—μ„œ μˆ˜μ • λ²„νŠΌ

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
    );
}
profile
πŸ—‚οΈ hamstern

0개의 λŒ“κΈ€