반응형

[프로젝트 생성하기]

https://honeystorage.tistory.com/252?category=784116 

 

[개발환경 세팅하기]

https://honeystorage.tistory.com/253?category=784116 

 

에 이어서

실제 개발에는 필수적이라고 할수있는

절대경로, 스타일 모듈 및 에디터 설정을 진행할것이다.

 

키워드는

babel-plugin-module-resolver

styled-components

prettier

3가지 이다.

 

먼저, styled-components를 통해 개발하기 위한 설정을 해주고

아주 작은 컴포넌트를 만들어볼것이다.

 

1. styled-components

설치를 해보자.

npm i --save styled-components
npm i --save-dev babel-plugin-styled-components @types/styled-components @types/styled-components-react-native

이제, babel.config.js에 코드 한줄만 추가해보자.

module.exports = {
  presets: ['module:metro-react-native-babel-preset'],
  plugins: ['babel-plugin-styled-components'], // 이것 추가
};

 

자, 설정은 모두 끝났다.

이전에 react를 다뤄봤다면 어렵지않게 

styled-components로 컴포넌트를 하나 만들어본다.

 

// App.tsx

const CustomBox = styled.View`
  width: 200px;
  height: 200px;
  background-color: red;

  // display: flex; - react-native의 View는 기본이 flex이다.
  align-items: center;
  justify-content: center;
`;

const CustomText = styled.Text`
  font-size: 16px;
  color: white;
  text-align: center;
`;

const App = () => {
  ...
  
  return (
    ...
      <CustomBox>
        <CustomText>제가 직접 만들었어요</CustomText>
      </CustomBox>
    ...
  )
}

 

화면에서 확인해보자

 

 

이런 이미지가 잘 나타났는가?

그렇다면  styled-components 개발환경 세팅은 끝났다고 볼수있다.

 

 

그런데 우리는 App.tsx 에서만 개발을 진행할수는 없다.

작은 단위로 구조화해서 개발을 진행해야하는데

그러려면 절대경로 설정은 필수라고 할수있다.

"../../../../../" 와 같은 지옥을 맛보기 싫다면

 

(다만, 규모가 작은 프로젝트에서

절대경로 설정에 어려움을 겪는다면 

굳이 설정할 필요는 없다고 생각한다.

그 시간에 빨리 작업을 마치는것도

개발 센스라고 본다.)

 

2. 절대경로 세팅하기

babel-plugin-module-resolver 를 설치하자.

npm i --save-dev babel-plugin-module-resolver

 

https://www.npmjs.com/package/babel-plugin-module-resolver

여기 가이드라인이 제법 잘 나와있다

따라해 보자.

루트 경로 아래에 src 폴더를 하나만든 뒤

// babel.config.js 파일을 만들고 아래와 같이 설정

{
  "plugins": [
    [
      "module-resolver",
      {
        "root": ["."],
        "alias": {
          "@components": "./src/components",
        },
        "extensions": [".ios.ts",".android.ts", ".ts", ".ios.tsx", ".android.tsx", ".tsx", ".jsx", ".js", ".json"]
      }
    ]
  ]
}
// tsconfig.json
{
  "compilerOptions": {
    ...
    "baseUrl": "./src",
    "paths": {
      "@components": [
        "./components/*"
      ],
    }
    ...
  }
}

 

빨간줄이 나온다거나 컴파일 에러가 보여질수 있습니다.

열려있는 스크립트 파일은 모두 닫고,

실행중인 런타임도 종료한뒤

npm start --reset-cache

위 명령어로 다시 런타임을 실행하면

정상적으로 절대경로 사용이 가능해진것을

확인해볼 수 있습니다.

 

그렇다면 이전에 작성한 코드를 옮겨봅니다.

./src/components/sample.tsx 파일을 만들고

해당 파일로 이전에 작성한 CustomText, CustomBox 코드를 옮깁니다.

// ./src/components/sample.tsx

import styled from 'styled-components/native';

