Spring์ 3 Layer Architecture
- Controller ํด๋์ค ํ๋๋ก ๋ชจ๋ API๋ฅผ ์ฒ๋ฆฌํ๋ ๊ฒ์ ๋ฐ๋์งํ์ง ์๋ค!
- ์ฝ๋์ ๊ฐ๋ ์ฑ๊ณผ ์ ์ง๋ณด์๋ฅผ ๋ฌธ์ ํด๊ฒฐ์ ์ํด ์๋ฒ์์์ ์ฒ๋ฆฌ ๊ณผ์ ์ Controller, Service, Repository ๋ก ๋ถ๋ฆฌํ๋ค.
1. 3 Layer Architecture
Controller
: ํด๋ผ์ด์ธํธ์ HTTP Request๋ฅผ ๋ฐ์ Service์ ์ ๋ฌํ๋ค. (๋ง์ฝ ๋ฐ์ดํฐ๊ฐ ์์ฒญ์ ์๋ค๋ฉด ํจ๊ป ์ ๋ฌ)
- Service์์ ์ฒ๋ฆฌ ์๋ฃ๋ ๊ฒฐ๊ณผ๋ฅผ ํด๋ผ์ด์ธํธ์๊ฒ ์๋ตํ๋ค.
Service
: ์ค์ ์ฌ์ฉ์์ ์๊ตฌ์ฌํญ์ ์ฒ๋ฆฌํ๋ค. (๋น์ง๋์ค ๋ก์ง์ ๊ตฌํ)
- DB๊ด๋ จ ์์ ์ Repository์๊ฒ ์์ฒญ
Repository
: DB์ ๊ด๋ จํ ์์ ์ ์ํํ๋ค.
- DB CRUD ์์ ์ ์ฒ๋ฆฌ!
์ค์ ๊ตฌ์กฐ๋ฅผ ์ดํด๋ณด๋ฉด ์ด์ ๊ฐ๋ค!
2. ์ญํ ๋ถ๋ฆฌํ๊ธฐ
# Controller - Service ๋ฅผ ๋ถ๋ฆฌํด๋ณด์
- Service ์ญํ ์ ๊ตฌํํด์ค ํด๋์ค๊ฐ ํ์ํ๋ค.
2-1) Controller ํด๋์ค
- ํด๋ผ์ด์ธํธ์ ์์ฒญ์ ๋ฐ์ Service์ ์ ๋ฌํ๋ ์ฝ๋๋ง ์๋ค.(์ค์ ๋ก์ง์ ์ํํ๋ ๋ถ๋ถ์ Service๋ก ๋์ด๊ฐ.)
@RestController
@RequestMapping("/api")
public class MemoController {
private final JdbcTemplate jdbcTemplate;
public MemoController(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
@PostMapping("/memos")
public MemoResponseDto createMemo(@RequestBody MemoRequestDto requestDto) {
MemoService memoService = new MemoService(jdbcTemplate);
return memoService.createMemo(requestDto);
}
@GetMapping("/memos")
public List<MemoResponseDto> getMemos() {
MemoService memoService = new MemoService(jdbcTemplate);
return memoService.getMemos();
}
@PutMapping("/memos/{id}")
public Long updateMemo(@PathVariable Long id, @RequestBody MemoRequestDto requestDto) {
MemoService memoService = new MemoService(jdbcTemplate);
return memoService.updateMemo(id, requestDto);
}
@DeleteMapping("/memos/{id}")
public Long deleteMemo(@PathVariable Long id) {
MemoService memoService = new MemoService(jdbcTemplate);
return memoService.deleteMemo(id);
}
}
2-2) Service์์ ์ํํ๋ ๋ถ๋ถ!
- ์ด์ ๊ธฐ์กด Controller์์ ์ฒ๋ฆฌํ๋ ๋ก์ง์ด Service ํด๋์ค์์ ์ํ๋๋ค.
public class MemoService {
private final JdbcTemplate jdbcTemplate;
public MemoService(JdbcTemplate jdbcTemplate) { //jdbc template์ ์์ฑ์๋ก ๋ฐ๊ณ ์์
this.jdbcTemplate = jdbcTemplate;
}
public MemoResponseDto createMemo(MemoRequestDto requestDto) {
// RequestDto -> Entity
Memo memo = new Memo(requestDto);
// DB ์ ์ฅ
KeyHolder keyHolder = new GeneratedKeyHolder(); // ๊ธฐ๋ณธ ํค๋ฅผ ๋ฐํ๋ฐ๊ธฐ ์ํ ๊ฐ์ฒด
String sql = "INSERT INTO memo (username, contents) VALUES (?, ?)";
jdbcTemplate.update( con -> {
PreparedStatement preparedStatement = con.prepareStatement(sql,
Statement.RETURN_GENERATED_KEYS);
preparedStatement.setString(1, memo.getUsername());
preparedStatement.setString(2, memo.getContents());
return preparedStatement;
},
keyHolder);
// DB Insert ํ ๋ฐ์์จ ๊ธฐ๋ณธํค ํ์ธ
Long id = keyHolder.getKey().longValue();
memo.setId(id);
// Entity -> ResponseDto
MemoResponseDto memoResponseDto = new MemoResponseDto(memo);
return memoResponseDto;
}
public List<MemoResponseDto> getMemos() {
// DB ์กฐํ
String sql = "SELECT * FROM memo";
return jdbcTemplate.query(sql, new RowMapper<MemoResponseDto>() {
@Override
public MemoResponseDto mapRow(ResultSet rs, int rowNum) throws SQLException {
// SQL ์ ๊ฒฐ๊ณผ๋ก ๋ฐ์์จ Memo ๋ฐ์ดํฐ๋ค์ MemoResponseDto ํ์
์ผ๋ก ๋ณํํด์ค ๋ฉ์๋
Long id = rs.getLong("id");
String username = rs.getString("username");
String contents = rs.getString("contents");
return new MemoResponseDto(id, username, contents);
}
});
}
public Long updateMemo(Long id, MemoRequestDto requestDto) {
// ํด๋น ๋ฉ๋ชจ๊ฐ DB์ ์กด์ฌํ๋์ง ํ์ธ
Memo memo = findById(id);
if(memo != null) {
// memo ๋ด์ฉ ์์
String sql = "UPDATE memo SET username = ?, contents = ? WHERE id = ?";
jdbcTemplate.update(sql, requestDto.getUsername(), requestDto.getContents(), id);
return id;
} else {
throw new IllegalArgumentException("์ ํํ ๋ฉ๋ชจ๋ ์กด์ฌํ์ง ์์ต๋๋ค.");
}
}
public Long deleteMemo(Long id) {
// ํด๋น ๋ฉ๋ชจ๊ฐ DB์ ์กด์ฌํ๋์ง ํ์ธ
Memo memo = findById(id);
if(memo != null) {
// memo ์ญ์
String sql = "DELETE FROM memo WHERE id = ?";
jdbcTemplate.update(sql, id);
return id;
} else {
throw new IllegalArgumentException("์ ํํ ๋ฉ๋ชจ๋ ์กด์ฌํ์ง ์์ต๋๋ค.");
}
}
private Memo findById(Long id) {
// DB ์กฐํ
String sql = "SELECT * FROM memo WHERE id = ?";
return jdbcTemplate.query(sql, resultSet -> {
if(resultSet.next()) {
Memo memo = new Memo();
memo.setUsername(resultSet.getString("username"));
memo.setContents(resultSet.getString("contents"));
return memo;
} else {
return null;
}
}, id);
}
}
<์ ๋ฆฌ>
๋น์ง๋์ค ๋ก์ง์ ์ฒ๋ฆฌํ ์๋น์ค ํด๋์ค๊ฐ ํ์ํจ.
์๋น์ค๋ก ์์ฒญ์ ์ ๋ฌํ๊ธฐ ์ํด์ ์๋น์ค ๊ฐ์ฒด๋ฅผ ์์ฑํด์ค.
๊ทธ๋ฆฌ๊ณ ํด๋น ๋ฉ์๋์ ๋ฆฌํด๊ฐ์ ์ปจํธ๋กค๋ฌ์ ๋ฉ์๋์.
๊ทธ ์์ฒญ ๋ด์ฉ์ ์ฒ๋ฆฌํ ๋ฉ์๋๊ฐ ๋น์ฐํ ์๋น์ค ์ธก์๋ ํ์ํจ
๊ทธ๋์ ์ปจํธ๋กค๋ฌ์ ๋์ผํ ์ด๋ฆ์ ๋ฉ์๋๋ฅผ ์์ฑํ์ฌ
์ค์ ๋น์ง๋์ค ๋ก์ง์ ํด๋น ๋ฉ์๋์ ๊ตฌํํ๋ค.
# Service - Repository ๋ถ๋ฆฌํ๊ธฐ!
- DB ์ฐ๊ฒฐ ๋ฐ CRUD ์์ Repository์์ ์งํ
- ๋ง์ฐฌ๊ฐ์ง๋ก ํด๋์ค ๋ง๋ค์ด์ค๋ค!
- Service์์ Repository ์ธ์คํด์คํํด์ ํธ์ถ ๊ทธ๋ฆฌ๊ณ DB๊ด๋ จํ ์์ ๋๊ฒจ์ค
2-3) Repository ํด๋์ค
public class MemoRepository {
private final JdbcTemplate jdbcTemplate;
public MemoRepository(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
public Memo save(Memo memo) {
// DB ์ ์ฅ
KeyHolder keyHolder = new GeneratedKeyHolder(); // ๊ธฐ๋ณธ ํค๋ฅผ ๋ฐํ๋ฐ๊ธฐ ์ํ ๊ฐ์ฒด
String sql = "INSERT INTO memo (username, contents) VALUES (?, ?)";
jdbcTemplate.update(con -> {
PreparedStatement preparedStatement = con.prepareStatement(sql,
Statement.RETURN_GENERATED_KEYS);
preparedStatement.setString(1, memo.getUsername());
preparedStatement.setString(2, memo.getContents());
return preparedStatement;
},
keyHolder);
// DB Insert ํ ๋ฐ์์จ ๊ธฐ๋ณธํค ํ์ธ
Long id = keyHolder.getKey().longValue();
memo.setId(id);
return memo;
}
public List<MemoResponseDto> findAll() {
// DB ์กฐํ
String sql = "SELECT * FROM memo";
return jdbcTemplate.query(sql, new RowMapper<MemoResponseDto>() {
@Override
public MemoResponseDto mapRow(ResultSet rs, int rowNum) throws SQLException {
// SQL ์ ๊ฒฐ๊ณผ๋ก ๋ฐ์์จ Memo ๋ฐ์ดํฐ๋ค์ MemoResponseDto ํ์
์ผ๋ก ๋ณํํด์ค ๋ฉ์๋
Long id = rs.getLong("id");
String username = rs.getString("username");
String contents = rs.getString("contents");
return new MemoResponseDto(id, username, contents);
}
});
}
public void update(Long id, MemoRequestDto requestDto) {
String sql = "UPDATE memo SET username = ?, contents = ? WHERE id = ?";
jdbcTemplate.update(sql, requestDto.getUsername(), requestDto.getContents(), id);
}
public void delete(Long id) {
String sql = "DELETE FROM memo WHERE id = ?";
jdbcTemplate.update(sql, id);
}
public Memo findById(Long id) {
// DB ์กฐํ
String sql = "SELECT * FROM memo WHERE id = ?";
return jdbcTemplate.query(sql, resultSet -> {
if (resultSet.next()) {
Memo memo = new Memo();
memo.setUsername(resultSet.getString("username"));
memo.setContents(resultSet.getString("contents"));
return memo;
} else {
return null;
}
}, id);
}
}
4) DB ๊ด๋ จ ์์ ์ ๋ชจ๋ Repository์ ๋๊ธด ํ์ Service!
public class MemoService {
private final JdbcTemplate jdbcTemplate;
public MemoService(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
public MemoResponseDto createMemo(MemoRequestDto requestDto) {
// RequestDto -> Entity
Memo memo = new Memo(requestDto);
// DB ์ ์ฅ
MemoRepository memoRepository = new MemoRepository(jdbcTemplate);
//๋ฉ๋ชจ๋ฅผ ์ ์ฅํ ๋ฉ์๋ ํ๋ ๋ง๋ค์ด์ค!
Memo saveMemo = memoRepository.save(memo);
// Entity -> ResponseDto
MemoResponseDto memoResponseDto = new MemoResponseDto(saveMemo);
return memoResponseDto;
}
public List<MemoResponseDto> getMemos() {
// DB ์กฐํ
MemoRepository memoRepository = new MemoRepository(jdbcTemplate);
return memoRepository.findAll();
}
public Long updateMemo(Long id, MemoRequestDto requestDto) {
MemoRepository memoRepository = new MemoRepository(jdbcTemplate);
// ํด๋น ๋ฉ๋ชจ๊ฐ DB์ ์กด์ฌํ๋์ง ํ์ธ
Memo memo = memoRepository.findById(id);
if (memo != null) {
// memo ๋ด์ฉ ์์
memoRepository.update(id, requestDto);
return id;
} else {
throw new IllegalArgumentException("์ ํํ ๋ฉ๋ชจ๋ ์กด์ฌํ์ง ์์ต๋๋ค.");
}
}
public Long deleteMemo(Long id) {
MemoRepository memoRepository = new MemoRepository(jdbcTemplate);
// ํด๋น ๋ฉ๋ชจ๊ฐ DB์ ์กด์ฌํ๋์ง ํ์ธ
Memo memo = memoRepository.findById(id);
if (memo != null) {
// memo ์ญ์
memoRepository.delete(id);
return id;
} else {
throw new IllegalArgumentException("์ ํํ ๋ฉ๋ชจ๋ ์กด์ฌํ์ง ์์ต๋๋ค.");
}
}
}
์ด๋ ๊ฒ 3 Layer Architecture ๋ก ๋ถ๋ฆฌ๋ฅผ ํด์ฃผ๋ฉด
DB ๊ด๋ จ ์์ -> Repository
๋น์ง๋์ค ๋ก์ง ์์ -> Service
๋ฐ์ดํฐ ์ ๋ฌํ๋ ๋ฐฉ์ ์์ -> Controller
๊ฐ๊ฐ ์ฉ๋์ ๋ง๋ ํด๋์ค๋ฅผ ๋ง๋ค์ด ์ฝ๋๋ฅผ ์์ฑํ๊ณ ์์ ์ฌํญ ๋ํ ๊ฐ๊ฐ ๋ณ๊ฒฝํด์ฃผ๋ฉด ๋๋ค!
์ด๋ ๊ฒ ๋ถ๋ฆฌํด์ ์ฝ๋๋ฅผ ์์ฑํ๊ฒ ๋๋ฉด ์ ์ง๋ณด์์ ํจ์ฌ ์ ๋ฆฌํ ๊ฒ์ด๋ค!
'Spring' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
TIL Spring #2-3 (0) | 2023.12.12 |
---|---|
TIL Spring 2-2 (0) | 2023.12.08 |
TIL Spring 1-3 (0) | 2023.12.06 |
TIL Spring 1-2 (0) | 2023.12.05 |
TIL Spring #1-1 (0) | 2023.12.04 |