Layered Architecture ์ค์ต
0. ํ๋ก์ ํธ ์์ฑ
๋๋ณด๊ธฐ
ํ๋ก์ ํธ ์์ฑ
- ๋ฉ๋ชจ์ฅ ํ๋ก์ ํธ๋ฅผ ์์ฑํ ๋์ ๋์ผํ๊ฒ ํ๋ก์ ํธ๋ฅผ ์์ฑํ๋ค.
- ๊ผญ ํ์ธํด์ผ ํ ์ฌํญ
- Name: layered
- Language: Java
- Build system: Gradle - Groovy
- JDK: 17
- ํ๋ก์ ํธ ๊ฒฝ๋ก(Location)๋ ์ด์ ์ ๋ง๋ค์๋ workspace ํด๋๋ก ์ง์
์ด๊ธฐ ํด๋์ค ์์ฑ
Memo
@Getter
@AllArgsConstructor
public class Memo {
private Long id;
private String title;
private String contents;
public void update(MemoRequestDto dto) {
this.title = dto.getTitle();
this.contents = dto.getContents();
}
public void updateTitle(MemoRequestDto dto) {
this.title = dto.getTitle();
}
}
MemoRequestDto
@Getter
public class MemoRequestDto {
private String title;
private String contents;
}
MemoResponseDto
@Getter
public class MemoResponseDto {
private Long id;
private String title;
private String contents;
public MemoResponseDto(Memo memo) {
this.id = memo.getId();
this.title = memo.getTitle();
this.contents = memo.getContents();
}
}
MemoController
@RestController
@RequestMapping("/memos")
public class MemoController {
private final Map<Long, Memo> memoList = new HashMap<>();
@PostMapping
public ResponseEntity<MemoResponseDto> createMemo(@RequestBody MemoRequestDto dto) {
// ์๋ณ์๊ฐ 1์ฉ ์ฆ๊ฐ ํ๋๋ก ๋ง๋ฆ
Long memoId = memoList.isEmpty() ? 1 : Collections.max(memoList.keySet()) + 1;
// ์์ฒญ๋ฐ์ ๋ฐ์ดํฐ๋ก Memo ๊ฐ์ฒด ์์ฑ
Memo memo = new Memo(memoId, dto.getTitle(), dto.getContents());
// Inmemory DB์ Memo ๋ฉ๋ชจ
memoList.put(memoId, memo);
return new ResponseEntity<>(new MemoResponseDto(memo), HttpStatus.CREATED);
}
}
1. Controller ๋ถ๋ฆฌํ๊ธฐ
๋๋ณด๊ธฐ
์ฑ ์ ๋ถ๋ฆฌ
- Controller์ ์ญํ
- ํด๋ผ์ด์ธํธ์ ์์ฒญ์ ๋ฐ๋ ์ญํ ์ ์ํํ๋ค.
- ์์ฒญ์ ๋ํ ์ฒ๋ฆฌ๋ฅผ Service Layer์ ์ ๋ฌํ๋ค.
- Service์์ ์ฒ๋ฆฌ ์๋ฃ๋ ๊ฒฐ๊ณผ๋ฅผ ํด๋ผ์ด์ธํธ์ ์๋ตํ๋ค.
/*
Controller์ ์ญํ
- ํด๋ผ์ด์ธํธ์ ์์ฒญ์ ๋ฐ๋ ์ญํ ์ ์ํํ๋ค.
- ์์ฒญ์ ๋ํ ์ฒ๋ฆฌ๋ฅผ Service Layer์ ์ ๋ฌํ๋ค.
- Service์์ ์ฒ๋ฆฌ ์๋ฃ๋ ๊ฒฐ๊ณผ๋ฅผ ํด๋ผ์ด์ธํธ์ ์๋ตํ๋ค.
*/
@RestController
@RequestMapping("/memos")
public class MemoController {
// Controller์ ๋ฐ์ดํฐ๋ฒ ์ด์ค (Repository) - ์๋ฃ๊ตฌ์กฐ
private final Map<Long, Memo> memoList = new HashMap<>();
/*
1. ์์ฒญ (Controller)
ํ๋ผ๋ฏธํฐ ๋ฐ์ธ๋ฉ ์ค์ด๋ค.
@RequestBody๋ฅผ ์ฌ์ฉํด์ HttpMessageConverter๊ฐ ๋์ํด์ JSON ๋ฐ์ดํฐ๊ฐ dto ํํ๋ก ๋ณํ๋๋ค.
*/
@PostMapping
public ResponseEntity<MemoResponseDto> createMemo(@RequestBody MemoRequestDto dto) {
/*
2. ๋น์ง๋์ค ๋ก์ง
MemoId ์๋ณ์ ๊ณ์ฐ (Repository)
์๋ณ์๊ฐ 1์ฉ ์ฆ๊ฐ ํ๋๋ก ๋ง๋ฆ
์ด๊ฒ์ ์๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ญํ ์ด๋ค. -> Repository๋ก ์ฎ๊ธธ ์์
*/
Long memoId = memoList.isEmpty() ? 1 : Collections.max(memoList.keySet()) + 1;
/*
์์ฒญ๋ฐ์ ๋ฐ์ดํฐ๋ก Memo ๊ฐ์ฒด ์์ฑ (Service)
์์ฑํ Repository๋ฅผ ํธ์ถํด์ ์ ์ฅํ๋๋ก ๋ง๋๋ ๊ฒ์ Service Layer์ ์์ญ์ด๋ค. -> Service Layer๋ก ์ฎ๊ธธ ์์
*/
Memo memo = new Memo(memoId, dto.getTitle(), dto.getContents());
/*
3. ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ํธ์์ฉ
Inmemory DB์ Memo ์ ์ฅ (Repository)
๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ค์ ๋ก ์ํธ์์ฉํ๋ ๋ถ๋ถ -> Repository๋ก ์ฎ๊ธธ ์์
*/
memoList.put(memoId, memo);
// 4. ์๋ต (Controller)
return new ResponseEntity<>(new MemoResponseDto(memo), HttpStatus.CREATED);
}
}
- ์์ฒญ, ์๋ต์ ์ ์ธํ ๋ชจ๋๋ฅผ Controller์์ ๋ถ๋ฆฌํด์ผ ํ๋ค.
Service Layer ๋ถ๋ฆฌ
- ๋น์ฆ๋์ค ๋ก์ง
public interface MemoService {
}
/**
* Annotation @Service๋ @Component์ ๊ฐ๋ค, Spring Bean์ผ๋ก ๋ฑ๋กํ๋ค๋ ๋ป.
* Spring Bean์ผ๋ก ๋ฑ๋ก๋๋ฉด ๋ค๋ฅธ ํด๋์ค์์ ์ฃผ์
ํ์ฌ ์ฌ์ฉํ ์ ์๋ค.
* ๋ช
์์ ์ผ๋ก Service Layer ๋ผ๋๊ฒ์ ๋ํ๋ธ๋ค.
* ๋น์ง๋์ค ๋ก์ง์ ์ํํ๋ค.
*/
@Service
public class MemoServiceImpl implements MemoService {
}
Repository Layer ๋ถ๋ฆฌ
- ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ํธ์์ฉ
public interface MemoRepository {
}
/**
* Annotation @Repository๋ @Component์ ๊ฐ๋ค, Spring Bean์ผ๋ก ๋ฑ๋กํ๋ค๋ ๋ป.
* Spring Bean์ผ๋ก ๋ฑ๋ก๋๋ฉด ๋ค๋ฅธ ํด๋์ค์์ ์ฃผ์
ํ์ฌ ์ฌ์ฉํ ์ ์๋ค.
* ๋ช
์์ ์ผ๋ก Repository Layer ๋ผ๋๊ฒ์ ๋ํ๋ธ๋ค.
* DB์ ์ํธ์์ฉํ์ฌ ๋ฐ์ดํฐ๋ฅผ CRUDํ๋ ์์
์ ์ํํ๋ค.
*/
@Repository
public class MemoRepositoryImpl implements MemoRepository {
private final Map<Long, Memo> memoList = new HashMap<>();
}
2. ๋ฉ๋ชจ ์์ฑ API ๋ฆฌํฉํ ๋ง
๋๋ณด๊ธฐ
Controller
- ์์ฒญ, Srvice Layer ํธ์ถ, ์๋ต
@RestController // @Controller + @ResponseBody
@RequestMapping("/memos") // Prefix
public class MemoController {
// ์ฃผ์
๋ ์์กด์ฑ์ ๋ณ๊ฒฝํ ์ ์์ด ๊ฐ์ฒด์ ์ํ๋ฅผ ์์ ํ๊ฒ ์ ์งํ ์ ์๋ค.
private final MemoService memoService;
/**
* ์์ฑ์ ์ฃผ์
* ํด๋์ค๊ฐ ํ์๋ก ํ๋ ์์กด์ฑ์ ์์ฑ์๋ฅผ ํตํด ์ ๋ฌํ๋ ๋ฐฉ์
* @param memoService @Service๋ก ๋ฑ๋ก๋ MemoService ๊ตฌํ์ฒด์ธ Impl
*/
public MemoController(MemoService memoService) {
this.memoService = memoService;
}
/**
* ๋ฉ๋ชจ ์์ฑ API
* @param : {@link MemoRequestDto} ๋ฉ๋ชจ ์์ฑ ์์ฒญ ๊ฐ์ฒด
* @return : {@link ResponseEntity<MemoResponseDto>} JSON ์๋ต
*/
@PostMapping // ์์ฒญ
public ResponseEntity<MemoResponseDto> createMemo(@RequestBody MemoRequestDto requestDto) {
// ServiceLayer ํธ์ถ ๋ฐ ์๋ต
return new ResponseEntity<>(memoService.saveMemo(requestDto), HttpStatus.CREATED);
}
}
Memo
@Getter
@AllArgsConstructor
public class Memo {
@Setter
private Long id;
private String title;
private String contents;
public Memo(String title, String contents) {
this.title = title;
this.contents = contents;
}
public void update(String title, String contents) {
this.title = title;
this.contents = contents;
}
public void updateTitle(String title) {
this.title = title;
}
}
Service
- ๋น์ฆ๋์ค ๋ก์ง
public interface MemoService {
MemoResponseDto saveMemo(MemoRequestDto requestDto);
}
/**
* Annotation @Service๋ @Component์ ๊ฐ๋ค, Spring Bean์ผ๋ก ๋ฑ๋กํ๋ค๋ ๋ป.
* Spring Bean์ผ๋ก ๋ฑ๋ก๋๋ฉด ๋ค๋ฅธ ํด๋์ค์์ ์ฃผ์
ํ์ฌ ์ฌ์ฉํ ์ ์๋ค.
* ๋ช
์์ ์ผ๋ก Service Layer ๋ผ๋๊ฒ์ ๋ํ๋ธ๋ค.
* ๋น์ง๋์ค ๋ก์ง์ ์ํํ๋ค.
*/
@Service
public class MemoServiceImpl implements MemoService {
private final MemoRepository memoRepository;
public MemoServiceImpl(MemoRepository memoRepository) {
this.memoRepository = memoRepository;
}
@Override
public MemoResponseDto saveMemo(MemoRequestDto requestDto) {
// ์์ฒญ๋ฐ์ ๋ฐ์ดํฐ๋ก Memo ๊ฐ์ฒด ์์ฑ ID ์์
Memo memo = new Memo(requestDto.getTitle(), requestDto.getContents());
// Inmemory DB์ Memo ์ ์ฅ
Memo savedMemo = memoRepository.saveMemo(memo);
return new MemoResponseDto(savedMemo);
}
}
Repository
- ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ํธ์์ฉ
public interface MemoRepository {
Memo saveMemo(Memo memo);
}
@Repository
public class MemoRepositoryImpl implements MemoRepository {
private final Map<Long, Memo> memoList = new HashMap<>();
@Override
public Memo saveMemo(Memo memo) {
// memo ์๋ณ์ ์๋ ์์ฑ
Long memoId = memoList.isEmpty() ? 1 : Collections.max(memoList.keySet()) + 1;
memo.setId(memoId);
memoList.put(memoId, memo);
return memo;
}
}
3. ๋ฉ๋ชจ ๋ชฉ๋ก ์กฐํ API ๋ฆฌํฉํ ๋ง
๋๋ณด๊ธฐ
Controller
@RestController // @Controller + @ResponseBody
@RequestMapping("/memos") // Prefix
public class MemoController {
// ์ฃผ์
๋ ์์กด์ฑ์ ๋ณ๊ฒฝํ ์ ์์ด ๊ฐ์ฒด์ ์ํ๋ฅผ ์์ ํ๊ฒ ์ ์งํ ์ ์๋ค.
private final MemoService memoService;
/**
* ์์ฑ์ ์ฃผ์
* ํด๋์ค๊ฐ ํ์๋ก ํ๋ ์์กด์ฑ์ ์์ฑ์๋ฅผ ํตํด ์ ๋ฌํ๋ ๋ฐฉ์
* @param memoService @Service๋ก ๋ฑ๋ก๋ MemoService ๊ตฌํ์ฒด์ธ Impl
*/
public MemoController(MemoService memoService) {
this.memoService = memoService;
}
/**
* ๋ฉ๋ชจ ์ ์ฒด ์กฐํ API
* @return : {@link List<MemoResponseDto>} JSON ์๋ต
*/
@GetMapping
public List<MemoResponseDto> findAllMemos() {
return memoService.findAllMemos();
}
}
Service
public interface MemoService {
List<MemoResponseDto> findAllMemos();
}
/**
* Annotation @Service๋ @Component์ ๊ฐ๋ค, Spring Bean์ผ๋ก ๋ฑ๋กํ๋ค๋ ๋ป.
* Spring Bean์ผ๋ก ๋ฑ๋ก๋๋ฉด ๋ค๋ฅธ ํด๋์ค์์ ์ฃผ์
ํ์ฌ ์ฌ์ฉํ ์ ์๋ค.
* ๋ช
์์ ์ผ๋ก Service Layer ๋ผ๋๊ฒ์ ๋ํ๋ธ๋ค.
* ๋น์ง๋์ค ๋ก์ง์ ์ํํ๋ค.
*/
@Service
public class MemoServiceImpl implements MemoService {
private final MemoRepository memoRepository;
public MemoServiceImpl(MemoRepository memoRepository) {
this.memoRepository = memoRepository;
}
@Override
public List<MemoResponseDto> findAllMemos() {
// ์ ์ฒด ์กฐํ
List<MemoResponseDto> allMemos = memoRepository.findAllMemos();
return allMemos;
}
}
Repository
public interface MemoRepository {
List<MemoResponseDto> findAllMemos();
}
@Repository
public class MemoRepositoryImpl implements MemoRepository {
private final Map<Long, Memo> memoList = new HashMap<>();
@Override
public Map<Long, Memo> findAllMemos() {
// init List
List<MemoResponseDto> allMemos = new ArrayList<>();
// HashMap<Memo> -> List<MemoResponseDto>
for (Memo memo : memoList.values()) {
MemoResponseDto responseDto = new MemoResponseDto(memo);
allMemos.add(responseDto);
}
return allMemos;
}
}
4. ๋ฉ๋ชจ ๋จ๊ฑด ์กฐํ API ๋ฆฌํฉํ ๋ง
๋๋ณด๊ธฐ
Controller
@RestController // @Controller + @ResponseBody
@RequestMapping("/memos") // Prefix
public class MemoController {
// ์ฃผ์
๋ ์์กด์ฑ์ ๋ณ๊ฒฝํ ์ ์์ด ๊ฐ์ฒด์ ์ํ๋ฅผ ์์ ํ๊ฒ ์ ์งํ ์ ์๋ค.
private final MemoService memoService;
/**
* ์์ฑ์ ์ฃผ์
* ํด๋์ค๊ฐ ํ์๋ก ํ๋ ์์กด์ฑ์ ์์ฑ์๋ฅผ ํตํด ์ ๋ฌํ๋ ๋ฐฉ์
* @param memoService @Service๋ก ๋ฑ๋ก๋ MemoService ๊ตฌํ์ฒด์ธ Impl
*/
public MemoController(MemoService memoService) {
this.memoService = memoService;
}
/**
* ๋ฉ๋ชจ ๋จ๊ฑด ์กฐํ API
* @param id ์๋ณ์
* @return : {@link ResponseEntity<MemoResponseDto>} JSON ์๋ต
*/
@GetMapping("/{id}")
public ResponseEntity<MemoResponseDto> findMemoById(@PathVariable Long id) {
return new ResponseEntity<>(memoService.findMemoById(id), HttpStatus.OK);
}
}
Service
public interface MemoService {
MemoResponseDto findMemoById(Long id);
}
/**
* Annotation @Service๋ @Component์ ๊ฐ๋ค, Spring Bean์ผ๋ก ๋ฑ๋กํ๋ค๋ ๋ป.
* Spring Bean์ผ๋ก ๋ฑ๋ก๋๋ฉด ๋ค๋ฅธ ํด๋์ค์์ ์ฃผ์
ํ์ฌ ์ฌ์ฉํ ์ ์๋ค.
* ๋ช
์์ ์ผ๋ก Service Layer ๋ผ๋๊ฒ์ ๋ํ๋ธ๋ค.
* ๋น์ง๋์ค ๋ก์ง์ ์ํํ๋ค.
*/
@Service
public class MemoServiceImpl implements MemoService {
private final MemoRepository memoRepository;
public MemoServiceImpl(MemoRepository memoRepository) {
this.memoRepository = memoRepository;
}
@Override
public MemoResponseDto findMemoById(Long id) {
// ์๋ณ์์ Memo๊ฐ ์๋ค๋ฉด?
Memo memo = memoRepository.findMemoById(id);
// ์๋ ์ฝ๋ ์ฌ์ฉ ๋ถ๊ฐ.
// if (memo == null) {
// return new ResponseEntity<>(HttpStatus.NOT_FOUND);
// }
return new MemoResponseDto(memo);
}
}
Repository
public interface MemoRepository {
Memo findMemoById(Long id);
}
@Repository
public class MemoRepositoryImpl implements MemoRepository {
private final Map<Long, Memo> memoList = new HashMap<>();
@Override
public Memo findMemoById(Long id) {
return memoList.get(id);
}
}
์์ธ์ฒ๋ฆฌ
- Layer ๊ฐ ๋ฐ์ดํฐ ์ ๋ฌ์ DTO๋ก ์ด๋ฃจ์ด์ง๋ค.
- ์ ์ ํ ์์ธ์ฒ๋ฆฌ๊ฐ ํ์ํ๋ค.
/**
* Annotation @Service๋ @Component์ ๊ฐ๋ค, Spring Bean์ผ๋ก ๋ฑ๋กํ๋ค๋ ๋ป.
* Spring Bean์ผ๋ก ๋ฑ๋ก๋๋ฉด ๋ค๋ฅธ ํด๋์ค์์ ์ฃผ์
ํ์ฌ ์ฌ์ฉํ ์ ์๋ค.
* ๋ช
์์ ์ผ๋ก Service Layer ๋ผ๋๊ฒ์ ๋ํ๋ธ๋ค.
* ๋น์ง๋์ค ๋ก์ง์ ์ํํ๋ค.
*/
@Service
public class MemoServiceImpl implements MemoService {
private final MemoRepository memoRepository;
public MemoServiceImpl(MemoRepository memoRepository) {
this.memoRepository = memoRepository;
}
@Override
public MemoResponseDto findMemoById(Long id) {
// ์๋ณ์์ Memo๊ฐ ์๋ค๋ฉด?
Memo memo = memoRepository.findMemoById(id);
// NPE ๋ฐฉ์ง
if (memo == null) {
throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Does not exist id = " + id);
}
return new MemoResponseDto(memo);
}
}
5. ๋ฉ๋ชจ ์ ์ฒด ์์ API ๋ฆฌํฉํ ๋ง
๋๋ณด๊ธฐ
Controller
@RestController // @Controller + @ResponseBody
@RequestMapping("/memos") // Prefix
public class MemoController {
// ์ฃผ์
๋ ์์กด์ฑ์ ๋ณ๊ฒฝํ ์ ์์ด ๊ฐ์ฒด์ ์ํ๋ฅผ ์์ ํ๊ฒ ์ ์งํ ์ ์๋ค.
private final MemoService memoService;
/**
* ์์ฑ์ ์ฃผ์
* ํด๋์ค๊ฐ ํ์๋ก ํ๋ ์์กด์ฑ์ ์์ฑ์๋ฅผ ํตํด ์ ๋ฌํ๋ ๋ฐฉ์
* @param memoService @Service๋ก ๋ฑ๋ก๋ MemoService ๊ตฌํ์ฒด์ธ Impl
*/
public MemoController(MemoService memoService) {
this.memoService = memoService;
}
/**
* ๋ฉ๋ชจ ์ ์ฒด ์์ API
* @param id ์๋ณ์
* @param : {@link MemoRequestDto} ๋ฉ๋ชจ ์์ ์์ฒญ ๊ฐ์ฒด
* @return : {@link ResponseEntity<MemoResponseDto>} JSON ์๋ต
* @exception ResponseStatusException ์์ฒญ ํ์๊ฐ์ด ์๋ ๊ฒฝ์ฐ 400 Bad Request, ์๋ณ์๋ก ์กฐํ๋ Memo๊ฐ ์๋ ๊ฒฝ์ฐ 404 Not Found
*/
@PutMapping("/{id}")
public ResponseEntity<MemoResponseDto> updateMemo(
@PathVariable Long id,
@RequestBody MemoRequestDto requestDto
) {
return new ResponseEntity<>(memoService.updateMemo(id, requestDto.getTitle(), requestDto.getContents()), HttpStatus.OK);
}
}
Service
public interface MemoService {
MemoResponseDto updateMemo(Long id, String title, String contents);
}
/**
* Annotation @Service๋ @Component์ ๊ฐ๋ค, Spring Bean์ผ๋ก ๋ฑ๋กํ๋ค๋ ๋ป.
* Spring Bean์ผ๋ก ๋ฑ๋ก๋๋ฉด ๋ค๋ฅธ ํด๋์ค์์ ์ฃผ์
ํ์ฌ ์ฌ์ฉํ ์ ์๋ค.
* ๋ช
์์ ์ผ๋ก Service Layer ๋ผ๋๊ฒ์ ๋ํ๋ธ๋ค.
* ๋น์ง๋์ค ๋ก์ง์ ์ํํ๋ค.
*/
@Service
public class MemoServiceImpl implements MemoService {
private final MemoRepository memoRepository;
public MemoServiceImpl(MemoRepository memoRepository) {
this.memoRepository = memoRepository;
}
@Override
public MemoResponseDto updateMemo(Long id, String title, String contents) {
// memo ์กฐํ
Memo memo = memoRepository.findMemoById(id);
// NPE ๋ฐฉ์ง
if (memo == null) {
throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Does not exist id = " + id);
}
// ํ์๊ฐ ๊ฒ์ฆ
if (title == null || contents == null) {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "The title and content are required values.");
}
// memo ์์
memo.update(title, contents);
return new MemoResponseDto(memo);
}
}
@Getter
@AllArgsConstructor
public class Memo {
private Long id;
private String title;
private String contents;
public void update(String title, String contents) {
this.title = title;
this.contents = contents;
}
public void updateTitle(MemoRequestDto dto) {
this.title = dto.getTitle();
}
}
Repository
- ๋ฉ๋ชจ๋ฆฌ ์(memoList)์ ์กด์ฌํ๋ Memo๋ฅผ ์ง์ ์์ ํ๊ธฐ ๋๋ฌธ์, ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ ๊ทผ์ด ํ์ ์๋ค.
6. ๋ฉ๋ชจ ์ ๋ชฉ ์์ API ๋ฆฌํฉํ ๋ง
๋๋ณด๊ธฐ
Controller
@RestController // @Controller + @ResponseBody
@RequestMapping("/memos") // Prefix
public class MemoController {
// ์ฃผ์
๋ ์์กด์ฑ์ ๋ณ๊ฒฝํ ์ ์์ด ๊ฐ์ฒด์ ์ํ๋ฅผ ์์ ํ๊ฒ ์ ์งํ ์ ์๋ค.
private final MemoService memoService;
/**
* ์์ฑ์ ์ฃผ์
* ํด๋์ค๊ฐ ํ์๋ก ํ๋ ์์กด์ฑ์ ์์ฑ์๋ฅผ ํตํด ์ ๋ฌํ๋ ๋ฐฉ์
* @param memoService @Service๋ก ๋ฑ๋ก๋ MemoService ๊ตฌํ์ฒด์ธ Impl
*/
public MemoController(MemoService memoService) {
this.memoService = memoService;
}
/**
* ๋ฉ๋ชจ ์ ๋ชฉ ์์ API
* @param id ์๋ณ์
* @param : {@link MemoRequestDto} ๋ฉ๋ชจ ์์ ์์ฒญ ๊ฐ์ฒด
* @return : {@link ResponseEntity<MemoResponseDto>} JSON ์๋ต
* @exception ResponseStatusException ์์ฒญ ํ์๊ฐ์ด ์๋ ๊ฒฝ์ฐ 400 Bad Request, ์๋ณ์๋ก ์กฐํ๋ Memo๊ฐ ์๋ ๊ฒฝ์ฐ 404 Not Found
*/
@PatchMapping("/{id}")
public ResponseEntity<MemoResponseDto> updateTitle(
@PathVariable Long id,
@RequestBody MemoRequestDto requestDto
) {
return new ResponseEntity<>(memoService.updateTitle(id, requestDto.getTitle(), requestDto.getContents()), HttpStatus.OK);
}
}
Service
public interface MemoService {
MemoResponseDto updateTitle(Long id, String title, String contents);
}
/**
* Annotation @Service๋ @Component์ ๊ฐ๋ค, Spring Bean์ผ๋ก ๋ฑ๋กํ๋ค๋ ๋ป.
* Spring Bean์ผ๋ก ๋ฑ๋ก๋๋ฉด ๋ค๋ฅธ ํด๋์ค์์ ์ฃผ์
ํ์ฌ ์ฌ์ฉํ ์ ์๋ค.
* ๋ช
์์ ์ผ๋ก Service Layer ๋ผ๋๊ฒ์ ๋ํ๋ธ๋ค.
* ๋น์ง๋์ค ๋ก์ง์ ์ํํ๋ค.
*/
@Service
public class MemoServiceImpl implements MemoService {
private final MemoRepository memoRepository;
public MemoServiceImpl(MemoRepository memoRepository) {
this.memoRepository = memoRepository;
}
@Override
public MemoResponseDto updateTitle(Long id, String title, String contents) {
// memo ์กฐํ
Memo memo = memoRepository.findMemoById(id);
// NPE ๋ฐฉ์ง
if (memo == null) {
throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Does not exist id = " + id);
}
// ํ์๊ฐ ๊ฒ์ฆ
if (title == null || contents != null) {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "The title and content are required values.");
}
memo.updateTitle(title);
return new MemoResponseDto(memo);
}
}
Repository
- ๋ฉ๋ชจ๋ฆฌ ์(memoList)์ ์กด์ฌํ๋ Memo๋ฅผ ์ง์ ์์ ํ๊ธฐ ๋๋ฌธ์, ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ ๊ทผ์ด ํ์ ์๋ค.
7. ๋ฉ๋ชจ ์ญ์ API ๋ฆฌํฉํ ๋ง
๋๋ณด๊ธฐ
Controller
@RestController // @Controller + @ResponseBody
@RequestMapping("/memos") // Prefix
public class MemoController {
// ์ฃผ์
๋ ์์กด์ฑ์ ๋ณ๊ฒฝํ ์ ์์ด ๊ฐ์ฒด์ ์ํ๋ฅผ ์์ ํ๊ฒ ์ ์งํ ์ ์๋ค.
private final MemoService memoService;
/**
* ์์ฑ์ ์ฃผ์
* ํด๋์ค๊ฐ ํ์๋ก ํ๋ ์์กด์ฑ์ ์์ฑ์๋ฅผ ํตํด ์ ๋ฌํ๋ ๋ฐฉ์
* @param memoService @Service๋ก ๋ฑ๋ก๋ MemoService ๊ตฌํ์ฒด์ธ Impl
*/
public MemoController(MemoService memoService) {
this.memoService = memoService;
}
/**
* ๋ฉ๋ชจ ์ญ์ API
* @param id ์๋ณ์
* @return {@link ResponseEntity<Void>} ์ฑ๊ณต์ Data ์์ด 200OK ์ํ์ฝ๋๋ง ์๋ต.
* @exception ResponseStatusException ์๋ณ์๋ก ์กฐํ๋ Memo๊ฐ ์๋ ๊ฒฝ์ฐ 404 Not Found
*/
@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteMemo(@PathVariable Long id) {
memoService.deleteMemo(id);
// ์ฑ๊ณตํ ๊ฒฝ์ฐ
return new ResponseEntity<>(HttpStatus.OK);
}
}
Service
public interface MemoService {
void deleteMemo(Long id);
}
/**
* Annotation @Service๋ @Component์ ๊ฐ๋ค, Spring Bean์ผ๋ก ๋ฑ๋กํ๋ค๋ ๋ป.
* Spring Bean์ผ๋ก ๋ฑ๋ก๋๋ฉด ๋ค๋ฅธ ํด๋์ค์์ ์ฃผ์
ํ์ฌ ์ฌ์ฉํ ์ ์๋ค.
* ๋ช
์์ ์ผ๋ก Service Layer ๋ผ๋๊ฒ์ ๋ํ๋ธ๋ค.
* ๋น์ง๋์ค ๋ก์ง์ ์ํํ๋ค.
*/
@Service
public class MemoServiceImpl implements MemoService {
private final MemoRepository memoRepository;
public MemoServiceImpl(MemoRepository memoRepository) {
this.memoRepository = memoRepository;
}
@Override
public void deleteMemo(Long id) {
// memo ์กฐํ
Memo memo = memoRepository.findMemoById(id);
// NPE ๋ฐฉ์ง
if (memo == null) {
throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Does not exist id = " + id);
}
memoRepository.deleteMemo(id);
}
}
Repository
public interface MemoRepository {
void deleteMemo(Long id);
}
@Repository
public class MemoRepositoryImpl implements MemoRepository {
private final Map<Long, Memo> memoList = new HashMap<>();
@Override
public void deleteMemo(Long id) {
memoList.remove(id);
}
}
ํด๊ฒฐํ ๋ฌธ์ ์
- Controller์ ์ฑ ์์ Layer ๋ณ๋ก ๋ถ๋ฆฌํ์๋ค.
๋ฌธ์ ์
- ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์๊ตฌ์ ์ผ๋ก ๋ฐ์ดํฐ๊ฐ ์ ์ฅ๋์ง ์๋๋ค. (Database ์ ๊ทผ ๊ธฐ์ )
- ์์ธ ๋ฐ์ ์ ๊ณตํต์ ์ผ๋ก ์ฒ๋ฆฌ๊ฐ ๋ถ๊ฐ๋ฅํ๋ค.
- ๊ฐ๊ฐ์ ๋ชจ๋ ์์ธ๋ฅผ try-catchํ์ฌ ์ฒ๋ฆฌํด์ผ ํ๋ค.
- RequestDto, ResponseDto๋ฅผ ๊ณต์ ํ์ฌ null๊ฐ์ด ๋ค์ด์ค๊ธฐ๋ ํ๋ค.
- ํ์ ์๋ ํ๋์ ์ถ๊ฐ์ ์ธ null ๊ฒ์ฌ๋ฅผ ํด์ผ ํ๋ค.
- Spring Bean, ์์ฑ์ ์ฃผ์ ๋ฑ Spring์ ๋์ ์๋ฆฌ์ ๋ํด ์ดํดํ์ง ๋ชปํ๋ค.
- ์ Interface๋ก ๋ง๋ค์ด์ ๊ตฌํํ์ฌ ์ฌ์ฉํ๋์ง ๋ชจ๋ฅธ๋ค.
'Today I Learned(TIL) > ์คํ๋ฅดํ ๋ด์ผ๋ฐฐ์์บ ํ' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
์ฃผํน๊ธฐ ์ ๋ฌธ/์๋ จ_Day 6 (1) | 2024.12.04 |
---|---|
์ฃผํน๊ธฐ ์ ๋ฌธ/์๋ จ_๋ฐ์ดํฐ๋ฒ ์ด์ค ์ ๊ทผ ๊ธฐ์ ์ ์ฉ (0) | 2024.12.04 |
์ฃผํน๊ธฐ ์ ๋ฌธ/์๋ จ_Day 5 (2) | 2024.12.03 |
์ฃผํน๊ธฐ ์ ๋ฌธ/์๋ จ_Day 4 (2) | 2024.12.02 |
์ฃผํน๊ธฐ ์ ๋ฌธ/์๋ จ_Day 2 (3) | 2024.11.30 |