const CustomBox = styled.View`
  width: 200px;
  height: 200px;
  background-color: red;

  // display: flex; - react-native의 View는 기본이 flex이다.
  align-items: center;
  justify-content: center;
`;

const CustomText = styled.Text`
  font-size: 16px;
   color: white;
   text-align: center;
`;

export { CustomBox, CustomText };
// App.tsx

import { CustomBox, CustomText } from '@components/sample';

const App = () => {
  ...
  
  return (
    ...
      <CustomBox>
        <CustomText>제가 직접 만들었어요</CustomText>
      </CustomBox>
    ...
  )
}

 

정상적으로 실행된다면

개발을 위한 환경을 얼추 다 갖추었다.

 

 

이제 팀원간 코드를 어떻게 작성할지

어떤 스타일 가이드에 따라 작성할지를

세팅하는  ./prettierrc 를 작성할 차례이다.

 

기본파일로 ./prettierrc.js가 생성되어있는데

원하는대로 커스텀해보자

 

// 예시
module.exports = {
  bracketSpacing: false,
  jsxBracketSameLine: true,
  singleQuote: true,
  trailingComma: 'all',
  arrowParens: 'avoid',
  semi: true,
  useTabs: false,
  tabWidth: 4,
  printWidth: 120,
};
반응형
반응형

지난편에서는

프로젝트를 생성해보았다

 

[ React-Native 가이드 - (1) 프로젝트 생성하기 ]

https://honeystorage.tistory.com/252?category=784116 

 

아쉽게도

생성된 프로젝트는 바로 실행되지는 않는다

android나 ios에 맞는 설정들을 진행해주어야한다.

 

0. 준비물

1) JDK (sdk) - https://www.oracle.com/java/technologies/javase/javase-jdk8-downloads.html

2) git - https://git-scm.com/book/ko/v2/%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0-Git-%EC%84%A4%EC%B9%98

3) Android Studio - https://developer.android.com/studio?gclid=Cj0KCQjwxdSHBhCdARIsAG6zhlUyhNLs6BwGLaUaNyCMdvN1e1ZiIt8RQCTBJLKMdxWDSi4nJZawgQsaArAREALw_wcB&gclsrc=aw.ds

4) Xcode (ios 개발용 - mac os에서만 가능)

5) npm, node

위 다섯가지 항목중 한개라도 설치되지 않은것이 있다면 먼저 설치를 진행해주어야한다.

 

1. Android 프로젝트 세팅

먼저, project/android/ 위치에

local.properties 라는 파일을 만들어줄것이다.

해당 파일에는

(mac os)
sdk.dir = /Users/USER_NAME/Library/Android/sdk

(window)
sdk.dir = C:\\Users\\USER_NAME\\AppData\\Local\\Android\\sdk

둘중에 자신의 os 맞는 코드를 한줄 적어주면 된다.

 

또한, android sdk 와 관련하여 간단한 설정을 해주어야한다.

(mac os 기준)

// .zshrc가 이미 있을 경우
open ~/.zshrc

// .zshrc가 없을경우
touch ~/.zshrc

// 맽 밑줄에 아래와 같은 내용 추가
export ANDROID_SDK=/Users/<USER_NAME>/Library/Android/sdk
export PATH=/Users/<USER_NAME>/Library/Android/sdk/platform-tools:$PATH

(저장 및 닫기)

// 스크립트 반영을 위해 터미널에서 아래의 명령어 실행
source ~/.zshrc

 

그러면 이제 실행을 위한 준비는 모두 되었다

 

 

안드로이드 시뮬레이터를 실행하거나  

pc에 안드로이드 디바이스를 연결한 뒤

npm run android

** 안드로이드 시뮬레이터(에뮬레이터) **

android-studio에서 설치가능하다.

프로젝트를 생성하거나 그런 작업은 할필요없다.

알맞는 android 버전을 가진 시뮬레이터를 생성만하면 된다.

 

** 안드로이드 디바이스 세팅 **

(simulator가 아닌 on-device 테스트 하기 위해서는 아래의 세팅이 필수)

1. 설정 > 휴대전화 정보 > 소프트웨어 정보 (이동)
2. 빌드번호를 5회 ~ 7회 연타
3. 개발자 옵션 활성화
4. 설정 > 개발자 옵션 (이동)
5. 화면켜짐 상태유지 On
6. USB 디버깅 On

 

 

2. Ios 세팅

다음은 애플의 ios 환경세팅이다.

시뮬레이터가 이미 설치되어있다면 다소 작업이 간단하다.

시뮬레이터가 없다면 xcode에서 simulator를 먼저 설치하자

 

설치되어있다면 시뮬레이터를 실행

(ios는 안드로이드와 달리 on-device 개발을 진행하는것이 어렵다.

시뮬레이터로 개발하고 배포전 testFlight을 통해 on-device 테스트를 해야한다.)

 

npm run ios

 

ios는 비교적 간단하게 실행해볼수있다.

 

 

 

다음 편에서는

개발을 진행하기위한 필수 세팅으로 볼수있는

 

에디터 환경 설정 + 절대경로 잡기 + 스타일모듈 붙이기 (styled-components)

 

위 3가지를 진행할것이다.

반응형
반응형

회사생활을 하다보니

회사 상황에 따라 개발을 하게되곤 하는대요

 

최근에는 1-2년정도는

react + typescript 환경에서 웹개발을 했었습니다.

 

이번에 다시 react-native를 통해

개발을 할일이 생겨서

과거에 했던것들을 전부 까먹은

지금같은 상황은 반복하지 않기위해

 

가장 많이 쓰이는 환경 세팅 및 기능을

일목요연하게 정리해볼 예정입니다.

 

1. 프로젝트 생성하기

2. 개발환경 세팅하기

3. 개발을 위한 절대경로, 스타일 모듈 및 에디터 설정하기

4. firebase를 통해 push 알림 발송하기

5. Android 배포하기

6. IOS 배포하기

반응형
반응형

next.js를 next install 하여

 

out 폴더를 그대로 배포하면 

 

새로고침 후 index페이지로 이동된다거나

 

~~~/register 와 같이 페이지에 접속했을때도 index페이지가 보여지는 등의 이슈가 발생한다

 

이를 해결하기 위해서는

 

node 서버에서 next.js앱을 실행해주어야한다.

 

node server 설정은

 

const { application } = require('express');
const express = require('express');
const next = require('next');

const dev = process.env.NODE_ENV !== 'production';
const nextApp = next({ dev });
const handle = nextApp.getRequestHandler();

nextApp
    .prepare()
    .then(() => {
        const app = express();

        app.get('*', (req, res) => {
            return handle(req, res);
        });

        app.listen(3000, err => {
            console.log('>>> server is ready on port 3000');
        });
    })
    .catch(err => {
        console.log(err);
        process.exit();
    });

 

이렇게 간단히 할수있고

 

실행은

 

node server.js 이다

 

pm2를통해 무중단 배포를 할때는

 

// package.json

"start": node server.js

 

// 실행

pm2 start npm --name 'next' -- start

반응형
반응형

< 3탄 - 결제 플로우가 어떻게 되는가 >

 

이전 글들을 못보신 분들을 위해 앞선 글들의 링크를 제공합니다.

< 1탄 - 프롤로그 >

https://blog.self-made.cloud/240?category=752264 

< 2탄 - Code 먼저 공개합니다. >

https://blog.self-made.cloud/241?category=752264

 

 

이니시스 결제모듈은

웹 버전과 모바일 버전의 API가 각각 다르게 제공됩니다.

사용해보니 모바일 버전이 나중에 따로 제작된것같네요.

 

아무튼 제공되는 API가 다르니

두가지를 나눠서 설명할 예정입니다.

 

먼저, 웹 버전의 플로우는 이와같습니다.

1. 클라이언트에서 서버로 상품 및 주문번호 요청
2. 서버에서 주문 상품을 가지고 주문을 생성, 주문 번호를 반환
3. 클라이언트에서 서버로부터 전달받은 주문 번호를 가지고 결제 폼을 서버로 요청
4. 서버에서 결제를 진행하기위한 데이터들을 클라이언트로 반환
5. 클라이언트에서 서버로 이니시스 결제모듈 요청 (팝업형태)
6. 서버에서 이니시스 결제모듈 반환
7. 클라이언트에 팝업 모듈이 열림 + 이때부터 팝업 모듈 상태를 주기적으로 체크
8. 사용자 액션에 따른 처리 (1. 팝업을 닫음, 2. 팝업에서 결제 요청)
  8-1. 닫은경우 팝업 열람전 페이지 유지 혹은 기타 처리
  8-2. 팝업에서 결제요청한 경우 서버로 요청이 전송됨 + 팝업이 닫힘
9. 서버에서 요청 받은 정보들을 통해 결제요청 처리 및 데이터 저장
10. 팝업 모듈이 닫힌게 체크되면 결제요청 완료 페이지로 이동
11. 클라이언트에서 서버로부터 결제 정보를 호출하여 사용자에게 보여줌

 

모바일 버전의 플로우

1. 클라이언트에서 서버로 상품 및 주문번호 요청
2. 서버에서 주문 상품을 가지고 주문을 생성, 주문 번호를 반환
3. 클라이언트에서 서버로부터 전달받은 주문 번호를 가지고 결제 모듈을 실행함
4. 사용자 액션에 따른 처리 (1. 팝업을 닫음, 2. 팝업에서 결제 요청)
  4-1. 팝업을 닫은 경우, 결제 실패 페이지로 보내거나, 기존의 페이지로 돌려보냄
  4-2. 결제 요청을 완료한 경우, 서버로 요청이 전송됨
5. 서버에서 요청을 처리 및 데이터를 저장하고 결제완료 페이지로 Redirect시킴
6. 클라이언트에서 서버로부터 결제 정보를 호출하여 사용자에게 보여줌
반응형
반응형

< 1탄 - 프롤로그 >

웹,앱 등의 서비스에서 광고 수익외에

직접적인 수익을 창출하려면 결제연동을 필수적으로 하게됩니다.

그 과정에서 어려움을 겪게되는대요.

 

주로 그 원인은

PG사들이 제공하는 가이드라인이

부실하기 때문입니다.

 

사실 부실할 수 밖에 없은 이유가있죠.

이제는 너무나도 다양해진 개발 환경에 

모두 대응되는 가이드라인을 제공할 수 없기 때문입니다.

 

이번에 React 프로젝트에 결제연동을 하다보니

react와 같은 CSR에 대해서는 가이드라인이 부실함은 물론

관련 자료도 매우 부족함을 알게되었습니다.

 

미약하지만

아임포트 같은 서비스없이

KG이니시스 결제모듈 연동에 성공하여 정보를 공유하고자합니다.

 

다룰 내용은

Client : React 

server : node js

PG: inicis
결제수단 : 가상계좌 ( 다른 결제수단도 PG사와 제휴만 맺으면 해당 방법으로 얼마든지 응용가능해보입니다.)

 

해당 상황에 해당하시는분들에게

많은 도움이 됐으면 합니다.

감사합니다.

반응형
반응형

프로젝트를 진행하다보면

 

점차 규모가 커져서 상대경로로 작업하는데 어려움이 찾아오곤 한다.

 

따라서, 절대경로로 작업을 하고싶을때가 오는데

 

두가지 설정해줄것들이 있다. 

 

1. 절대경로로 표기해도 경로를 자동완성 해줄  "jsconfig.json"

2. 빌드 후에도 해당 경로를 올바르게 파싱해줄 "webpack.config.js"

 

여기서는 jsconfig.json의 설정을 살펴본다

 

아래 링크에서 예제를 확인해볼 수 있다.

 

https://code.visualstudio.com/docs/languages/jsconfig

 

jsconfig.json Reference

View the reference for jsconfig.json.

code.visualstudio.com

 

 

파일경로가

App
- src
  - index.js
  - screens
    - main
      - introduce.js
      - team.js
      - contact.js
    - about.js
  - components
    - common
      - table
        - row.js
        - item.js
- public
  ...

이렇게 되어있을때, team.js에서 row.js를 import 한다고 가정해보자.

import {} from '../../components/common/table/row'

 

지금은 뎁스가 깊지않아 어렵지 않네? 어쩌피 자동완성 지원해주는데 그냥 쓸까? 싶기도 하겠지만

방심은 금물

금방 프로젝트 구조는 복잡해지고말게 분명하다.

 

// jsconfg.json

{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"]
    }
  }
}

이렇게 간단한 파일 하나만 App 프로젝트 밑에 추가해주면

import {} from '@/components/common/table/row';

이런식으로 작성하여도  vscode가 자동완성을 지원해준다.

반응형
반응형

클라이언트 코드를

EC2에서 관리 및 배포하곤 했었는데

사실 용량도 많이 차지하고 좋은 방법은 아니라고 생각했다.

 

더 빠른 전달속도와 더 쉬운 프로젝트 관리를 위한 방법을 찾던중

CloudFront + Route53+ S3 + ACM(for SSL)
조합을 발견했다.

 

처음해보는 사람이라도 쉽게 할수있고,

효과는 눈이 번쩍일정도로 뛰어난것같다.

 

이에 대해 고민하던 나와 다른 분들을위해

위 조합을 이용하는 방법을 상세하게 공유하고자 한다.

 

1. S3

1-1) 먼저, 시작은 S3에서부터다

1-2) React 프로젝트가 있다면 빌드후 생성된 파일들을 S3에 올릴것이다.

1-3) S3 -> 버킷 만들기

1-4) 주의사항은 모든 퍼블릭 액세스 차단을 해제시킬것 (사이트는 누구나 접근가능해야하니까요)
1-4-1) 버킷 만들기
1-5) 버킷을 만들고나면 객체 탭에다가 빌드후 생성된 파일들을 드래그다운하여 업로드한다.
1-6) 다음, 권한 탭에서 버킷 정책을 생성해준다
1-6-1) 편집 -> 정책 생성기 
1-6-2) Select Type of Policy: S3
1-6-3) Effect: Allow

1-6-4) Principal: *

1-6-5) Aws Service: S3

1-6-6) Actions: GetObject
1-6-7) ARN: 정책 편집 페이지에 있는 버킷ARN을 복사해 붙여넣는다. 그리고 뒤에 /*을 덧붙인다
1-6-8) ARN 예시: arn:aws:s3:::coke.cola/*
1-7) 속성탭으로 이동한다.
1-7-1) 맨 하단에 정적 웹 사이트 호스팅을 편집
1-7-2) 정적 웹사이트 호스팅 -> 활성화, 유형 -> 정적 웹사이트 호스팅, 인덱스 문서 -> index.html
1-7-3) 변경 사항 저장

여기까지 했으면 S3설정은 끝났다.

심심하다면 index.html의 객체 URL로 접근해보면 접속됨을 확인할 수 있다.

 

이제 누구나 쉽게 접속할수있게 도메인을 설정해주는 것과 좀더 빠른 페이지를 위한 CloundFront 적용이 남았다.

아, 안전한 서비스 제공을 위한 SSL도 필수니까 당연히 진행하는거로


이전 포스팅에서 했던것처럼 ACM(Certificate Manager)을 통해 SSL 인증서를 생성해보자

 

2.  SSL 인증

2-1) ACM (Certificate Manager)에 접속
2-2) 인증서 요청 -> 공인 인증서 요청
2-3) 도메인 이름 사용하고자 하는거로 입력  (S3에 저장한 사이트를 운영하고자하는 사이트 도메인), (구매해둔 도메인은 있다는 가정)

2-4) DNS 검증 -> 태그 설정 (내가 식별을 위한거니까 영문으로 알아볼수 있게 쓰면됨)

2-5) 검토를 하고나서 생성된 정보를 기반으로 Route 53에 해당 CNAME을 등록해주면 됩니다.

 

 

SSL은 간단히 이정도만 해주면 끝입니다.

그러면 잠시 뒤 발급완료 처리가 됩니다.

 

다음 순서는 CloudFront입니다.

S3에서 파일을 제공하는것보다 빠를 뿐아니라, SSL을 연결해주는것도 쉽게 가능합니다.

 

3. CloudFront 설정하기 - 조금 번거로움

3-1) CloudFront 접속 

3-2) Create distribution

3-2-1) Origin Domain 검색 (로딩이 좀 걸립니다) ->  S3 버킷이 나타나면 클릭

3-2-2) Viewer protocol policy: Redirect HTTP to HTTPS

3-2-3) Custom SSL certificate - optional: 이전에 생성해둔거로 지정

3-2-4) Default root object: index.html

3-2-5) Create distribution
3-3) 생성됐다면, 도메인을 설정해줄건데요. 다시 Roue53에 해당 호스팅 영역으로 갑니다.

3-3-1) 레코드 생성 - "A 유형"

3-3-2) 도메인 이름 설정 (2-3과 일치하게)

3-3-3) 트래픽 라우트 대상 -> 별칭 active -> Cloud Front 배포에 대한 별칭 선택 -> 검색란에 CloudFront의 Distribution domain name 이름 검색 및 선택

3-3-4) 3-3-1 ~ 3-3-3의 작업을 한번 더 반복하여 "AAA 유형"도 생성

3-4) 거의 끝났습니다. 다시 Clound Front로 돌아갑니다.

3-4-1) 해당 객체를 Edit

3-4-2) Alternative domain name에 "Add Item" 하여 2-3에서 만든 도메인과 동일하게 입력해줍니다.
3-4-3) 그리고 저장하면 끝

 

자 이제 두근두근 하면서

해당 도메인에 https://로 접속해 봅니다.

 

잘되나요? 잘됐길바라며 여기서 마치겠습니다.

반응형
반응형

서비스를 운영하다보면 아무리 이미지 압축을 잘 하더라도,

이미지 자체가 워낙 큰 파일이라 로드에 시간을 길게 소요하는 경우가 발생합니다.

 

이런 경우를 대비해 이미지 로드에 부가적인 처리를 좀 해주면

멋스럽고 좋은 사용자 경험을 제공할 수 있습니다.

 

간단한 js와 css를 함께 응용해야하는데,

예제 코드들로 살펴보도록 하겠습니다.

 

[ 주요 키워드: classList, Image ]

 

1. 기본 핵심코드

1.1 html

<div class='image-wrapper'>
  <img class='image-thumbnail' src='/no-image.png' alt='이미지' />
</div>

1.2 css

.image-wrapper {
  background-color: #dadada;
  
  &.visible {
    background-color: transparent;
    transition: all 0.25s;
  }
  
  &.visible > .image-thumbnail {
    transform: scale(1);
    opacity: 1;
  }
}

.image-thumbnail {
  transform: scale(0.5);
  opacity: 0;
  
  width: 100%;
  height: auto;
  object-fit: cover;
}

1.3 js

<script>
  const source = "https://t1.daumcdn.net/tistory_admin/static/top/pc/img_common_tistory_200910.png";
  const image = new Image();
  image.setAttribute('src', source);
  image.onload = function() {
    const wrapper_node = document.querySelector('image-wrapper');
    const node = document.querySelector('image-thumbnail');
    
    wrapper_node.classList.add('visible')
    node.src = source;
  }
</script>

 

 

자, 이렇게하면 이미지가 로드된 후에 고급진 이펙트와 함께 이미지가 나타나게됩니다.

가능하다면 no image상태일때 이미지를 설정해줘도 좋겠죠?

 

 

하지만, 이렇게 단일 이미지를 로드할때보다는

여러 이미지를 로드할때 이것은 더욱 빛을 바랍니다.

예를들어,  Youtube의 영상 목록을 불러올때나 와디즈에서 펀딩 목록을 불러올때

image가 로드되는동안 기본 이미지(혹은 배경색)을 보여주다가

이미지가 로드되면 약간의 효과와 함께 이미지를 띄워줍니다.

 

 

이번에는 React 예제로 살펴보겠습니다.

예시의 편의성을 위해 데이터는 어딘가 서버로부터 불러왔다고 가정하겠습니다.

그리고 실제 개발에서 쓸수있도록, 페이지 스크롤에 따라 이미지 로드와 효과 적용을 핸들링 해보도록 하겠습니다.

 

const ImageList = ({ images ) => {
  return (
    <>
    {
      images.map((img, index) => {
        const image = new Image();
        image.load = function() {
          // how...?
        }
        return (
          <div key={"image-item-" + index.toString()} className='image-wrapper>
            <img className='image-thumbnail' alt='썸네일' />
          </div>
        );
      })
    }
    </>
  )
}

 

이전과 비슷한데  React라는 점, 그리고 단일 이미지가 아닌 list라는 부분에서 차이가 발생했습니다.

여기서 어떻게 각기 알맞는 이미지 태그에 이미지를 넣어줄 수 있을까요?

 

여러가지 방법이 있을 수 있지만,

여기서는 React hooks의 useRef를 사용해보도록 하겠습니다.

(최근에, hooks를 좀 익혀보는 중이거든요)

 

[ 주요 키워드: classList, Image, useRef, useEffect ]

 

<script>
import React, { useRef, useEffect } from 'react';

const ImageList = ({ images ) => {
  return (
    <>
    {
      images.map((img, index) => {
        const image_card = useRef(null);
        
        useEffect(() => {
          scorller();
          window.addEventListener('scroll', scroller, false);
          
          return window.removeEventListener('scoll', scroller, false);
        });
        
        const scroller = () => {
          const { classList: classes, offsetTop, clientHeight } = image_card.current;
          
          // 이미 visible 처리된 element는 중복작업 방지 - 쓸데없는 메모리낭비x
          if (classes.contains('visible')) return null;
          
          // 화면 스크롤 높이에따라 element가 노출되고 있는지를 체크
          const visible_timing = window.innerHeight + windwo.scrollY >= offsetTop - (clientHeight / 2);
          
          // scroll 위치까지 고려해서 이미지 로드 처리
          if (visible_timing) {
            const image = new Image();
            image.setAttribute('src', img);
            image.onload = function() {
              const node = image_card.current.querySelector('.image-thumbnail');
              if (node) {
                classes.add('visible');
                node.src = img;
              }
            }
          }
        }
        
        return (
          <div 
            key={'image-item-' + index.toString()} 
            className='image-wrapper'
            ref={image_card}
          >
            <img className='image-thumbnail' alt='썸네일' />
          </div>
        );
      })
    }
    </>
  )
}
</script>

 

이 처럼 React로 이미지 목록을 구현하는 방법을 살펴보았습니다.

어떤가요?

코드가 어렵다거나 하지는 않죠?

생각보다 간단하게 괜찮은 효과를 낼수 있음을 알 수 있습니다.

 

좀 더 나아간다면 ImageCard를 모듈화 하면 더 좋겠죠?

 

 

반응형
반응형

React기반인 서비스를 운영중인 회사의 서비스 페이지에 Fullpage.js + aos를 적용해보았습니다.

아주 쉽고 빠르게 잘 붙었지만

이게 웬걸...

 

로딩만 했다하면 도저히 원인 파악이 어려울 정도의 상황이 발생했습니다.

스크롤 위치가 이상한데 잡히면서 컴포넌트들이 나타나지 않았습니다.

 

aos가 나타나는 trigger에 문제가 있다고 짐작할뿐 대체 왜 이런 현상이 계속되는가...

를 3시간을 추적에 추적을했습니다.

 

그러다 Lazy loading이라는 키워드를 발견했고

서비스페이지만 Lazy loading을 제거했습니다.

 

와우 너무나도 정상적으로 동작..?!

 

이렇게 간단한 이슈인것을 몇시간을 헤맸네요.

Lazy loading을 했을때 왜 해당 이슈가 발생하는지 근본적인 원인에 대해 탐구하는 포스팅을 다음 글에서 이어가도록 하겠습니다.

 

반응형