post 처리를 한다 = post는 CRUD 중 Create
그리고 Mapping은 @GetMapping과 동일하게 URL 매핑을 담당하지만
POST 요청을 처리하는 경우에 사용
그러고보니 GET은 읽는다인가????? 오 맞네

GET /api/v1/posts : 주세요 글들을
GET /api/v1/posts/3 : 3번 글 주세요
DELETE /api/v1/posts/3 : 3번 글 삭제해주세요
@PostMapping(value ="/create/{id}")
이렇게 안하고 value 생략 가능함
@PostMapping("/create/{id}")
^^bbbb
@RequsetParam << 저번에 사용했던 것 중 하나
그냥 콕 찝어서 이거다 라고 할 때 사용했던 것 같음
내부처리 (눈에 보이지 않는 부분)
UI (눈에 보이는 부분)
백엔드 개발자가 스프링부트로 내부처리와 UI를 모두 구현 (둘 다 하기)
백엔드 개발자는 스프링부트로 내부처리만 구현하고 UI는 프론트엔드 개발자가 구현
REST API 구현 이라고 한다.요건 스트링부트 입장에선 편지를 받은 것과 같음
Request : 클라이언트가 서버에게 보내는 요청 (편지)
Response : 서버(스프링부트)가 클라이언트에게 보내는 응답 (편지)
Request 헤더 : 요청에 대한 메타데이터(부가정보)를 담는 곳
예시 )
Content-Type:application/json
Request 바디 : 요청의 실제 내용을 담는 곳
예시 )
{"title" : "제목", "content" : "내용"}
프론트엔드 개발자가 싫어한다
원래 숫자가 10, 20이었는데 이걸 내가 임의로 30, 40으로 수정해버리면
바뀐 API 양식으로 소스코드를 수정해야 한다.
나같아도 싫을듯
그래서 엔티티 객체를 REST API 를 통해 노출하지 않고
따로 DTO 클래스를 만들어 노출하는 것이 좋다.
DTO 를 사용하면 보안, 유지보수성, 성능 면에서 유리하고,
API 응답 구조를 유연하게 제어할 수 있다.
DTO 클래스 정의필요한 데이터만 담아 클라이언트에 전달하도록 설계된 클래스
보통 엔티티 클래스와 비슷한 구조를 가지지만, 엔티티와 1:1 매핑이 아닌 경우도 많다.
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class PostDto {
private Long id;
private String title;
private String content;
private LocalDateTime createdDate;
private LocalDateTime modifiedDate;
}
DTO 변환 로직을 추가하기엔티티 객체를 DTO로 변환하는 작업은 일반적으로 서비스 계층에서 수행된다.
변환하기 위해 엔티티를 DTO로 변환하는 메서드를 작성한다.
@Service
@RequiredArgsConstructor
public class PostService {
private final PostRepository postrepository;
public List<PostDto> findAllPosts() {
return postrepository.findAllByOrderByIdDesc()
.stream()
.map(this::convertToDto)
.collect(Collector.toList());
}
public PostDto findPostById(long id) {
Post post = postrepository.findById(id)
.orElseThrow(() -> new IllegalArgumentException("Post not found"));
return convertToDto(post);
}
private PostDto convertToDto(Post post) {
return new PostDto(
post.getId(),
post.getTitle(),
post.getContent(),
post.getCreatedAt(),
post.getModifiedAt()
);
}
DTO 반환하기컨트롤러는 DTO를 반환하도록 변경,
서비스 게층에서 반환된 DTO를 반환받아 클라이언트에게 전달
@RestController
@RequestMapping("/api/v1/posts")
@RequiredArgsConstructor
public class ApiV1PostController {
private final PostService postService;
@GetMapping
public List<Post> getItems() {
return postService.findAllPosts();
}
@GetMapping("/{id}")
public Post getItem(
@PathVariable long id
) {
return postService.findPostById(id);
}
클라이언트가 데이터를 전달할 때도 DTO를 사용한다.
이렇게 하면 API 인터페이스와 내부 도메인 간의 명확한 분리가 가능하다.
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class PostCreateRequsetDto {
@NotBlank
@Length(min = 2)
private String title;
@NotBlank
@Length(min = 2)
private String content;
@PostMapping
public RsData createItem(@RequestBody @Valid PostCreateRequestDto requestDto) {
Post post = postService.createPost(
requestDto.getTitle(),
requestDto.getContent()
);
return new RsData("200-1", "%d번 글이 작성되었습니다.".formatted(post_getId()));
}
ModelMapper 또는 MapStruct 사용
수동으로 변환 메서드를 작성하는 대신, DTO와 엔티티 간의 변환을 자동화할 수 있다.
ModelMapper@Bean
public ModelMapper modelMapper() {
return new ModelMapper();
}
// 변환
PostDto postDto = modelMapper.map(post, PostDto.class);
MapStruct@Mapper
public interface PostMapper {
PostMapper INSTANCE = Mappers.getMapper(PostMapper.class);
PostDto toDto(Post post);
Post toEntity(PostDto postDto);
}
이렇게 하면 뭐가 좋은가
보안 : 엔티티에 민감한 정보(비밀번호 등)가 포함되어 있어도 DTO에 포함되지 않음으로써 노출을 방지
API 구조 유연성 : 클라이언트 요구에 맞게 DTO를 설계 가능
유지보수성 : 엔티티 변경이 API에 영향을 미치지 않음
데이터 최적화 : 필요한 데이터만 클라이언트로 전송하여 성능을 향상
Local Area Network (LAN)
MAN(Metropolitan Area Network), WAN(Wide Area Network) 등이 있다
그러면 학교에 있던 컴퓨터들도 다 랜으로 묶여있었다 라고 생각하면 되겠다
인터넷 (Internet) 은 컴퓨터 네트워크들을 서로 연결 지여주는 범지구적 네트워크
(= Inter-Network = 컴퓨터 네트워크들의 네트워크)
인터넷 안에 컴퓨터 네트워크가 있는 거??
이렇게 구축이 된 인터넷이라는 거대한 네트워크 위에서
우리가 사용하는 다양한 서비스들이 동작한다.
이메일도 보내고 웹도 사용하고 등등
인터넷이라는 네트워크 인프라가 갖춰졌기 때문에,
이를 활용한 서비스들이 동작할 수 있는 것
웹이 없어도 인터넷은 존재하지만 인터넷이 없으면 웹은 존재하지 않는다