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

경북대 FE_김민주 6주차 과제 Step 3, 4 #107

Open
wants to merge 64 commits into
base: joojjang
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
f9e9639
chore: 지난 주 코드 복사
joojjang Jul 31, 2024
7d833f3
design(Header): 테두리 선 추가
joojjang Jul 31, 2024
f87a9f5
design(Header): 로고 이미지의 최대 크기 지정 - 헤더 영역 벗어나지 않게
joojjang Jul 31, 2024
a754bf1
feat(Header): 요청 API 드롭다운 추가
joojjang Jul 31, 2024
520a64d
feat(Header): API 옵션 로컬 스토리지로 관리
joojjang Jul 31, 2024
153fea2
feat(Login/SignUp): id -> 이메일 변경, 이메일 형식 검사 로직 추가
joojjang Jul 31, 2024
384e491
refactor(useValidateEmail): 이메일 유효성 검사 모듈화
joojjang Jul 31, 2024
4f3f4f9
chore(Login/SignUp): 쫌쫌따리
joojjang Jul 31, 2024
ad19080
feat(SignUp): 회원가입 api 구현 (ing)
joojjang Aug 1, 2024
0e2fbcd
feat(API): 요청 URL apiOption에 따라 변경
joojjang Aug 1, 2024
bd09149
feat(SignUp): 회원가입 api 구현
joojjang Aug 1, 2024
377f48f
fix(API): 요청 URL 수정
joojjang Aug 1, 2024
ebc7006
feat(Login): 로그인 api 구현
joojjang Aug 1, 2024
4e37426
feat(storage): emailSessionStorage 추가, 화면에 표시되는 토큰 -> 이메일로 변경
joojjang Aug 1, 2024
65abc4f
refactor(Login): 새로고침 때문에 useNavigate -> window.location 변경
joojjang Aug 1, 2024
cedc740
design(Home): 로그인 안 했을 때 사용자 이름 표시 X
joojjang Aug 1, 2024
34121f5
chore(useGetCategories): 파일명 변경
joojjang Aug 1, 2024
801f922
fix(API): useGetCategories 응답 객체 키 수정, 통신 에러 처리 구문 추가
joojjang Aug 1, 2024
e24f94c
design(CategoryImage): 홈에 카테고리 이미지 비율 조정
joojjang Aug 1, 2024
36aa0fa
fix(API): 상품 상세 api 수정
joojjang Aug 2, 2024
107d363
fix(API): 상품 옵션 api 수정, 응답 객체 키 명 수정
joojjang Aug 2, 2024
2215caf
refactor(storage): apiOption getter, setter 훅
joojjang Aug 2, 2024
4849740
fix(opiOption): 선택된 apiOption이 화면에 계속 나오도록 수정
joojjang Aug 2, 2024
db95b4d
refactor(API): 모든 api 에러 처리 구문 추가, 불필요한 export 삭제
joojjang Aug 2, 2024
86df4cc
style(Wish): 위시 추가/삭제 핸들러 명 변경
joojjang Aug 2, 2024
2f0dba4
feat(API): wish 등록(post) api 구현
joojjang Aug 2, 2024
6f48b07
test(API): useGetProducts 응답 데이터 콘솔에 출력
joojjang Aug 2, 2024
db66d52
design(OptionSection): 위시 버튼 주문 버튼 UI 수정
joojjang Aug 2, 2024
4df9f71
feat(OptionSection): 상품의 옵션 바꿀 수 있도록 드롭다운 UI 추가
joojjang Aug 2, 2024
f308120
feat(OptionSection): 옵션 선택 동작하도록 구현 (orderHistory에 optionId 추가하고 저장)
joojjang Aug 2, 2024
a89b093
feat(apiOption): apiOption 바뀌면 리로드(새로고침)
joojjang Aug 2, 2024
aafcd92
fix(API): useGetProductDetail (상품 상세) suspense에 대한 처리 추가
joojjang Aug 2, 2024
3145859
fix(OptionSection): 선택한 옵션에 따라 CountOptionItem에 옵션명 바뀌도록 수정
joojjang Aug 2, 2024
bbe0fa1
fix(API): postWish (위시 등록) 수정 중
joojjang Aug 2, 2024
f22ffd3
feat(API): 위시 삭제 함수 및 훅 구현
joojjang Aug 2, 2024
2858c15
feat(wish): 위시 등록 api 파라미터 실제 productId로 수정
joojjang Aug 2, 2024
52a07cc
refactor(wish): 위시 api 모듈 분리
joojjang Aug 2, 2024
7ecbba4
HOTFIX(categories): 카테고리 데이터가 배열인지 확인
joojjang Aug 3, 2024
37f2cea
HOTFIX(options): optoins가 배열인지 확인
joojjang Aug 3, 2024
42d4907
HOTFIX(categories): 카테고리 데이터가 배열인지 확인
joojjang Aug 3, 2024
9284b7d
chore(env): 환경변수 빌드되는지 확인
joojjang Aug 3, 2024
4716eea
chore(deploy): deploy script 추가
joojjang Aug 4, 2024
d1b9b76
feat(wish): 위시 post API 로그인 안 한 경우 처리
joojjang Aug 4, 2024
5b7895b
refactor(wish): 사용자가 로그인하지 않기로 선택한 경우, API 요청 미전송
joojjang Aug 4, 2024
334ff6e
fix(OptionSection): 옵션 데이터가 없을 때 UI 수정 (옵션 드롭다운 없이 수량, 주문 버튼 나오게)
joojjang Aug 4, 2024
2023bed
style(usePostWish): 요청 객체 타입 명 수정
joojjang Aug 4, 2024
11ae41a
refactor(useDeleteWish): 위시 삭제 요청 파라미터: 넘버 -> 객체로 변경
joojjang Aug 4, 2024
86710c9
feat(useHandleWish): 위시 핸들러에 삭제 api 요청 추가
joojjang Aug 4, 2024
b8f90a4
feat(useGetWish): 위시 get 훅 구현
joojjang Aug 4, 2024
63c2248
refactor(getWishesPath): URLSearchParams 객체 사용
joojjang Aug 4, 2024
0c3542e
chore(usePostWish): 필요 없는 주석 삭제
joojjang Aug 4, 2024
e20de07
feat(Wish): 위시 페이지에서 훅 호출, 데이터 렌더링
joojjang Aug 4, 2024
88cb4a1
feat(Wish): 위시 삭제 wishId로 하도록 파라미터 넘김
joojjang Aug 4, 2024
d75ca66
refactor(instance): fetchInstance와 initInstance 병합
joojjang Aug 4, 2024
d19342f
refactor(api/hooks): api 별로 디렉토리 분리
joojjang Aug 4, 2024
8151ffe
feat(order): 주문 api 구현
joojjang Aug 4, 2024
9e457a6
fix(order): 오더 옵션id 없을 수도
joojjang Aug 4, 2024
60b224f
design(order): 오더 페이지 GoodsInfo UI 수정
joojjang Aug 4, 2024
23a3c99
docs(README): 기능 구현 사항 및 질답 작성
joojjang Aug 4, 2024
ddefa7a
docs(README): 질답 작성
joojjang Aug 4, 2024
3d3a929
feat(order): 포인트 사용하는 부분 추가
joojjang Aug 4, 2024
221b28c
design(Button): font weight 추가
joojjang Aug 4, 2024
a8b423d
feat(order): 포인트 사용하는 부분 인풋, 전액사용 버튼 추가, 포인트 로직 구현
joojjang Aug 4, 2024
9088f6c
refactor(Layout): 폴더 위치 변경
joojjang Oct 6, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"presets": ["@babel/preset-env", "@babel/preset-react", "@babel/preset-typescript"]
}
59 changes: 59 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
module.exports = {
env: {
browser: true,
es2021: true,
node: true,
},
extends: [
'plugin:@typescript-eslint/recommended',
'airbnb/hooks',
'airbnb-typescript',
'prettier',
'plugin:storybook/recommended',
],
parser: '@typescript-eslint/parser',
parserOptions: {
project: './tsconfig.json',
ecmaFeatures: {
jsx: true,
},
ecmaVersion: 'latest',
sourceType: 'module',
},
plugins: [
'react',
'@typescript-eslint',
'react-hooks',
'json-format',
'simple-import-sort',
'@emotion',
'prettier',
],
rules: {
'react/react-in-jsx-scope': 'off',
'simple-import-sort/imports': 'error',
'simple-import-sort/exports': 'error',
'@typescript-eslint/consistent-type-imports': 'warn',
'@typescript-eslint/no-unused-vars': [
'error',
{
argsIgnorePattern: '^_',
},
],
'import/extensions': ['off'],
'import/no-extraneous-dependencies': ['off'],
'react/jsx-filename-extension': [
'warn',
{
extensions: ['.tsx', '.js', '.jsx'],
},
],
'@typescript-eslint/no-use-before-define': ['off'],
},
ignorePatterns: ['**/build/**/*', '.eslintrc.js', 'craco.config.js'],
settings: {
'import/resolver': {
typescript: {},
},
},
};
27 changes: 27 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js

# testing
/coverage

# production
/build

# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local

npm-debug.log*
yarn-debug.log*
yarn-error.log*

.yaml

.env
3 changes: 3 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/.vscode
/node_modules

8 changes: 8 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"singleQuote": true,
"semi": true,
"tabWidth": 2,
"trailingComma": "all",
"printWidth": 100,
"arrowParens": "always"
}
77 changes: 76 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,76 @@
# react-deploy
# FE 카카오 선물하기 6주차 과제: 배포 & 협업

## 1단계 구현 사항

- [x] 회원 API 구현 (회원가입, 로그인)
- [x] 카테고리 API, 상품 API, 상품 옵션 API 리팩토링 (에러 처리 블록 추가)
- [x] 상품 옵션 기능 추가
- [x] 상품 상세 페이지에서 옵션도 선택할 수 있도록 UI 추가 구현
- [x] 위시 기능 구현
- [x] 위시 GET, POST, DELETE api 구현
DELETE는 비동기 함수는 구현했지만, 요청이 wishId(위시 고유 번호)로 가기 때문에
위시 페이지에서는 요청을 보내고, 상품 상세 페이지에서는 요청을 보내지 않습니다
(상품 상세 페이지에서 삭제 요청을 보내기 위해서는 productId가 필요하다고 생각했습니다).
추후 DTO 수정해야 할 것 같습니다.
- [ ] 주문 API 구현

비동기 통신을 모두 훅으로 만들고 데이터가 필요한 컴포넌트에서 import하여 사용하도록 했습니다.

## 2단계 구현 사항

배포 주소:
http://kakao-gift-deploy.s3-website-ap-southeast-2.amazonaws.com/
우상단 API 선택을 통해 요청 호스트를 바꿉니다.
(개발자 도구 콘솔에서 base url 확인 가능합니다. api 작동하는 것 확인했지만 네트워크 에러가 자주 뜹니다.)

## 3단계 질의응답

### 질문 1.

SPA 페이지를 정적 배포를 하려고 할 때 Vercel을 사용하지 않고 한다면 어떻게 할 수 있을까요?

---

정적 배포 호스팅 서비스로는 Vercel을 제외하고도 Netlify, GitHub Pages, AWS S3, EC2 + Nginx 등이 있습니다.
이번 과제에서는 Vercel과 S3를 사용해보았는데, 그 중 S3에 대해 간략히 설명하겠습니다.

정적 데이터를 담는 버킷인 S3 버킷을 만들고, 빌드한 프로젝트를 이 버킷에 업로드합니다.
CloudFront을 함께 사용하면 CDN으로 사용자와 가까운 서버에서 더 빠른 페이지 응답이 가능하고, 도메인 커스텀이나 HTTPS로 변환도 가능합니다.

### 질문 2.

CSRF나 XSS 공격을 막는 방법은 무엇일까요?

---

**CSRF** (Cross-Site Request Forgery, 사이트 간 요청 위조): 사용자가 의도와 무관한 요청을 서버에 보내게 하거나 상태 변경(수정, 삭제)하게 하는 공격

방어 방법

1. GET 요청과 POST/PUT 요청을 구분합니다. GET은 읽기 전용으로 사용하고, form 태그로 값을 받을 경우 POST를 이용합니다.
2. 요청 전송 시 (서버에서 발급해준) 토큰을 함께 전송합니다. 서버에서는 이 토큰으로 사용자를 인증 후 요청을 처리하도록 합니다.
3. 서버에서 요청의 Referer 헤더를 검증하여 요청이 올바른 출처에서 왔는지 확인합니다. 하지만 이 정보는 조작이 가능하여 다른 방법과 함께 보조적인 수단으로 사용하는 것이 좋습니다.
4. CAPCHA와 같은 추가적인 인증 수단을 사용합니다. 해당 인증을 통과하지 못하면 요청 자체를 막습니다.

**XSS** (Cross-Site Scripting, 사이트 간 스크립팅): 다른 사용자의 브라우저에 악의적인 스크립트를 삽입하여 실행되게 만드는 공격

방어 방법

1. XSS는 사용자의 입력 값(파라미터)에서부터 발생하므로, 입력 값을 인코딩하여 해당 값이 읽히지 않도록 합니다.
특수 문자나 기호를 HTML Entity로 변환하여 전송하는 방법이 있습니다. 이렇게 하면 HTML 태그가 변환되어서 읽히지 않습니다.
2. 출력 값을 인코딩하는 방법도 있습니다. 출력 시 사용자 입력을 HTML, JavaScript, URL 등의 컨텍스트에 맞게 인코딩하여 악성 스크립트가 실행되지 않도록 합니다.

### 질문 3.

브라우저 렌더링 원리에 대해 설명해주세요.

---

브라우저는 HTML, CSS, JavaScript 파일을 파싱하는 등 리소스를 처리하여 화면에 시각적으로 출력합니다.

1. 브라우저는 HTML을 파싱하여 DOM 트리를 만들고, CSS를 파싱하여 CSSOM 트리를 생성합니다.
트리의 각 노드는 HTML 요소입니다.
2. DOM 트리와 CSSOM 트리를 결합하여 렌더 트리를 생성합니다.
3. 레이아웃: 화면에 페인팅할 요소들의 크기나 위치를 계산합니다.
4. 페인팅: 각 노드를 화면에 그립니다.
5. 컴포지팅: 최종적으로 화면을 브라우저에 띄웁니다.
Comment on lines +69 to +76
Copy link

Choose a reason for hiding this comment

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

리페인트, 리플로우 같은 사이드이펙트에 대해서도 같이 알아두시면 좋을 것 같아요~

27 changes: 27 additions & 0 deletions craco.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
const path = require('path');

module.exports = {
webpack: {
alias: {
'@': path.resolve(__dirname, 'src'),
},
},
jest: {
configure: {
setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
preset: 'ts-jest',
testEnvironment: 'jsdom',
moduleNameMapper: {
'^@/(.*)$': '<rootDir>/src/$1', // 절대 경로 설정
},
transform: {
'^.+\\.(js|jsx)$': 'babel-jest', // Babel을 사용하여 JS 파일을 변환
'^.+\\.(ts|tsx)$': 'ts-jest',
},
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
transformIgnorePatterns: [
'/node_modules/(?!(axios)/)', // axios 모듈을 변환 대상으로 포함
],
},
},
};
1 change: 1 addition & 0 deletions jest.setup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import '@testing-library/jest-dom';
Loading