๊ฐ์
์คํ๋ง ๋ฐ์ดํฐ JPA๋ฅผ ์ฐ๋ค ๋ณด๋ฉด, ๊ฑฐ์ ๋ฌด์กฐ๊ฑด ์ํฐํฐ๋ฅผ ์ ์ฅํ๋ save ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ ์ ์ด ์์ผ์ค ๊ฒ์
๋๋ค.
๊ทธ๋ฐ๋ฐ save์ ๋ฐํ ํ์
์ผ๋ก๋ ์ด๋ค ๊ฒ์ ์จ์ผ ํ ์ง ๊ณ ๋ฏผ์ด ๋ค์๋ ์ ์ด ์์ผ์ ๊ฐ์? ์ค๋์ ์ด์ฉ๋ฉด ๋ฌด์์์ ์ผ๋ก ๋๊ฒจ๋ฒ๋ฆฌ๊ธฐ๋ง ํ๋ ๋ฐํ ํ์
์ ๋ํด ๊ธ์ ์จ ๋ณด๊ณ ์ ํฉ๋๋ค.
save ๋ฉ์๋ ์๊ฐ
์ฐ์ , ์คํ๋ง ๋ฐ์ดํฐ JPA์ ์์ฑ๋์ด ์๋ save ๋ฉ์๋๋ ์๋ ๊ตฌ์กฐ๋ก ๋์ด ์์ต๋๋ค.
@NoRepositoryBean
public interface CrudRepository<T, ID> extends Repository<T, ID> {
<S extends T> S save(S entity);
...
}
์ฒซ ๋ฒ์งธ๋ก, JpaRepository<T, ID> (์ธํฐํ์ด์ค)๋ ๋ฐ๋ผ๊ฐ๋ค ๋ณด๋ฉด CrudRepository<T, ID> (์ธํฐํ์ด์ค)๋ฅผ ์์๋ฐ์ต๋๋ค.
๊ทธ๋ฆฌ๊ณ ์ด JpaRepository<T, ID> ์ธํฐํ์ด์ค๋ JpaRepositoryImplementation<T, ID> ์ธํฐํ์ด์ค๊ฐ ์์๋ฐ์ผ๋ฉฐ, ์ด๊ฒ์ ๊ตฌํ์ฒด๋ก SimpleJpaRepository<T, ID>๊ฐ ์์ต๋๋ค.
@Repository
@Transactional(
readOnly = true
)
public class SimpleJpaRepository<T, ID> implements JpaRepositoryImplementation<T, ID> {
...
@Transactional
public <S extends T> S save(S entity) {
Assert.notNull(entity, "Entity must not be null");
if (this.entityInformation.isNew(entity)) {
this.entityManager.persist(entity);
return entity;
} else {
return this.entityManager.merge(entity);
}
}
...
}
๊ตฌํ์ฒด์ ์ธํฐํ์ด์ค๋ฅผ ๋ณด๋ฉด, ๋ฉ์๋์ ์ธ์๋ก ๋๊ธด S ํ์
์ ๋ฐํํจ์ ์ ์ ์์ต๋๋ค.
Repository์ ๋ฐํ ํ์ ์ผ๋ก ๊ฐ๋ฅํ ๊ฒ
์ด ๊ธ์์ ์ฌ์ฉํ Repository๋ ์คํ๋ง ๋ฐ์ดํฐ JPA๋ฅผ ๊ทธ๋๋ก ์ฌ์ฉํ๋ ๊ฒ์ด ์๋๋ผ, ์๋์ฒ๋ผ ๋๋ฉ์ธ์์ ์ฌ์ฉํ Repository ์ธํฐํ์ด์ค๋ฅผ ๋ง๋ค๊ณ ๊ตฌํ์ฒด๋ฅผ ์ ์ํ ๋ ์คํ๋ง ๋ฐ์ดํฐ JPA๋ฅผ ํ๋๋ก ๊ฐ์ง ๊ตฌ์กฐ์ ๋๋ค.
๊ฒ์๊ธ (Board)์ ๋ํ C/R ์ฝ๋๋ฅผ ์๋ก ๋ค๊ฒ ์ต๋๋ค!
BoardRepository ์ฝ๋
public interface BoardRepository {
[Board | void] save(final Board board);
Optional<Board> findById(final Long id);
List<Board> findAll();
}
์คํ๋ง ๋ฐ์ดํฐ JPA ์ฝ๋
public interface BoardJpaRepository extends JpaRepository<Board, Long> {
...
}
BoardJpaRepositoryImpl ์ฝ๋ (๊ตฌํ์ฒด)
@RequiredArgsConstructor
@Repository
public class JpaBoardRepositoryImpl implements BoardRepository {
private final BoardJpaRepository boardJpaRepository;
@Override
public [Board | void] save(final Board board) {
...
}
@Override
public Optional<Board> findById(final Long id) {
return boardJpaRepository.findById(id);
}
@Override
public List<Board> findAll() {
return boardJpaRepository.findAll();
}
}
์์ ์ฝ๋๋ฅผ ์ฐธ๊ณ ํ๋ฉด, ๋ฐํ ํ์
์ผ๋ก ๊ฐ๋ฅํ ๊ฒ์ ํฌ๊ฒ ์ํฐํฐ๋ฅผ ๋ฐํํ๋๋, void๋ฅผ ๋ฐํํ๋๋๋ก ๋๋ ์ ์์ต๋๋ค.
๊ฐ ๋ฐฉ์์ ์ ํํ์ ๋ ์ด๋ ํ ํน์ง์ด ์๋์ง ์์๋ณด๊ฒ ์ต๋๋ค!
1. ๋ฉ์๋์ ์ธ์๋ก ๋ฐ์ ์ํฐํฐ ํ์ ์์ฒด๋ฅผ ๋ฐํํ๋ ๋ฐฉ๋ฒ (์์ํ๋ ์ํฐํฐ ๋ฐํ)
์๋
์คํ๋ง ๋ฐ์ดํฐ JPA์ ๋ฐํ ํ์ ์ ๊ทธ๋๋ก ๊ณ์นํ๊ธฐ ์ํจ์ ๋๋ค.
์ฅ์
- ์์ํ๋ Entity๋ฅผ ๋ฐํํ๊ธฐ์ Service์์๋ Entity, Long (= id) ํ์ ์ ๋ฐํํ ๋ id๊ฐ null์ด ์๋๋๋ค.
- Service์์ ๋ฐํํ ํ์ ์ ๋ํ ์ ์ฝ์ด ์์ต๋๋ค. (Service์์ Controller์๊ฒ ์ด๋ค ๊ฐ์ ์ ๊ณตํ๋ ์ง ๋ฌธ์ ๊ฐ ์์ต๋๋ค.)
- ํ ์คํธ ์ id ๊ฐ์ ๊บผ๋ผ ์ ์์ผ๋ฏ๋ก ํ ์คํธ ์์ฑ์ด ํธ๋ฆฌํฉ๋๋ค.
๋จ์
- void๋ฅผ ๋ฐํํ ๋ ๋ณด๋ค ์ฑ ์ (์์ํ)์๋ง ์ง์คํ๋ค๋ ์๋๊ฐ ํ๋ ค์ง๋๋ค.
์์ - ๊ตฌํ ์ฝ๋
๋๋ฉ์ธ ์ฝ๋๋ ์๋์ฒ๋ผ ๋์ด ์์ต๋๋ค. (์ต์ํ์ ์ฝ๋ - ๋ฆฌํฌ์งํ ๋ฆฌ๊ฐ void ํ์ ์ผ ๋์๋ ๋์ผ)
// import ํํ์ ์๋ต
@Getter
@Builder
@AllArgsConstructor(access = AccessLevel.PROTECTED)
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Entity
public class Board {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String title;
@Column(nullable = false)
private String content;
public Board(final String title, final String content) {
this.title = title;
this.content = content;
}
}
์ปจํธ๋กค๋ฌ ์ฝ๋๋ ์๋์ฒ๋ผ ๋์ด ์์ต๋๋ค.
// import ํํ์ ์๋ต
@RequiredArgsConstructor
@RequestMapping("/boards")
@RestController
public class BoardController {
private final BoardService boardService;
@PostMapping
public ResponseEntity<BoardWriteResponse> write(@RequestBody @Valid final BoardWriteRequest request) {
Board writeBoard = boardService.write(request);
BoardWriteResponse response = BoardWriteResponse.from(writeBoard);
return ResponseEntity.ok(response);
}
@GetMapping("/{id}")
public ResponseEntity<BoardFindResponse> findBoardById(@PathVariable final Long id) {
Board findBoard = boardService.findById(id);
BoardFindResponse response = BoardFindResponse.from(findBoard);
return ResponseEntity.ok(response);
}
@GetMapping
public ResponseEntity<List<BoardFindResponse>> findAllBoards() {
List<BoardFindResponse> responses = boardService.findAllBoards()
.stream()
.map(BoardFindResponse::from)
.toList();
return ResponseEntity.ok(responses);
}
}
์๋น์ค ์ฝ๋๋ ์๋์ ๊ฐ์ต๋๋ค. ์๋น์ค์์๋ ๊ธ ์ ์ฅ ์ ์ํฐํฐ๋ฅผ ๋ฐํํ๋ ๊ฒ์ผ๋ก ๊ฐ์ ํ๊ฒ ์ต๋๋ค.
์ฝ๋๋ฅผ ๋ณด๋ฉด ์๋น์ค์์ ์์ํ๋ ์ํฐํฐ๋ฅผ ๋ฐํํ๊ฑฐ๋ ์์ํ๋ id๋ฅผ ๋ฐํํ๋ ๋ฐ ์ ์ฝ์ด ์์์ ์ ์ ์์ต๋๋ค.
๋ง์ฝ ๋ฆฌํฌ์งํ ๋ฆฌ๊ฐ void ํ์
์ด๋ผ๋ฉด ์๋น์ค์์ ์ํฐํฐ๋ฅผ ๋ฐํํ๊ฑฐ๋ id๋ฅผ ๋ฐํํ๊ณ ์ ํ ๋์๋ id๊ฐ ์ ์ฅ๋์ง ์์ ๊ฒ์ด ์ปจํธ๋กค๋ฌ์ ์ ๋ฌ๋ ๊ฒ์
๋๋ค.
// import ํํ์ ์๋ต
@Transactional(readOnly = true)
@RequiredArgsConstructor
@Service
public class BoardService {
private final BoardRepository boardRepository;
@Transactional
public Board write(final BoardWriteRequest request) {
Board newBoard = new Board(request.title(), request.content());
return boardRepository.save(newBoard); // ์๋น์ค์์ ์์ํ๋ ์ํฐํฐ๋ฅผ ๋ฐํํ๊ฑฐ๋ ์์ํ๋ id๋ฅผ ๋ฐํํ๋ ๋ฐ ์ ์ฝ์ด ์์ต๋๋ค!
}
public Board findById(final Long id) {
return boardRepository.findById(id)
.orElseThrow(BoardNotFoundException::new);
}
public List<Board> findAllBoards() {
return boardRepository.findAll();
}
}
์์ - ํ ์คํธ ์ฝ๋
์๋น์ค ์ฝ๋์์ ์ ์ฝ์ด ์์์ ์์๋ดค์ผ๋, ํ
์คํธ ์ฝ๋๋ ์ด๋ป๊ฒ ์์ฑํ ์ง ๋ณด๊ฒ ์ต๋๋ค. (ํ
์คํธ ๊ฒฉ๋ฆฌ๋ฅผ ์ํ ์ด๋
ธํ
์ด์
๋ค์ ์์ฑํ ๊ฒ ์๋๋ฐ, ์ด๊ฒ์ ๋ํด์๋ ์ถํ ์์ฑํ๊ฒ ์ต๋๋ค!)
์๋๋ Repository์ ๋ํ ํ
์คํธ ์ฝ๋์
๋๋ค.
// import ํํ์ ์๋ต
@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)
@SuppressWarnings("NonAsciiCharacters")
@DataJpaTest
@CleanDatabase // ํ
์คํธ ๊ฒฉ๋ฆฌ ์ด๋
ธํ
์ด์
public class JpaBoardRepositoryTest {
@Autowired
private BoardJpaRepository boardJpaRepository;
@Test
void ๊ฒ์๊ธ์_์ ์ฅํ๋ค() {
// given
Board writeBoard = BoardFixtures.๊ฒ์๊ธ_id_์์(); // ์๋น์ค์์ ์์ฑํ Board๋ id๊ฐ ์์ต๋๋ค.
Long expectedId = 1L;
// when
Board saveBoard = boardJpaRepository.save(writeBoard);
// then
SoftAssertions.assertSoftly(softly -> {
softly.assertThat(saveBoard.getId()).isEqualTo(expectedId);
softly.assertThat(saveBoard).usingRecursiveComparison()
.ignoringFields("id")
.isEqualTo(writeBoard);
});
}
...
}
๋ฆฌํฌ์งํ ๋ฆฌ์์ ๋ฐํํ Board๋ ์์ํ๋ ๊ฒ์๊ธ์ด๊ธฐ ๋๋ฌธ์, ๊ธฐ์กด writeBoard์์ id๊ฐ ์์ฑ๋์ด ์์ง ์๋๋ผ๋ saveBoard์ id ๊ฐ์ด expectedId์ ๊ฐ์์ ๊ฒ์ฆํด ๋ณผ ์ ์์ต๋๋ค.
JPA ํ๊ฒฝ์์์ ํ ์คํธ์ด๊ธฐ์, Repository์์ void๋ก ๋ฐํํ๋๋ผ๋ ์ ํ ์คํธ๋ ํต๊ณผํ๊ฒ ๋ฉ๋๋ค. EntityManager๊ฐ persist ํจ์ ๋ฐ๋ผ ์์์ฑ ์ปจํ ์คํธ์ ์ ์ฅ๋์ด id๋ฅผ ํ ๋น๋ฐ์ ์ ์๊ธฐ ๋๋ฌธ์ ๋๋ค.
writeBoard์๋ id๊ฐ null/1L๋ก ๋ค๋ฅด๊ธฐ ๋๋ฌธ์ id๋ฅผ ์ ์ธํ ๋๋จธ์ง ์์ฑ์ ๋ํด์ ๊ฐ์์ง ๋น๊ตํจ์ผ๋ก์จ ๊ฒ์ฆํด์ผ ํฉ๋๋ค.
Service์ ๋ํ ํ
์คํธ๋ ์๋์ ๊ฐ์ต๋๋ค.
// import ํํ์ ์๋ต
@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)
@SuppressWarnings("NonAsciiCharacters")
public class BoardServiceTest {
private BoardService boardService;
private BoardRepository boardRepository;
@BeforeEach
void init() {
boardRepository = new BoardFakeRepository(); // HashMap<Long, Board>๋ฅผ ๊ฐ์ง ํ
์คํธ ๋ฆฌํฌ์งํ ๋ฆฌ
boardService = new BoardService(boardRepository);
}
@Test
void ๊ฒ์๊ธ์_์ ์ฅํ๋ค() {
// given
String title = "default title";
String content = "default content";
BoardWriteRequest request = new BoardWriteRequest(title, content);
Long expectedId = 1L;
// when
Board writeBoard = boardService.write(request);
// then
SoftAssertions.assertSoftly(softly -> {
softly.assertThat(writeBoard.getId()).isEqualTo(expectedId);
softly.assertThat(writeBoard.getTitle()).isEqualTo(title);
softly.assertThat(writeBoard.getContent()).isEqualTo(content);
});
}
...
}
๋ฆฌํฌ์งํ ๋ฆฌ์์์ ๋ง์ฐฌ๊ฐ์ง๋ก id์ ๋ํ ์ค์ ๊ฐ์ ๊ฒ์ฆํ ์ ์์ต๋๋ค.
2. void๋ฅผ ๋ฐํํ๋ ๋ฐฉ๋ฒ
์๋
Repository๊ฐ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์์ํํ๋ ๊ฒ์๋ง ์ง์ค์ํค๊ธฐ ์ํจ์ ๋๋ค.
์ฅ์
Repository๊ฐ ๊ฐ์ง ์ฑ ์ (์์ํ)์๋ง ์ง์คํ ์ ์์ต๋๋ค.
๋จ์
- Service์์ Entity, Long (= id) ํ์ ์ ๋ฐํ์ํฌ ๊ฒฝ์ฐ id๊ฐ null๋ก ๋ฉ๋๋ค. (์๋น์ค ํ ์คํธ ํ์ , ์ค์ ํ๋ก๋์ ์์๋ JPA๋ฅผ ํ์ฉํ ๊ฒฝ์ฐ id๋ฅผ ๋ฐ์ ์ ์์ต๋๋ค.)
- Service์์ void๋ก ๋ฐํํ ์๋ ์์ผ๋, ๊ทธ๋ ๊ฒ ๋๋ฉด Controller์์ ์ ์ฅ๋ Entity์ ๋ํ ์๋ฌด ์ ๋ณด๋ ์ป์ ์ ์์ต๋๋ค. (์ด๋ Service์์ void๋ฅผ ๋ฐํํ ๋์ ๋จ์ ์ด๊ธฐ๋ ํฉ๋๋ค.)
- ํ ์คํธ ์ ๋ถํธํจ์ด ๋ฐ๋ฆ ๋๋ค. id๊ฐ์ ๊บผ๋ด๋ฉด null์ด ๋๊ธฐ ๋๋ฌธ์ ๋๋ค. ๋ฐ๋ผ์ findAll(), verify() ๋ฑ์ผ๋ก ๊ฒ์ฆ์ ํด์ผ ํฉ๋๋ค.
์์ - ๊ตฌํ ์ฝ๋
๋๋ฉ์ธ, ์ปจํธ๋กค๋ฌ ์ฝ๋๋ ๋ณํจ์ด ์์ต๋๋ค.
์๋น์ค ์ฝ๋๋ ์๋์ฒ๋ผ ์์ฑ๋ฉ๋๋ค.
// import ํํ์ ์๋ต
@Transactional(readOnly = true)
@RequiredArgsConstructor
@Service
public class BoardService {
private final BoardRepository boardRepository;
@Transactional
public Board write(final BoardWriteRequest request) {
Board newBoard = new Board(request.title(), request.content());
boardRepository.save(newBoard);
return newBoard; // JPA์์๋ save ์ persist๋ฅผ ํ ๋ค์ id๊ฐ ์ ์ฅ๋๊ธฐ ๋๋ฌธ์ save ์ดํ newBoard๋ฅผ ์ ๋ฌํ๋ฉด id๊ฐ ์์ต๋๋ค.
}
...
}
์์ - ํ ์คํธ ์ฝ๋
์์ ๋ฆฌํฌ์งํ ๋ฆฌ์์์ ํ
์คํธ (JpaBoardRepositoryTest)์์ ์์ฑํ์๋ฏ, Repository์์ save์ ๋ฐํ ํ์
์ ์ํฐํฐ๋ก ํ๋ ์ง void๋ก ํ๋ ์ง์ ์๊ด์์ด Repository์ ๋ํ ํ
์คํธ๋ ๋ฌธ์ ์์ด ํต๊ณผํ๊ฒ ๋ฉ๋๋ค. ์ด๋ JPA๊ฐ ๊ฐ์ง ํน์ฑ (save ์ persist/merge๊ฐ ๋ฐ์ํ๊ณ , ์ดํ ์์์ฑ ์ปจํ
์คํธ์ id๋ฅผ ๊ฐ์ง ์ฑ๋ก ๋ณด๊ด) ๋๋ฌธ์
๋๋ค.
๋ฌธ์ ๋ ์๋น์ค ํ
์คํธ ์ฝ๋์
๋๋ค. ์๋น์ค ํ
์คํธ ์ฝ๋๋ JPA๋ฅผ ์ฌ์ฉํ์ง ์๋, HashMap์ ์ฌ์ฉํ๋ BoardFakeRepository๋ฅผ ์ฌ์ฉํฉ๋๋ค. ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ์์์ฑ ์ปจํ
์คํธ์ ๋์์ ๋ฐ์ง ๋ชปํ๋ฉฐ, ์๋์ BoardFakeRepository๋ฅผ ๋ณด๋ฉด ์ธ์๋ก ๋ฐ์ Board์ id์ ๋ํด์๋ id ๊ฐ์ด ์ ์ฅ๋์ง ์๋ ์ ์ ์ ์ ์์ต๋๋ค. (๊ทธ๋ ๋ค๊ณ id๋ฅผ set ํ๊ธฐ ์ํ Setter ๋ฉ์๋๋ฅผ ๋ง๋ ๋ค๋ฉด, ํ
์คํธ๋ฅผ ์ํด ๋ฉ์๋๋ฅผ ์ถ๊ฐํ๋ ๊ฒ์ด๋ ์ด๋ ์ง์ํด์ผ ํฉ๋๋ค.)
// import ํํ์ ์๋ต
// ์๋น์ค์ ๊ธฐ๋ฅ ๊ฒ์ฆ์๋ง ์ง์คํ๊ธฐ ์ํด JPA๋ฅผ ์ฌ์ฉํ์ง ์๋ ์์์ ํ
์คํธ ๋ฆฌํฌ์งํ ๋ฆฌ๋ฅผ ์ฌ์ฉํฉ๋๋ค.
public class BoardFakeRepository implements BoardRepository {
private final static HashMap<Long, Board> store = new HashMap<>();
private Long id = 1L;
@Override
// ๋ง์ฝ Board๋ฅผ ๋ฆฌํดํ๋ค๋ฉด id๊ฐ ์ ์ฅ๋ newBoard๋ฅผ ๋ฆฌํดํ ๊ฒ์
๋๋ค.
public void save(final Board board) {
Board newBoard = Board.builder()
.id(id)
.title(board.getTitle())
.content(board.getContent())
.build();
store.put(id, newBoard);
id++;
}
...
}
๊ทธ๋์ ์๋์ฒ๋ผ ์์ธ๊ฐ ๋ฐ์ํฉ๋๋ค.
findAll๋ก ์ ์ฅ๋์๋์ง ๊ฒ์ฆํจ์ผ๋ก์จ ์ฐํ์ ์ผ๋ก ํ์ธํ ์ ์์ต๋๋ค.
@Test
void ๊ฒ์๊ธ์_์ ์ฅํ๋ค() {
// given
String title = "default title";
String content = "default content";
BoardWriteRequest request = new BoardWriteRequest(title, content);
// Long expectedId = 1L;
int expectedSize = 1;
// when
Board writeBoard = boardService.write(request);
// then
assertSoftly(softly -> {
// softly.assertThat(writeBoard.getId()).isEqualTo(expectedId);
softly.assertThat(boardService.findAllBoards()).hasSize(expectedSize);
softly.assertThat(writeBoard.getTitle()).isEqualTo(title);
softly.assertThat(writeBoard.getContent()).isEqualTo(content);
});
}
...
}
์ถ๊ฐ: Service์์ ์ ์ฅ ์ ๋ฐํ ํ์
Service์์๋ ๋ฐํ ํ์ ์ ๋ํ ๊ณ ๋ฏผ์ด ์๊น๋๋ค. ์ ์ฅ๋ (์์ํ๋) ์ํฐํฐ๋ฅผ ๋ฐํํด์ผ ํ ๊น์, ์๋๋ฉด id (Long) ํ์ ์ ๋ฐํํ๋ ๊ฒ ์ข์๊น์? ์ด ๋ํ ๊ฐ๊ธฐ ์ฅ๋จ์ ์ด ์์ต๋๋ค. (์ด๋ค ๋ถ๋ค์ DTO๋ก ๋ฐํํ๋ ๋ฐฉ์์ผ๋ก ์ฌ์ฉํ์๊ธฐ๋ ํ๋๋ฐ, DTO๋ฅผ ๋ฐํํ๋ ๋ฐฉ์์ ๊ฒฐ๊ตญ ํํ ๊ณ์ธต์ ๋ํด ์์กด๋๋ฏ๋ก ์ ํฉํ์ง ์๋ค๋ ์๊ฐ์ ๊ฐ์ง๊ณ ์์ต๋๋ค. ๋ฐ๋ผ์ ์ํฐํฐ/Long ๋ฐํ ๋ฐฉ์์ ์ฐจ์ด์ ๋ํด์๋ง ์์ฑํ๊ฒ ์ต๋๋ค.)
์ํฐํฐ๋ฅผ ๋ฐํํ๋ ๊ฒฝ์ฐ
์ฅ์
- ํํ ์์ญ์์ id ๋ง๊ณ ๋ ๋ค๋ฅธ ๊ฐ (์ ๋ชฉ, ๊ธ ๋ฑ)์ ํ์๋ก ํ ๊ฒฝ์ฐ ์ํฐํฐ์์ ์ด๋์ด๋ผ ์ ์์ต๋๋ค.
๋จ์
- ๋ช ๋ น๊ณผ ์กฐํ์ ๋ถ๋ฆฌ (์๋ ์์น)์ ์๋์ ๋ง์ง ์์ต๋๋ค.
id (Long)๋ฅผ ๋ฐํํ๋ ๊ฒฝ์ฐ
์ฅ์
- ๋ช ๋ น๊ณผ ์กฐํ์ ๋ถ๋ฆฌ (CQRS: Command and Query Responsibility Segregation) ์์น์ ์งํค๋ ๋ฐ ์ ํฉํฉ๋๋ค. ์กฐํ๋ฅผ ์ํ ์ต์ํ์ ์ ๋ณด๋ง ์ ๊ณตํ ์ ์์ต๋๋ค.
๋จ์
- ์๋น์ค์์ id๋ง์ ๋ฐํํ๋ค๋ฉด, ํํ ์์ญ (์ปจํธ๋กค๋ฌ) ๋ํ id๋ง์ ์ ๊ณตํ๊ฒ ๋ฉ๋๋ค.
๊ฒฐ๋ก
๋ ๋ฐฉ์ ๋ชจ๋ ๊ฐ๋ฅํ ๋ฐฉ์์ด๊ณ , ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ์ ํํ ์ด๋ค ๊ฒ์ด ์ ๋ต์ด๋ค!๋ผ๋ ๊ฒ์ ๋ด๋ฆฌ๊ธฐ ํ๋ ๋ฌธ์ ๊ฐ์ต๋๋ค. (์๋ ๊ฐ๋ฐ์ ๋ช
ํํ ์ ํด์ง ์ ๋ต์ด ์ ์กด์ฌํ์ง ์๊ธฐ๋ ํ์ฃ ..)
๊ฐ์ธ์ ์ผ๋ก๋ ์ฑ
์์ ์์ญ์ ์กฐ๊ธ ํ๋ฆด ์๋ ์์ด๋ ํ
์คํธ์๋ ์ ํฉํ ์ํฐํฐ๋ฅผ ๋ฐํํ๋ ๋ฐฉ๋ฒ์ด ๋ ๋ง์์ ๋๋๋ฐ, ์ด๋ฌํ ๋ ๋ฐฉ์์ ์ฐจ์ด์ ์ ๊ทผ๊ฑฐ๋ก ํ์ ๋ถ๋ค๊ณผ ๋
ผ์ํด ๊ฐ๋ฉฐ ์ค์ ํ๋ก์ ํธ์์๋ ์ด๋ค ๋ฐฉ์์ผ๋ก ํ ์ง ๊ฒฐ์ ํด์ผ ํ ๊ฒ ๊ฐ์ต๋๋ค.
์๋น์ค์์์ ๋ฐํ ๋ฐฉ์ ๋ํ ๋
ผ์๊ฐ ํ์ํ ๋ถ๋ถ์
๋๋ค. ์ ์ฅ๋ ํ API๋ก ์๋ตํ ๋ id๋ง ์์ด๋ ๊ด์ฐฎ์์ง, ์๋๋ฉด ๋ถ๊ฐ์ ์ธ ์์ฑ (๊ฒ์๊ธ์ ๊ฒฝ์ฐ ์ ๋ชฉ, ๊ธ ๋ฑ)์ด ๋ ํ์ํ์ง์ ๋ฐ๋ผ ๋ฌ๋ผ์ง ๊ฒ ๊ฐ์ต๋๋ค.
'๐ค ๊ณ ๋ฏผ์ ' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
getter์ setter๋ ์ด๋์ ๋๋ ๊ฒ ์ข์๊น? (1) | 2023.11.15 |
---|