각종 후기/우아한테크코스

[우아한 테크코스 3기] LEVEL 1 회고 - 체스 4, 5단계 미션 1차 피드백을 받아보다 (62일차)

제이온 (Jayon) 2021. 4. 4.

안녕하세요? 제이온입니다.

 

레벨 1 방학을 만끽하던 중에 체스 미션 4, 5단계 피드백이 와서 공유합니다.

 

 

체스 미션 4, 5단계 1차 피드백

1, 2, 3단계와 마찬가지로 김고래 리뷰어님이 피드백을 남겨주셨습니다. 오늘 오후 즈음에 피드백이 왔다는 알림을 받고 확인해보니, 수정 사항이 꽤 많았습니다. 그래서 집으로 돌아와서 나름대로 수정을 해 보았습니다. 자잘한 내용을 제외하고 피드백 내용을 공유하겠습니다.

 

 

 

 

첫 번째 수정 사항은 추상화하는 것입니다. 그런데.. 해당 기능을 도저히 분리를 못하겠어서 일단은 뒤로 미뤘습니다.

 

 

    public void savePiece(final Position position, final Piece piece) throws SQLException {
        final String query = "INSERT INTO pieces VALUES (?, ?)";
        try (final Connection conn = ConnectionSetup.getConnection();
            final PreparedStatement pstmt = conn.prepareStatement(query)) {
            pstmt.setString(1, position.horizontalSymbol() + position.verticalSymbol());
            pstmt.setString(2, piece.name());
            pstmt.executeUpdate();
        }
    }

    public void updatePiece(final Position position, final String name) throws SQLException {
        final String query = "UPDATE pieces SET name = ? WHERE position = ?";
        try (final Connection conn = ConnectionSetup.getConnection();
            final PreparedStatement pstmt = conn.prepareStatement(query)) {
            pstmt.setString(1, name);
            pstmt.setString(2, position.horizontalSymbol() + position.verticalSymbol());
            pstmt.executeUpdate();
        }
    }

    public void deleteAll() throws SQLException {
        final String query = "TRUNCATE TABLE pieces";
        try (final Connection conn = ConnectionSetup.getConnection();
            final PreparedStatement pstmt = conn.prepareStatement(query)) {
            pstmt.executeUpdate();
        }
    }

 

 

이런식으로 비슷한 구조가 반복되는데 추후 고민해 보려고 합니다.

 

 

 

 

두 번째 수정 사항은 적절한 에러 코드를 사용하라는 것입니다. 저는 400번대가 다 비슷하게 오류와 관련된 처리를 하는 줄 알고 적당한 번호를 써 보았는데, 이 기회에 각각의 에러 코드를 정리하였습니다.

 

 

https://codediver.tistory.com/132

 

 

401번은 로그인 하지 않은 상태에서 로그인해야 접근 가능한 컨텐츠를 접근할 때 발생하는 에러 코드이며, 403번은 관리자 권한이 없는 상태에서 관리자 페이지 등을 접근할 때 발생하는 에러 코드라 생각하시면 되겠습니다. 그 외에 설명은 명확해서 넘어가도 좋겠습니다.

 

 

 

 

세 번째 수정 사항은 적절한 곳에서 예외를 처리하라는 것입니다. 저는 처음에 예외는 비중을 적게 두고 기능 구현에 초점을 맞춰서 해당 SQLException을 모두 시그니처에 박아뒀습니다. 그러다가 위 피드백을 받고 나서 Dao 단에서는 시그니처를 정의하되, 해당 Dao를 쓰는 곳에서 catch 하도록 수정하였습니다.

 

 

    public Response end() {
        if (chessGame.isGameOver()) {
            try {
                boardDao.updateIsGameOver();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            return new Response(ResponseCode.GAME_OVER.code(), ResponseCode.GAME_OVER.message());
        }
        return new Response(ResponseCode.RUN.code(), ResponseCode.RUN.message());
    }

 

 

이런 방식으로 사용하는 입장에서 예외를 처리하도록 수정하였으나, 리뷰어님이 말씀하신 "계속 위로 넘기지 말라"를 지킨 것처럼 보이지는 않아서 이 부분은 따로 질문하였습니다.

 

 

 

 

네 번째 수정 사항은 close와 관련된 것입니다. 저는 Connection만 close 해야 하는 줄 알고 그것만 try with resource를 사용하여 자원을 해제하였습니다. 하지만, PreparedStatement와 ResultSet도 close해야하는 것을 알게 되었고, 다음과 같이 코드를 작성했습니다.

 

 

    public BoardDto load() throws SQLException {
        final String query = "SELECT * FROM board";

        try (final Connection conn = ConnectionSetup.getConnection();
            final PreparedStatement pstmt = conn.prepareStatement(query);
            final ResultSet rs = pstmt.executeQuery()) {
            if (!rs.next()) {
                return null;
            }

            final String team = rs.getString("team");
            final boolean isGameOver = rs.getBoolean("isGameOver");
            return new BoardDto(team, isGameOver);
        }
    }

 

 

참고로 여러 개의 자원을 사용할 때는 콤마가 아니라 세미콜론을 써 주어야 합니다. 위의 코드가 길다고 느껴지면 각 변수를 try 전에 할당한 다음에 변수명만 쓰는 '향상된 try with resource'가 있는데, 이것은 java 9 이상부터 가능합니다.

 

 

 

 

다섯 번째 수정 사항은 Optional을 사용하라는 것입니다. 다만, 저는 Optional이 null 대신 초깃값을 설정하기 위해 사용하는 것으로 알고 있는데 해당 부분에서 어떻게 응용하는지 모르겠어서 리뷰어님께 질문을 남겼습니다.

 

 

 

 

여섯 번째 수정 사항은 urI를 구분하라는 것입니다. 렌더링하기 위한 urI는 '/'나 '/result'와 같이 작성하였고, api를 요청하는 urI는 '/api/xx'와 같이 엔트리 포인트를 작성해 주었습니다.

 

 

 

 

마지막 수정 사항은 Update를 통해 해결했습니다. 저는 Update 쿼리문을 잘 몰랐어서 메소드의 인자가 4개가 필요하다고 생각했는데 그것이 아니었습니다.

 

 

    public void updatePiece(final Position position, final String name) throws SQLException {
        final String query = "UPDATE pieces SET name = ? WHERE position = ?";
        try (final Connection conn = ConnectionSetup.getConnection();
            final PreparedStatement pstmt = conn.prepareStatement(query)) {
            pstmt.setString(1, name);
            pstmt.setString(2, position.horizontalSymbol() + position.verticalSymbol());
            pstmt.executeUpdate();
        }
    }

 

 

위와 같이 충분히 인자가 2개인 메소드를 2번 호출함으로써 이동할 때마다 변화된 데이터를 업데이트할 수 있었습니다. 더불어 턴과 게임 종료 여부도 업데이트 쿼리문으로 수정하였습니다.

 

 

정리

피드백을 반영하는데 꽤 오랜 시간이 걸렸지만, 오늘 안에 다시 리뷰 요청을 보내게 되어 다행이라고 생각합니다. 아직 해결되지 못한 사항이 있지만, 리뷰어님과의 대화나 다른 크루의 도움을 통해 해결할 수 있을 듯합니다.

댓글

추천 글