Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[기본과제/심화과제] 2주차 스프링을 이용해서 REST API 구현하기 #2

Open
wants to merge 38 commits into
base: main
Choose a base branch
from

Conversation

hayounSong
Copy link
Collaborator

@hayounSong hayounSong commented Apr 20, 2023

아이고 제가 브랜치를 1주차 브랜치에서 판지 다 끝나고 알아버렸어요. 1주차 커밋들은 무시해주세요 ㅎ..

2주차 심화과제 API 명세서

✍️ 메뉴 등록하기

URL METHOD
/menu POST

💪 Reuqest Body

{
	"name":"String"
	"price":"int"
}

📕 Request Headers

{
	"Content-Type":"application/json"
}

📣 Response

"name" 이 등록 완료되었습니다!

✅ 등록된 메뉴 확인하기

URL METHOD
/menu/{menuId} GET

💪 Reuqest Body

{
}

📕 Request Headers

{
	"Content-Type":"application/json"
	"menuId": "int" (PathVaribale)
}

📣 Response

{
	"name":"String"
	"price":"int"
}

⛔️ Error Response

{
    "timestamp": "2023-04-20T08:33:04.763+00:00",
    "status": 404,
    "error": "Not Found",
    "path": "/menu/{menuId}"
}

🔩 등록된 메뉴 수정하기

URL METHOD
/menu/{menuId} PUT

💪 Reuqest Body

{
	"name":"String"
	"price":"int"
	}

📕 Request Headers

{
	"Content-Type":"application/json"
	"menuId": "int" (PathVaribale)
}

📣 Response

{
	"name":"String"
	"price":"int"
}

⛔️ Error Response

{
    "timestamp": "2023-04-20T08:33:04.763+00:00",
    "status": 404,
    "error": "Not Found",
    "path": "/menu/{menuId}"
}

❌ 등록된 메뉴 삭제하기

URL METHOD
/menu?name={} DELETE

💪 Reuqest Body

{

}

📕 Request Headers

{
	"Content-Type":"application/json"
	(params) "name":"string"
}

📣 Response

"name"을 삭제헀습니다.

⛔️ Error Response

{
    "timestamp": "2023-04-20T08:33:04.763+00:00",
    "status": 404,
    "error": "Not Found",
    "path": "/menu"
}

🐕 과제 구현 명세

[기본과제]

POST라는 게시판 게시물 도메인을 가정하여서, 기본 과제 코드들을 구현했습니다!

package sopt.org.SecondSeminar.domain;

import lombok.Getter;

@Getter
public class Post {
    public Post(String title,String create_user,String content){
        this.title=title;
        this.create_user=create_user;
        this.content=content;
    }
    public void setId(long id){
        this.id=id;
    }
    private Long id;
    private String title;
    private String create_user;
    private String content;

}

위와 같이 Post 도메인을 만들어주었습니다.

    @GetMapping("/post/{postId}")
    public PostResponseDto getPost(@PathVariable final long postId){
        Post post=postList.get((int) (postId-1));
        PostResponseDto postResponseDto = PostResponseDto.newInstance(post.getTitle(),post.getCreate_user(),post.getContent());
        return postResponseDto;
    }
    @GetMapping("/post")
    public ResponseEntity getPostByTitle(@RequestParam final String title){
        for(int i=0;i<postList.size();i++){
            if(postList.get(i).getTitle().equals(title)){
                Post post=postList.get(i);
                HttpHeaders httpHeaders=new HttpHeaders();
                PostResponseDto postResponseDto=PostResponseDto.newInstance((post.getTitle()),post.getCreate_user(),post.getContent());
                return new ResponseEntity(postResponseDto,httpHeaders, HttpStatus.OK);
            }
        }

        throw new ResponseStatusException(
                HttpStatus.NOT_FOUND, "entity not found"
        );
    }

아직 서버 새싹이지만, 뭔가 그냥 dto를 리턴하는 것보다는 간단한 예외처리와 정렬화된 Response 통신을 해보고 싶어서 ResponseEnitty를 이용해서 GetMapping을 해주었습니다. 또한, 이 title 값이 ArrayList안에 없을 경우 404 에러를 발생시키는 간단한 에러처리를 해주었습니다!

