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

게시글 작성 api에서 사진을 없는 경우 empty file을 보내는 방식 수정 및 수정 관련 버그 수정 #557

Merged
merged 50 commits into from
Sep 19, 2023

Conversation

chsua
Copy link
Collaborator

@chsua chsua commented Sep 11, 2023

🔥 연관 이슈

close: #541: 게시글 작성 api에서 사진을 없는 경우 empty file을 보내는 방식 수정 및 수정 관련 버그 수정
close: #531: 게시글 작성 시 기간이 7일까지 설정할 수 있도록 하기
close: #280: [BUG] 본문과 내용에 사진을 추가할 때 안될 때가 있다
close: #480:[BUG] IOS에서 마감시간, 생성시간이 NaN으로 나오는 것 수정
close: #482:[BUG] safari에서 글 쓸때 확대되어서 보인다는 제보가 들어옴

📝 작업 요약

api변경에 따른 적용

  • 게시글 작성 api에서 사진을 없는 경우 없는사진.jpg file을 보내는 방식 수정
  • 게시글 수정 시 option ID도 보내기
  • imageUrl 미리보기를 위해 도메인 붙이기/제거하기 로직 삭제(서버에서 해주기로)

정책 수정에 따른 적용

  • 정책 변경에 따라 14일 마감시간 연장

버그 수정

  • 선택지 동일한 사진 삭제후 업로드 안되는 오류 수정
  • 본문 내용에 연속으로 개행이 있는 경우 개행 1회로 변환 처리

UI

  • 기간 nan나오는거 수정
  • 사파리 글쓸때 확대되는거 수정
  • 글쓰기 모바일 페이지 UI 수정 - 좌우 마진 동일하게, 데스크탑 사진 크기 줄이기

⏰ 소요 시간

주말동안 죽어있었습니다..

🔎 작업 상세 설명

api변경에 따른 적용

  • 게시글 작성 api에서 사진을 없는 경우 없는사진.jpg file을 보내는 방식 수정
    • 만약 사진이 없다면 imageFile 필드를 아예 보내지 않음
//formData 관련 알고 리뷰하면 좋을 지식

//기본적으로 프론트에서 이렇게 넣어 보내면
formData.append(필드명, file | string)

//서버에서는 아래처럼 객체로 보입니다.
{
    필드명: file | string
}


//이렇게 프론트에서 동일한 필드명을 넣어 보내면
formData.append(A, "Apple")
formData.append(A, "Banana")

//서버에서는 아래처럼 배열로 보입니다.
{
    A: ["Apple", "Banana"]
}


//이렇게 프론트에서 "동일한 필드명[index].필드명"을 넣어 보내면
formData.append(A[0].a, "Apple")
formData.append(A[0].b, "Banana")

//서버에서는 아래처럼 객체가 들어있는 배열로 보입니다.
{
    A: [{
        a: "Apple", 
        b: "Banana"
    }]
}

정책 수정에 따른 적용

  • 정책 변경에 따라 14일 마감시간 연장
    • 버튼도 모두 변경(1일, 3일...). 이에 따라 기존 버튼 관련 배열 형태 수정. time과 이름을 묶어놔야 추후에 또 마감시간 정책이 변경될 때 적용이 쉬워보임
// 수정전
export const DEADLINE_OPTION: DeadlineOption[] = ['10분', '30분', '1시간', '6시간', '1일'];

//수정후
export const DEADLINE_OPTION: DeadlineOptionInfo[] = [
  {
    name: '1일',
    time: {
      day: 1,
      hour: 0,
      minute: 0,
    },
  },...
]

버그 수정

  • 선택지 동일한 사진 삭제후 업로드 안되는 오류 수정
    • option관련 hook에 ref를 사용해 element[]를 저장

UI

🌟 논의 사항

  • 변경된 api형태는 노션에 적도록 하겠습니다.
  • 글씨 크기에 대해 더 논의해보면 좋을 것 같아요. 너무 작아보여요.
  • 머지는 다즐 완성되면 연결해보고 머지하겠습니다!

- grid 속성 설정 + 내부 자식 width: 100% 설정
- 헤더 내 취소/제출 버튼을 헤더 글씨 버튼 컴포넌트로 수정(다른 헤더와 통일성 위해)
- 원인: 사파리에서는 input, textArea의 폰트 크기가 16px 미만이면 자동 zoom이 됨
+ 현재와 30일 이상 차이나는 날짜는 "yyyy-mm-dd"형식 문자열로 그려지게 수정
- 공통된 Time interface type폴더로 이동 및 적용
- 마감 제한 시간 상수화
- 마감일자 optionList 형태 변경
- 기존: 받은 imageUrl에 http-를 붙여야 image가 보여짐. 반대로 http-를 떼서 수정 api를 보내야 함
- 수정: 서버에서 보내주는 url 그대로 받아서 image를 보이고 수정 api를 보냄
Copy link
Member

@inyeong-kang inyeong-kang left a comment

Choose a reason for hiding this comment

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

image
그저 GOD 수아.................

레전드 리팩토링입니다.

프로젝트에서 리팩토링 1순위라고 생각했는데 상수 분리, hook 분리 등등 컴포넌트에서 관심사 분리를 매우 깔끔하게 해주셔서 감탄만 나오네요.. 정말 고생 많으셨습니다:)

@@ -0,0 +1,61 @@
import { convertTimeToWord } from '@utils/time';
Copy link
Member

Choose a reason for hiding this comment

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

이 파일 제목 다른 파일들처럼 테스트하려는 함수명(convertTimeword.test.ts)으로 통일하는거 어떠신가요?


export const DEADLINE_OPTION: DeadlineOption[] = ['10분', '30분', '1시간', '6시간', '1일'];
export type DeadlineOptionName = '1일' | '3일' | '5일' | '7일' | '14일';
Copy link
Member

Choose a reason for hiding this comment

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

👍👍

time: Time;
}

export const DEADLINE_OPTION: DeadlineOptionInfo[] = [
Copy link
Member

Choose a reason for hiding this comment

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

오 분리하니까 훨씬 깔끔해졌네요!!👍

formData.append('categoryIds', categoryId.id.toString())
);
formData.append('title', writingTitle);
formData.append('content', deleteOverlappingNewLine(writingContent));
Copy link
Member

Choose a reason for hiding this comment

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

음 혹시 여러줄의 개행을 한번의 개행으로 만드시려는 의도가 궁금해요!

사용자가 여러줄 개행하고 싶어하는 경우에도 한번의 개행으로 되어버리지 않나요??

Copy link
Collaborator

Choose a reason for hiding this comment

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

음 그러게요 여러줄을 개행해서 문단을 만들고 싶어하는 유저도 있을 수 있겠네요

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

데모데이에서 한 코치분께서 해보셨던 케이스가 있는데요,
연속된 개행이 계속되는 경우 의미없이 엄청 긴 개행이 일어났어요.
저도 그것을 보면서 불필요한 개행은 제한되어야 한다고 생각했습니다!
해당 부분 대면으로 상의 후 5줄로 수정하겠습니다!

!imageUrlList[index] || imageUrlList[index] === serverImageUrl
? contentImageFileList.push(new File(['없는사진'], '없는사진.jpg'))
: contentImageFileList.push(item.files[0]);
item.files[0] && formData.append('imageFile', item.files[0]);
Copy link
Member

Choose a reason for hiding this comment

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

와우 코드 가독성이 굉장히 개선되었네요!! 속이 뻥 뚫립니다...감사해요👍👍

if (optionList.length > 5) return '선택지는 최대 5개 입력할 수 있습니다.';
if (optionList.some(option => option.content.trim() === '')) return '선택지에 글을 입력해주세요.';

if (Object.values(time).reduce((a, b) => a + b, 0) < 1) return '시간은 필수로 입력해야 합니다.';
Copy link
Member

Choose a reason for hiding this comment

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

이 케이스는 time의 minute, hour, day 가 모두 0인 경우인가요?

const isTimeOptionsZero = Object.values(time).reduce((a, b) => a + b, 0) < 1;
if (isTimeOptionsZero) return '시간은 필수로 입력해야 합니다.';

요렇게 한번 변수로 분리해주는건 어떠신가요? 이 코드를 처음 보는 개발자도 빨리 이해하면 좋겠다 싶어서요!

@@ -181,7 +183,7 @@ export const WithTimePicker = () => {
<S.CloseButton onClick={closeModal}>X</S.CloseButton>
</S.Header>
<S.Body>
<S.Description>최대 3일을 넘을 수 없습니다.</S.Description>
<S.Description>최대 {MAX_DEADLINE}일을 넘을 수 없습니다.</S.Description>
Copy link
Member

Choose a reason for hiding this comment

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

👍👍

accept="image/*"
tabIndex={-1}
ref={(ele: HTMLInputElement) => {
if (contentInputRefList.current) {
Copy link
Member

Choose a reason for hiding this comment

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

만약 if문에 안걸리면 ref에는 undefined 가 할당되는건가용?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

아마 제 예상으로는 그럼 아예 할당이 되지 않아서 기존값인 null이 유지될 것 같습니다.

@@ -76,6 +77,10 @@ export const useWritingOption = (initialOptionList: WritingVoteOptionType[] = IN
});

setOptionList(updatedOptionList);
contentInputRefList.current &&
Copy link
Member

Choose a reason for hiding this comment

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

오.. 이 부분 내일 설명해주실 수 있을까요..? 살짝 아리까리해서...🤔

@@ -40,8 +40,8 @@ export const GlobalStyle = createGlobalStyle`
/* Fonts *****************************************/
--text-title: 600 2rem/2.4rem san-serif;
--text-subtitle: 600 1.8rem/2.8rem san-serif;
--text-body: 400 1.6rem/2.4rem san-serif;
--text-caption: 400 1.4rem/2rem san-serif;
--text-body: 400 1.7rem/2.4rem san-serif;
Copy link
Member

Choose a reason for hiding this comment

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

👍👍

@inyeong-kang
Copy link
Member

fe-리뷰완

Copy link
Collaborator

@Gilpop8663 Gilpop8663 left a comment

Choose a reason for hiding this comment

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

깔끔한 코드 잘 보았습니다 👍👍👍

그리고 PR에 상세히 설명을 적어주셔서 코드 이해에 많은 도움이 되었어요

테스트도 적어주셔서 함수가 무슨 동작을 하는 지 쉽게 보였습니다

몇 가지 코멘트를 달았는데요. 크게 수정할 부분은 없어서 어프로브 하겠습니다

👍👍👍 깔끔한 코드 리스펙해요 🔥🔥🔥

fe-리뷰완

Comment on lines 31 to 34
const text =
'안녕하세요. 이것은 유틸함수를 테스트하기 위한 문자열입니다.\n\n\n동일한 결과물이 나와야 옳은 작동을 하는 유틸함수 입니다.';
const expectText =
'안녕하세요. 이것은 유틸함수를 테스트하기 위한 문자열입니다.\n동일한 결과물이 나와야 옳은 작동을 하는 유틸함수 입니다.';
Copy link
Collaborator

Choose a reason for hiding this comment

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

과도한 엔터키를 막을 수 있겠네요 👍👍

세심하신데요?

Comment on lines 139 to 138
if (selectedOptionList.length < 1) return openToast('카테고리를 최소 1개 골라주세요.');
if (selectedOptionList.length > 3) return openToast('카테고리를 최대 3개 골라주세요.');
if (writingTitle.trim() === '') return openToast('제목은 필수로 입력해야 합니다.');
if (writingContent.trim() === '') return openToast('내용은 필수로 입력해야 합니다.');
if (writingOptionList.length < 2) return openToast('선택지는 최소 2개 입력해주세요.');
if (writingOptionList.length > 5) return openToast('선택지는 최대 5개 입력할 수 있습니다.');
if (writingOptionList.some(option => option.content.trim() === ''))
return openToast('선택지에 글을 입력해주세요.');
if (Object.values(time).reduce((a, b) => a + b, 0) < 1)
return openToast('시간은 필수로 입력해야 합니다.');
const errorMessage = checkValidationPost(
selectedOptionList,
writingTitle,
writingContent,
writingOptionList,
time
);
if (errorMessage) return openToast(errorMessage);
Copy link
Collaborator

Choose a reason for hiding this comment

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

함수로 만드니깐 너무 깔끔해요 !! 👍👍👍

Comment on lines 141 to 157
const imageFileInputs = e.target.querySelectorAll<HTMLInputElement>('input[type="file"]');
const fileInputList = [...imageFileInputs];

selectedOptionList.forEach(categoryId =>
formData.append('categoryIds', categoryId.id.toString())
);
formData.append('title', writingTitle);
formData.append('content', deleteOverlappingNewLine(writingContent));
formData.append('imageUrl', contentImageHook.contentImage);
writingOptionList.forEach((option, index) => {
serverVoteInfo && formData.append(`postOptions[${index}].id`, option.id.toString());
formData.append(`postOptions[${index}].content`, option.content);
formData.append(`postOptions[${index}].imageUrl`, option.imageUrl);
});
formData.append('deadline', addTimeToDate(time, baseTime));

fileInputList.forEach((item: HTMLInputElement, index: number) => {
Copy link
Collaborator

Choose a reason for hiding this comment

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

PR의 상세한 설명 덕분에 이해하는데 큰 도움이 되었습니다 💯💯💯

Comment on lines 5 to 24
export const checkValidationPost = (
categoryList: Option[],
title: string,
content: string,
optionList: any[],
time: Time
) => {
if (categoryList.length < 1) return '카테고리를 최소 1개 골라주세요.';
if (categoryList.length > 3) return '카테고리를 최대 3개 골라주세요.';

if (title.trim() === '') return '제목은 필수로 입력해야 합니다.';

if (content.trim() === '') return '내용은 필수로 입력해야 합니다.';

if (optionList.length < 2) return '선택지는 최소 2개 입력해주세요.';
if (optionList.length > 5) return '선택지는 최대 5개 입력할 수 있습니다.';
if (optionList.some(option => option.content.trim() === '')) return '선택지에 글을 입력해주세요.';

if (Object.values(time).reduce((a, b) => a + b, 0) < 1) return '시간은 필수로 입력해야 합니다.';
};
Copy link
Collaborator

Choose a reason for hiding this comment

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

optionList를 any말고 아래의 타입으로 변경하는 것은 어떠세요?

export const checkValidationPost = (
  categoryList: Option[],
  title: string,
  content: string,
  optionList: { content: string }[],
  time: Time
) => {
  if (categoryList.length < 1) return '카테고리를 최소 1개 골라주세요.';
  if (categoryList.length > 3) return '카테고리를 최대 3개 골라주세요.';

  if (title.trim() === '') return '제목은 필수로 입력해야 합니다.';

  if (content.trim() === '') return '내용은 필수로 입력해야 합니다.';

  if (optionList.length < 2) return '선택지는 최소 2개 입력해주세요.';
  if (optionList.length > 5) return '선택지는 최대 5개 입력할 수 있습니다.';
  if (optionList.some(option => option.content.trim() === '')) return '선택지에 글을 입력해주세요.';

  if (Object.values(time).reduce((a, b) => a + b, 0) < 1) return '시간은 필수로 입력해야 합니다.';
};

Comment on lines +16 to +17
const changedTime =
time.day === MAX_DEADLINE ? { day: MAX_DEADLINE - 1, hour: 23, minute: 59 } : time;
Copy link
Collaborator

Choose a reason for hiding this comment

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

꼼꼼하시네요 🔥

Comment on lines 40 to 44
ref={(ele: HTMLInputElement) => {
if (contentInputRefList.current) {
contentInputRefList.current[index] = ele;
}
}}
Copy link
Collaborator

Choose a reason for hiding this comment

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

contentInputRefList 초기값이 [] 빈 배열이여서 항상 true로 나오기 때문에 if문은 삭제해도 좋을 것 같습니다

image

Copy link
Collaborator

Choose a reason for hiding this comment

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

contentInputRefList.current.push(ele)를 하면 index를 삭제할 수 있을 것 같아요

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

const handleButtonClick = (e: MouseEvent<HTMLButtonElement>) => {
    e.preventDefault();
    contentInputRefList.current && contentInputRefList.current[index].click();
  };

버튼 클릭 시 Input 버튼을 누르는 것과 동일하게 처리하기 위해서 index가 필요할 것 같습니다ㅠ
일단 두겠습니다!

Copy link
Collaborator

Choose a reason for hiding this comment

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

현재 라벨과 파일 인풋이 연결되어 있어서 handleButtonClick 이벤트가 없어도 작동을 하는데요 추가하신 이유가 궁금합니다

fe-리뷰완

const id = optionId.toString();

const handleButtonClick = (e: MouseEvent<HTMLButtonElement>) => {
e.preventDefault();
inputRef.current && inputRef.current.click();
contentInputRefList.current && contentInputRefList.current[index].click();
Copy link
Collaborator

Choose a reason for hiding this comment

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

contentInputRefList.current 는 삭제해도 좋을 것 같아요

  const handleButtonClick = (e: MouseEvent<HTMLButtonElement>) => {
    e.preventDefault();
    contentInputRefList.current[index].click();
  };

Comment on lines 1 to 3
export const deleteOverlappingNewLine = (text: string) => {
return text.replace(/(\n{2,})/g, '\n');
};
Copy link
Collaborator

Choose a reason for hiding this comment

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

정규표현식을 이용하신 부분 멋있어요 🔥🔥🔥

Comment on lines +10 to +12
return (
DEADLINE_OPTION.find(option => JSON.stringify(option.time) === stringTime)?.name ?? '사용자지정'
);
Copy link
Collaborator

Choose a reason for hiding this comment

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

오브젝트 비교를 stringify로 하셨군요! 배워갑니다 👍👍

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

그냥 비교하니 주소값으로 비교해버려서 ㅎㅎㅎㅎ
깊은 비교를 하려면 이렇게 해야 하더라구요 하하

@@ -26,10 +26,16 @@ export const HeaderButton = styled.button`
export const Wrapper = styled.div`
display: grid;
grid-template-columns: 1fr;
justify-items: center;
Copy link
Collaborator

Choose a reason for hiding this comment

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

수아 덕분에 justify-items라는 속성을 공부할 수 있었어요 🔥

@github-actions
Copy link

github-actions bot commented Sep 12, 2023

⚡️ Lighthouse report!

Category Score
🟠 Performance 52
🟠 Accessibilty 89
🟠 SEO 85
🟠 PWA 89
Category Score
🟢 First Contentful Paint 0.7 s
🔴 Largest Contentful Paint 4.9 s
🔴 Total Blocking Time 2,250 ms
🟢 Cumulative Layout Shift 0
🟠 Speed Index 3.7 s

@Gilpop8663
Copy link
Collaborator

PostForm 내부의 ContentImageSection 과 게시글 작성 옵션에서 이미지 업로드 컴포넌트에서 아래의 이벤트는 없어도 되겠습니다

  const handleButtonClick = (e: MouseEvent<HTMLButtonElement>) => {
    e.preventDefault();
    contentInputRef.current && contentInputRef.current.click();
  };

       <S.Button
            type="button"
            $isVisible={!!contentImage}
            aria-label="본문 이미지 업로드"
             onClick={handleButtonClick} << 요부분이요
          >

fe-리뷰완

Gilpop8663 and others added 21 commits September 19, 2023 14:57
* feat: (#556) lazy import 설정 및 트리쉐이킹 설정

* feat: (#556) 로그인, 투표 통계, 회원정보 입력 페이지 lazy import 적용

* feat: (#556) 번들 이름 매번 바뀌도록 변경 및 수정되었던 코드 복구

* feat: (#556) Suspense 코드 복구

---------

Co-authored-by: jero_kang <81199414+inyeong-kang@users.noreply.github.com>
* feat: (#555) browser-image-compression 설치 및 본문 이미지 훅에 적용

* feat: (#555) 선택지 옵션 사진을 webp로 변환하도록 구현
* refactor: (#513) Report 도메인 코드 가독성 리팩토링

* refactor: (#513) Report 도메인 관련 테스트 코드 리팩토링

* refactor: (#513) Report의 Controller, Service를 컨벤션에 맞춰 클래스명 개선

* refactor: (#513) 전략 패턴 클래스들에 대한 테스트 코드 추가

* refactor: (#513) Transactional 어노테이션 클래스에 붙는 것으로 위치 개선

* refactor: (#513) 닉네임 3회 신고 받은 후 해당 멤버에 대한 닉네임 신고 기록 삭제

* refactor: (#513) 각 신고 전략에 관한 상수는 각 클래스에 두는 것으로 개선

* refactor: (#513) 파라미터가 2개인 메서드의 선언문 개행 되돌리기

* refactor: (#513) deleteByReportTypeAndTargetId 메서드의 테스트 코드 추가

* refactor: (#513) 파라미터 2개인 메서드 선언부 개행 삭제
* chore: (#620) package-lock.json 업데이트

* fix: (#621) 스토리북을 이용하려고 할 때 웹팩 chunk 관련 에러가 나는 것 수정

* style: (#620) 이미지의 가로, 세로 비율에 맞게 이미지를 보여주도록 수정

* style: (#620) 게시글 작성 시  선택지 이미지에 적용

* chore: (#620) 변경된 컴포넌트 이름이 적용되어 있지 않던 스토리북 파일 수정

* style: (#620) 게시글 작성시 본문 이미지에도 적용
* chore: (#619) 리액트 쿼리 캐싱 확인을 위한 세팅

* feat: (#619) 마감된 게시물 상세정보 1시간 캐싱하기

* design: 에러 메세지 컴포넌트 어절 단위로 개행 및 상하 마진 수정

* feat: (#619) 통계 서버데이터 형식을 사용처가 아닌 불러오는 곳에서 형식 변경

* feat: (#619) 통계 페이지 리액트 쿼리로 수정 및 서스펜스, 에러바운더리 적용

* fix: 통계 api msw에서 실서버로 요청 전환

* fix: thead, tbody가 없어서 발생하는 에러 해결

* fix: (#627) 개발서버 오리진 url 수정 (#628)

* style: (#622) 선택지가 왼쪽으로 움직이는 버그 수정

* fix: (#629) https 로컬호스트 오리진 url 추가 (#630)

* feat: (#602) 본문 이미지를 붙여넣기 이벤트로 이미지를 첨부할 수 있도록 구현

* refactor: (#602) 선택지 작성에서 중복되는 업로드 이미지 코드를 리팩터링한 것을 적용

* refactor: (#602) 사용하지 않는 async 제거, 부자연스러운 함수명 변경

* refactor: (#619) 불분명한 변수명 수정

* feat: 열정유저 테이블 내 2개의 api 중 하나라도 로딩/에러 시 테이블 폴백처리

* refactor: (#619) 사용하지 않는 useFetch 삭제

* feat: (#619) 통계 페이지 에러바운더리/ 서스펜스 범위 수정

- 기존: 글 전체 통계에 서스펜스와 에러바운더리 적용, post api에는 에러바운더리만 적용
- 수정: 글 전체 통계와 post Api 한번에 감싸는 서스펜스와 에러바운더리 적용

* refactor: (#619) 서스펜스, 에러바운더리 감싸는 순서를 기존 코드와 통일

- 에러바운더리 안에 서스펜스, 그 안에 api 호출하는 컴포넌트

* feat: 리액트 쿼리 데브 툴 설정

---------

Co-authored-by: lookh <103165859+aiaiaiai1@users.noreply.github.com>
Co-authored-by: Gilpop8663 <wolfye@naver.com>
발급받은 기기에서만 유효한 pem키이기 때문에 git에 올릴 필요가 없음
- 기존: 받은 imageUrl에 http-를 붙여야 image가 보여짐. 반대로 http-를 떼서 수정 api를 보내야 함
- 수정: 서버에서 보내주는 url 그대로 받아서 image를 보이고 수정 api를 보냄
* chore: (#620) package-lock.json 업데이트

* fix: (#621) 스토리북을 이용하려고 할 때 웹팩 chunk 관련 에러가 나는 것 수정

* style: (#620) 이미지의 가로, 세로 비율에 맞게 이미지를 보여주도록 수정

* style: (#620) 게시글 작성 시  선택지 이미지에 적용

* chore: (#620) 변경된 컴포넌트 이름이 적용되어 있지 않던 스토리북 파일 수정

* style: (#620) 게시글 작성시 본문 이미지에도 적용
* refactor: (#512) 게시글 댓글 도메인 리팩토링

* refactor: (#512) 테스트 엔티티 저장 유틸 클래스 구현

* refactor: (#512) 게시글 도메인 리팩토링

* refactor: (#512) 게시글 DTO 중복 제거 및 리팩토링

* refactor: (#512) 게시글 게스트 조회 기능에 대한 레포지토리 리팩토링

* refactor: (#512) 게스트 게시글 기능 리팩토링

* refactor: (#512) 게시글 조회 관련 레포지토리 리팩토링

* refactor: (#512) 게시글 조회 관련 애플리케이션 로직 리팩토링

* refactor: (#512) 게시글 조회 관련 API 리팩토링

* refactor: (#512) 사용하지 않는 클래스 제거

* refactor: (#512) 게시글 쿼리 기능을 위한 부가 클래스 구현

* refactor: (#512) 게시글 도메인 리팩토링

* refactor: (#512) 게시글 쿼리 관련 레포지토리 기능 구현

* refactor: (#512) 블라인드 게시글 조회 예외 처리

* refactor: (#512) 이미지 파일명 생성 기능 구현

* refactor: (#512) 이미지 저장 및 삭제 기능 구현

* refactor: (#512) 게시글 댓글 블라인드 예외 처리

* refactor: (#512) 게시글 작성, 수정, 삭제 로직 리팩토링

* refactor: (#512) 게시글 작성, 수정, 삭제 API 리팩토링

* chore: (#512) 코드 컨벤션 정리

* refactor: (#512) 게시글 요청, 응답 형식 수정

* refactor: (#512) 게시글 도메인 수정

* refactor: (#512) 요청, 응답 수정에 따른 변화 수정

* refactor: (#512) 게시글 수정 로직 개선

* refactor: (#512) 요청 파일 크기 제한 설정

* refactor: (#512) sequence가 필요한 메서드에서 sequence에 의존하도록 수정

* refactor: (#512) 코드 컨벤션에 맞게 name 속성 제거

* refactor: (#512) 게시글 옵션 예외 분리

* refactor: (#512) 임의의 url로 수정

* refactor: (#512) 람다식 컨벤션 수정

* refactor: (#512) enum 컨벤션 수정

* refactor: (#512) 변수명 수정

* refactor: (#512) 쿼리, 커맨드 트랜잭션 방식 명시

* refactor: (#512) early return 방식으로 수정

* refactor: (#512) 메서드 체이닝 방식으로 수정

* refactor: (#512) early return 방식으로 수정

* refactor: (#512) 게시글에 대한 신고 삭제 기능 구현

* refactor: (#512) 기존 게시글 옵션이 아닌 경우 예외 던지도록 수정

* refactor: (#512) 예외 타입 네이밍 수정

* refactor: (#512) 투표 수 int -> long 전환

* refactor: (#512) 게시글 옵션 ID 검증 로직 분리

* refactor: (#512) 충돌 해결하면서 터지는 테스트 수정

* refactor: (#512) 코드 컨벤션 수정

* refactor: (#512) hikari, JpaTransactionManager 로그 제거

* feat: (#512) tomcat 설정 환경변수 추가

* feat: (#512) 게시글 리팩토링
# Conflicts:
#	backend/src/main/java/com/votogether/domain/post/controller/PostGuestController.java
#	backend/src/main/java/com/votogether/domain/post/controller/PostGuestControllerDocs.java
#	backend/src/main/java/com/votogether/domain/post/dto/request/post/PostOptionCreateRequest.java
#	backend/src/main/java/com/votogether/domain/post/dto/response/post/PostOptionVoteResultResponse.java
#	backend/src/main/java/com/votogether/domain/post/entity/Post.java
#	backend/src/main/java/com/votogether/domain/post/service/PostCommandService.java
#	backend/src/main/java/com/votogether/domain/post/service/PostGuestService.java
#	backend/src/main/java/com/votogether/infra/image/ImageName.java
#	backend/src/main/java/com/votogether/infra/image/LocalUploader.java
#	backend/src/test/java/com/votogether/domain/post/controller/PostGuestControllerTest.java
#	backend/src/test/java/com/votogether/domain/post/service/PostGuestServiceTest.java
#	backend/src/test/java/com/votogether/domain/post/service/PostQueryServiceTest.java
#	backend/src/test/java/com/votogether/infra/image/LocalUploaderTest.java
#	frontend/src/components/PostForm/index.tsx
#	frontend/src/components/optionList/WrittenVoteOptionList/WrittenVoteOption/style.ts
@chsua chsua merged commit 27a78d3 into dev Sep 19, 2023
2 checks passed
@woo-chang woo-chang deleted the feat/#541 branch September 19, 2023 09:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment