Skip to content

[강정민] sprint3#38

Open
jeongmin00 wants to merge 2 commits intocodeit-sprint-fullstack:basic-강정민from
jeongmin00:basic-강정민-sprint3

Hidden character warning

The head ref may contain hidden characters: "basic-\uac15\uc815\ubbfc-sprint3"
Open

[강정민] sprint3#38
jeongmin00 wants to merge 2 commits intocodeit-sprint-fullstack:basic-강정민from
jeongmin00:basic-강정민-sprint3

Conversation

@jeongmin00
Copy link
Copy Markdown
Collaborator

@jeongmin00 jeongmin00 commented Mar 16, 2026

요구사항

기본 요구사항

공통

  • Github에 스프린트 미션 PR을 만들어 주세요.
  • 'https://panda-market-api-crud.vercel.app/docs/#/Article' API를 이용하여 아래 함수들을 구현해 주세요.
    • [ ] getArticleList() : GET 메서드를 사용해 주세요.
      • [ ] pagepageSizekeyword 쿼리 파라미터를 이용해 주세요.
    • [ ] getArticle() : GET 메서드를 사용해 주세요.
    • [ ] createArticle() : POST 메서드를 사용해 주세요.
      • request body에 titlecontentimage 를 포함해 주세요.
    • [ ] patchArticle() : PATCH 메서드를 사용해 주세요.
    • [ ] deleteArticle() : DELETE 메서드를 사용해 주세요.
  • fetch 혹은 axios 를 이용해 주세요.
    • 응답의 상태 코드가 2XX가 아닐 경우, 에러메시지를 콘솔에 출력해 주세요.
  • .then() 메서드를 이용하여 비동기 처리를 해주세요.
  • .catch() 를 이용하여 오류 처리를 해주세요.
  • 'https://panda-market-api-crud.vercel.app/docs/#/Product' API를 이용하여 아래 함수들을 구현해 주세요.
    • [ ] getProductList() : GET 메서드를 사용해 주세요.
      • [ ] pagepageSizekeyword 쿼리 파라미터를 이용해 주세요.
    • [ ] getProduct() : GET 메서드를 사용해 주세요.
    • [ ] createProduct() : POST 메서드를 사용해 주세요.
      • request body에 namedescriptionpricetagsimages 를 포함해 주세요.
    • [ ] patchProduct() : PATCH 메서드를 사용해 주세요.
    • [ ] deleteProduct() : DELETE 메서드를 사용해 주세요.
  • async/await 을 이용하여 비동기 처리를 해주세요.
  • try/catch 를 이용하여 오류 처리를 해주세요.
  • 구현한 함수들을 아래와 같이 파일을 분리해 주세요.
    • [ ] export를 활용해 주세요.
    • [ ] ProductService.js 파일 Product API 관련 함수들을 작성해 주세요.
    • [ ] ArticleService.js 파일에 Article API 관련 함수들을 작성해 주세요.
  • 이외의 코드들은 모두 main.js 파일에 작성해 주세요.
    • [ ] import를 활용해 주세요.
    • 각 함수를 실행하는 코드를 작성하고, 제대로 동작하는지 확인해 주세요.

@jeongmin00 jeongmin00 requested review from iamjaeholee and yongsub-lee and removed request for yongsub-lee March 16, 2026 08:51
@jeongmin00 jeongmin00 changed the title feat: Article 및 Product API 서비스 구현 및 README 작성 [강정민] sprint3 Mar 16, 2026
@jeongmin00 jeongmin00 requested review from greatelv and removed request for iamjaeholee March 20, 2026 07:53
Copy link
Copy Markdown
Collaborator

@greatelv greatelv left a comment

Choose a reason for hiding this comment

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

이번 스프린트에서 비동기 처리 로직(.then, async/await)을 학습하시고 직접 API 연동까지 훌륭히 구현해 주셨네요! 전반적인 흐름과 로직 구조가 매우 좋습니다. 👏

다만 실제 서비스 코드라고 상상했을 때 발생할 수 있는 잠재적 버그, 그리고 코드의 중복을 피해 유지보수성을 극대화(DRY 원칙)할 수 있는 심화 과정의 피드백을 다양하게 남겨드립니다. 천천히 읽어보시고 적용해 보시면 큰 도움이 될 것 같습니다!

(※ 참고로, 혹 AI 도구를 활용해 바이브코딩을 진행하셨다면, 이 피드백만큼은 가급적 AI의 도움 없이 직접 원리를 파악하며 보시기를 적극 권장해 드립니다.)

package.json Outdated
"start": "node src/main.js"
},
"dependencies": {
"axios": "^1.x.x"
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

P3

현재 프로젝트의 두 서비스 클래스가 모두 브라우저 내장 fetch API를 사용하여 네트워킹을 잘 처리하고 있습니다. axios가 의존성에 설치되어 있으나 실제로는 사용되지 않는 것으로 보이는데, 패키지 혼란을 막기 위해 사용하지 않는 라이브러리라면 과감하게 제거해 주시는 것을 권장해 드립니다.

@@ -0,0 +1,76 @@
// src/api/ArticleService.js
const BASE_URL = 'https://panda-market-api-crud.vercel.app/articles';
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

P4

ArticleServiceProductService 모두 BASE_URL이 중복으로 선언되어 있고 하드코딩 되어 있습니다. 중복 선언을 방지하고 조금 더 시니어 레벨의 구조를 고민하신다면, 향후 src/config/index.js나 별도의 상수 파일로 BASE_URL을 분리하여 import 하는 패턴을 적용해 보시는 것도 좋은 베스트 프랙티스입니다!

* 1. 게시글 목록 조회 (GET /articles)
* 파라미터: page, pageSize, orderBy(recent/like), keyword
*/
export const getArticleList = (page = 1, pageSize = 10, orderBy = 'recent', keyword = '') => {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

P3

keyword = ''인 상태로 URLSearchParams에 넘겨지면 ...?keyword=와 같이 불필요한 빈 쿼리스트링 파라미터가 생성될 수 있습니다. 값이 있을 때만 파라미터에 추가되도록 조건부로 처리하시면 훨씬 더 깔끔하고 견고한 URL이 생성될 것 같습니다.

const params = new URLSearchParams({ page, pageSize, orderBy, keyword });

return fetch(`${BASE_URL}?${params.toString()}`)
.then((response) => {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

P2

fetch 모듈 호출, response.ok 체크, .json() 파싱을 수행하는 이 로직이 모든 API 메서드(CRUD)에 계속 반복되고 있습니다. 이러한 중복(DRY 위배) 코드를 피하기 위해 request(url, options) 처럼 공통 유틸리티 함수를 만들어서 관리하시면 코드가 절반 이하로 훨씬 간결해질 것입니다. 한 번 고려해 보세요!

body: JSON.stringify(productData),
});

if (!response.ok) throw new Error(`상품 생성 실패: ${response.status}`);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

P3

fetch 통신 요청이 실패했을 경우, 백엔드 서버에서 구체적인 에러 메시지가 담긴 JSON Body를 내려주는 경우가 잦습니다. 실패 시 단순히 HTTP Code(.status)만 던지기보단, await response.text().json()을 활용해 에러 사유를 구체적으로 파싱하여 에러 객체에 담는 코드를 짜보시면 실무 디버깅 난이도가 한결 낮아집니다!

src/main.js Outdated
// 5. 상품 삭제
if (createdProduct && createdProduct.id) {
const deletedProduct = await ProductService.deleteProduct(createdProduct.id);
console.log(`✅ [Product] ${createdProduct.id}번 삭제 완료:\n`, deletedProduct);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

P3

runProductTests는 비동기(async) 함수이므로 뒷단의 코드도 기다림 없이 곧바로 실행되게 됩니다. 그 결과 터미널 로그의 출력 시점이 뒤섞이게 되어(Race Condition 현상) 결과를 확인하기 쉽지 않습니다. async IIFE(즉시 실행 함수) 등을 활용하여 해당 테스트가 온전히 끝난 후 다른 테스트가 순차적으로 실행되도록 제어 메커니즘을 부여해 보시는 것을 권장해 드립니다.

image: "https://example.com/test-image.png",
};

ArticleService.createArticle(newArticleData)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

P4

생성 데이터가 누락되거나 ID가 제대로 반환되지 않았을 불확실성을 사전 대비한 아주 훌륭한 방어적 프로그래밍 관점의 체크 포인트입니다! 👏 아주 좋습니다.

src/main.js Outdated

ArticleService.createArticle(newArticleData)
.then((createdData) => {
console.log("✅ [Article] 생성 결과:\n", createdData);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

P3

이 부분의 .then() 내부를 보면, 하위 구조에서 다시 ArticleService.patchArticle 체이닝 구조를 만들어 리턴하고 있습니다. 바깥 로직과 잘 연동은 되지만 Promise Hell 징후를 다소 보이고 있습니다. 뎁스(Depth)를 깊게 들어가지 말고 바깥쪽 스코프의 플래트닝(Flattening) 체인으로 연결을 시도해 보시면 더욱 가독성 높고 유려한 비동기 컨트롤 흐름을 구사하실 수 있을 것 같습니다!

src/main.js Outdated
return ArticleService.deleteArticle(createdData.id);
})
.then((deleteData) => {
console.log(`✅ [Article] ${createdData.id}번 삭제 완료:\n`, deleteData);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

P2

비동기 Promise 체이닝의 종단점 체인 끝에는 반드시 단일 .catch() 블록을 두는 것이 좋습니다. 체인 과정 속 어느 시점에서 이슈가 터지더라도 한 곳에서 확실하게 잡아내어(Unhandled Promise Rejection 방지) 앱의 크래시를 막고 통일된 예외 처리가 가능하므로 로직 마지막에 꼭 추가해 주시기 바랍니다!

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants