본문 바로가기

내일배움캠프

Trello프로젝트(심화 프로젝트) 1일차

지금껏 배운 내용으로 팀 프로젝트를 시작하기로 했다.

 

프로젝트의 주제는 다음과 같다.

와이어프레임:

ERD Diagram:

API명세서:

Github rules:https://teamsparta.notion.site/Github-Rules-d46a7603bb2f4c12bfd6a8f712a4732b

 

Github Rules | Notion

깃허브 규칙

teamsparta.notion.site

 

요구사항 중에 특이한 점이 하나 있었다.

보드에 사용자를 초대하면 보드가 아닌 해당 보드에 소속된 컬럼에 소속된 카드에 대한 권한을 부여해야 하는지라 구현이 쉽지 않을 것 같았다.

 

참고로 필자는 컬럼과 관련된 api 담당이다. 

 

프로젝트를 시작하기 전에 엔티티가 준비되어 있지 않으면 작업을 진행할 수 없을 것 같아서 미리 엔티티를 구현한 다음 작업을 시작하려고 했었다.

그런데 한 가지 문제가 생겼다. 원격 레포지토리로 push를 할 수 없었다.

실제 겪었던 오류와 비슷한 사진으로 가져왔다. 출처:https://velog.io/@s0nnyday/%EA%B9%83%ED%97%88%EB%B8%8C-%EC%98%A4%EB%A5%98-organization-%EC%83%9D%EC%84%B1-%ED%9B%84-The-requested-URL-returned-error403

 

계정 권한 문제였던것 같아서 관련 내용을 조사해봤다.

https://syntaxsugar.tistory.com/entry/Git-GitHub-Organization-remote-Permission-to-repository

 

[Git] GitHub Organization - remote: Permission to repository

GitHub Organization을 이용하면서 발생한 문제입니다. Organization에 있는 Repository는 권한을 얻기전까지 push할 수가 없습니다. $ git push ✱ remote: Permission to Dev-Sweeter/go-jose.git denied to bang9211. fatal: unable to

syntaxsugar.tistory.com

이 포스트에 따르면 personal access token이 없는게 문제인 것 같았다.

그래서 계정 설정에서 personal access token을 발급해 보기로 했다.

토큰을 생성하려고 보니까 굉장히 상세하게 권한을 부여할 수 있었다. 뭘 골라야 할지 몰라서 일단 사진처럼 권한을 체크하고 토큰을 생성했다.

위 글에서 빨갛게 칠해진 곳에 토큰을 집어넣고 push하면 된다고 했다. 

그런데 여전히 똑같은 에러가 발생했다. 혹시 몰라서 이번에는 모든 권한을 전부 부여한 채로 토큰을 다시 생성하고 토큰을 붙여 보았다.

 

다행히 이번에는 잘 push가 되었다. 아마 내가 놓친 권한이 있어서 그랬던 것 같다.

 

어쨌든 이런 우여곡절 끝에 필요한 엔티티를 모두 구현했고 본격적으로 개발을 시작했다.

 

오늘은 시간이 많이 지체되서 많은 작업을 할 수 없었다. 그래서 오늘은 컬럼 생성과 수정만 구현을 했다.

Column 엔티티:

@Entity
@Table(name = "columns")
@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Columns extends Timestamped {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne
    @JoinColumn(name = "board_id")
    private Board board;
    @Enumerated(value = EnumType.STRING)
    private CategoryEnum category;

    public void updateComment(ColumnsRequestDto requestDto) {
        this.category = CategoryEnum.valueOf(requestDto.getCategory());
    }
}

Board 엔티티:

@Entity
@Table(name = "boards")
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Board extends Timestamped {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String title;

    private String description;

}

 

Service클래스:

@Service
@RequiredArgsConstructor
public class ColumnsServices {
    private final ColumnsRepository columnsRepository;
    private final BoardRepository boardRepository;

board와의 연관관계 때문에 BoardRepository도 주입을 시켰다.

public ColumnsResponseDto createColumns(Long boardId, ColumnsRequestDto requestDto) {
    Board board = boardRepository.findById(boardId).orElseThrow(() -> new IllegalArgumentException("존재하지 않는 보드입니다."));
    Columns columns = Columns.builder()
            .board(board)
            .category(CategoryEnum.valueOf(requestDto.getCategory()))
            .build();
    columnsRepository.save(columns);
    ResponseData responseData = new ResponseData(columns.getCategory());
    return createResponseDto("컬럼 생성성공", HttpStatus.CREATED, responseData);
}

관계를 맺을 board를 찾고 column을 생성할 때 board를 해당 컬럼에 입력했다. db에 저장될 때는 board의 id 값이 외래키로 저장될 것이다.

public ColumnsResponseDto createColumns(Long boardId, ColumnsRequestDto requestDto) {
    Board board = boardRepository.findById(boardId).orElseThrow(() -> new IllegalArgumentException("존재하지 않는 보드입니다."));
    Columns columns = Columns.builder()
            .board(board)
            .category(CategoryEnum.valueOf(requestDto.getCategory()))
            .build();
    columnsRepository.save(columns);
    ResponseData responseData = new ResponseData(columns.getCategory());
    return createResponseDto("컬럼 생성성공", HttpStatus.CREATED, responseData);
}

findById 쿼리 메소드는 자주 사용할 것 같아서 따로 메소드를 정의했다.

ResponseDto객체를 생성하는 생성자도 자주 호출할 것 같아서 별도로 메소드를 정의했다.

public Columns findById(Long id) {
    return columnsRepository.findById(id).orElseThrow(() -> new IllegalArgumentException("존재하지 않는 컬럼입니다."));
}

public ColumnsResponseDto createResponseDto(String msg, HttpStatus status, ResponseData responseData) {
    return ColumnsResponseDto.builder()
            .msg(msg)
            .statuscode(status.value())
            .data(responseData)
            .build();
}

Controller 클래스:

@RestController
@RequiredArgsConstructor
@RequestMapping("/api")
public class ColumnsController {
    private final ColumnsServices columnsServices;

    @PostMapping("/boards/{id}/columns")
    public ColumnsResponseDto createColumns(@PathVariable("id") Long id, @RequestBody ColumnsRequestDto requestDto) {
        return columnsServices.createColumns(id, requestDto);
    }
    @PutMapping("/columns/{id}")
    public ColumnsResponseDto updateColumns(@PathVariable("id") Long id, @RequestBody ColumnsRequestDto requestDto) {
        return columnsServices.updateColumns(id, requestDto);
    }
}

 

내일은 컬럼의 순서를 바꾸는 api를 어떻게 만들지 생각해 봐야겠다.

 

글쓰다가 지금 생각나서 적는건데 위에 적어놓은 Column엔티티가 정상적으로 생성되지 않는 것을 팀원들 각자 엔티티를 구현하고 develop 브랜치에 푸쉬하고 나서 뒤늦게 발견했다. 아마 기존에는 테이블 이름을 'column'으로 했었는데 이게 mysql에서 예약어로 지정되어 있어서 생성을 못하는것 같았다.

@Table(name = "columns")

지금은 위의 코드처럼 이름을 바꾸니 잘 동작한다.