근데 뭔가 아직 스프링 코드를 자바처럼 짜는게 아닌, JS처럼 짜는게 티가 나네요.. for문 대신 for:each문을 사용했다면 더 좋았을 것 같습니다!

[심화과제]

Menu라는 새로운 도메인을 만들어 과제를 진행하였습니다.

    @PostMapping("/menu")
    public String uploadMenu(@RequestBody RequestMenuDto requestMenuDto){
        menuService.RegisterMenu(requestMenuDto);
        return requestMenuDto.getName()+"을 등록했습니다!";
    }

평범한 Post 메서드 처리,

@GetMapping("/menu/{menuId}")
    public ResponseEntity getMenu(@PathVariable final int menuId){
        if(menuList.size()<menuId){
            throw new ResponseStatusException(
                    HttpStatus.NOT_FOUND, "entity not found"
            );
        }
        Menu menu=menuList.get(menuId-1);
        if(menu==null) {
            throw new ResponseStatusException(
                    HttpStatus.NOT_FOUND, "entity not found"
            );
        }
        ResponseMenuDto responseMenuDto=ResponseMenuDto.newInstance(menu.getName(),menu.getPrice());
        HttpHeaders httpHeaders=new HttpHeaders();

        return new ResponseEntity(responseMenuDto,httpHeaders,HttpStatus.OK);
    }

그리고, GET 메서드를 만들어주었는데, 여기서도 나름대로 에러 핸들링을 해보고 싶어 ResponseEntity 사용과, PathVariable로 주어진 menuId가 현재 menuList의 사이즈보다 클 경우, 404에러를 발생시켰습니다! 그리고 menu가 검색되지 않았을때도!

근데, 뭔가 에러핸들링과 index 처리가 어색한데.. 실제 데이터베이스 쓰면 나아질 것 같지만, 좀 더 공부해보겠습니다!

@PutMapping("/menu/{menuId}")
    public ResponseEntity putMenu(@PathVariable final int menuId,@RequestBody RequestMenuDto requestMenuDto){
        if(menuList.size()<menuId){
            throw new ResponseStatusException(
                    HttpStatus.NOT_FOUND, "entity not found"
            );
        }
        Menu menu=new Menu(requestMenuDto.getName(),requestMenuDto.getPrice());
        menuList.set(menuId-1,menu);
        ResponseMenuDto responseMenuDto=ResponseMenuDto.newInstance(menuList.get(menuId-1).getName(),menuList.get(menuId-1).getPrice());
        HttpHeaders httpHeaders=new HttpHeaders();
        return new ResponseEntity(responseMenuDto,httpHeaders,HttpStatus.OK);
    }

Put 메서드도 ResponseEntity와 이전과 같은 간단한 에러 핸들링을 사용했습니다.

  @DeleteMapping("/menu")
    public String deleteMenu(@RequestParam final String name){

        boolean isDeleted=false;
        Menu delMenu=null;
        for (Menu menu:menuList) {
            if(menu.getName().equals(name)) {
                isDeleted = true;
                delMenu=menu;
            }
        }
        menuList.remove(delMenu);

        if(isDeleted==false){
            throw new ResponseStatusException(
                    HttpStatus.NOT_FOUND, "entity not found"
            );
        }
        return name+"을 삭제했습니다.";
    }

메뉴 삭제 기능 역시 구현하였는데, 이름이 검색되지 않아 삭제가 되지 않았을 경우에는 마찬가지로 404 에러를 response하도록 구성해주었습니다!

🐥 이런 점이 새로웠어요 / 어려웠어요

  • 뭔가 의미 있는 과제를 하고 싶어서, 나름대로의 에러 핸들링을 해보았는데.. 데이터베이스를 안써서 그런진 몰라도 코드 자체가 조금 어색해서 개인적으로 더 공부를 해보겠습니다

  • 프론트 출신 아니랄까봐 뭔가 코드를 JS 처럼 짜는 나쁜 버릇이 있는 것 같습니다. Java만의 메서드들을 통해서 좀더 객체지향적으로 코드를 설계해보고 싶습니다!

Copy link

@GaHee99 GaHee99 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

서버 새싹이라고 하기엔 많은 내용을 알고 있어서 굉장히 놀랐따우!
시험기간인데 풀리퀘 날리느라 고생했고,
나랑 같이 해볼 패턴이 좀 보인다우

  1. 빌더패턴 적용
  2. Response메시지 DTO만들어보기
  3. Response메시지 알아보기
  4. 에러처리하기
    다 적용해보자 이번주에 얘기하고!

ResponseMenuDto responseMenuDto=ResponseMenuDto.newInstance(menu.getName(),menu.getPrice());
HttpHeaders httpHeaders=new HttpHeaders();

return new ResponseEntity(responseMenuDto,httpHeaders,HttpStatus.OK);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

헤더에 아무 내용이 없는데, 헤더 넣어서 보내는 이유가 모에용?


boolean isDeleted=false;
Menu delMenu=null;
for (Menu menu:menuList) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

private String name;
private int price;

public static ResponseMenuDto newInstance(String name,int price){
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

인스턴스 만들 때 따로 메서드로 newInstance로 만드는 이유가 모죠?

Copy link

@2zerozu 2zerozu Apr 21, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cmd+option+v 누르면 인스턴스 자동으로 만들어진대요!!

"contact "+this.contact+"\n"+
"age "+this.age+"\n";
}
private Long id;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

변수들 위로 올리자고~

public class MenuService {

public String RegisterMenu(RequestMenuDto request){
Menu menu=new Menu(request.getName(),request.getPrice());
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

에러처리도 가보자고~

public class UserService {
public Long register(RegisterRequestDto request){

User newUser=new User(request.getGender(),request.getName(),request.getContact(),request.getAge());
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

우리 이거 빌더패턴 해볼까?

Copy link

@2zerozu 2zerozu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

고생하셨습니다!!
코드 보고 배우고 갑니다~~

private String name;
private int price;

public static ResponseMenuDto newInstance(String name,int price){
Copy link

@2zerozu 2zerozu Apr 21, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cmd+option+v 누르면 인스턴스 자동으로 만들어진대요!!

Comment on lines +34 to +48
@GetMapping("/post")
public ResponseEntity getPostByTitle(@RequestParam final String title){
for(int i=0;i<postList.size();i++){
if(postList.get(i).getTitle().equals(title)){
Post post=postList.get(i);
HttpHeaders httpHeaders=new HttpHeaders();
PostResponseDto postResponseDto=PostResponseDto.newInstance((post.getTitle()),post.getCreate_user(),post.getContent());
return new ResponseEntity(postResponseDto,httpHeaders, HttpStatus.OK);
}
}

throw new ResponseStatusException(
HttpStatus.NOT_FOUND, "entity not found"
);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

에러처리 잘 보고갑니다!!!

Copy link
Member

@sojungpp sojungpp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR 과제 설명 작성하신 거 와 마크다운 장인이시네요
exception 처리하는 거 잘 보고 배워갑니당

Comment on lines +35 to +41
public ResponseEntity getPostByTitle(@RequestParam final String title){
for(int i=0;i<postList.size();i++){
if(postList.get(i).getTitle().equals(title)){
Post post=postList.get(i);
HttpHeaders httpHeaders=new HttpHeaders();
PostResponseDto postResponseDto=PostResponseDto.newInstance((post.getTitle()),post.getCreate_user(),post.getContent());
return new ResponseEntity(postResponseDto,httpHeaders, HttpStatus.OK);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 부분은 stream() 사용하시면 더 깔끔하게 코드 작성할 수 있을 것 같아요 🙌

Comment on lines +29 to +31
throw new ResponseStatusException(
HttpStatus.NOT_FOUND, "entity not found"
);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HttpStatus 활용한 예외처리 배워가겠슴니다

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants