반응형

지난 주에 19일부터 대회 기념품 배송이 될거라는 안내가 왔었는데 딱 맞춰 19일에 배송이 왔네요.

대회안내 홈페이지에는 져지가 그림으로 되어 있고 색도 녹색이라 별 기대 안했는데 실제 받아본 져지는 너무 맘에 드네요.

오른팔에 충주 그란폰도 대회 엠블럼 왼쪽엔 뭔지 모르겠어요 스폰서인 VSOL인건가... 암튼 나름 예쁜거 같아요.

산티니 져지는 처음 입어보는건데 사이즈가 정말 크게 나오는듯하네요. 저는 아덴바이크나 오스바이크 져지를 주로 입는데 같은 사이즈임에도 산티니가 더 큽니다.  

 

마라톤 대회도 그렇듯 그란폰도 대회도 이런 가방을 많이 주는듯 합니다. 보통은 비닐로 된 경우가 많던데 천으로 되어 있네요. 운동 후 옷 넣어다니기 좋겠어요.

스폰서인 파워풀엑스의 진생 리커버리 크림

파워플렉스인줄 알았는데 파워풀엑스였네요. 몇년전에 박찬호 크림으로 꽤나 유명했던거 같은데 지금 장민호로 모델이 바뀌었네요. 대회 끝나고 발라보는걸로....

 

트렉도 스폰서라고 되있긴 했는데 그냥 실리콘 스포츠 밴드입니다. 굳이?

대회 홈페이지 기념품안내에는 없네요.

역시나 스폰서인 에네스티의 썬스틱과 수딩젤입니다. 그렇다구요.

여행용으로 쓰는걸로

경품권과 배번표, 홀더

배번표는 기록칩이 내장된 플라스틱 형태로 싯포스트에 설치하는 형태로 제공하네요. 양양그란폰도에서는 져지 뒤에 부착해야 해서 옷핀으로 져지를 찔러야 해서 슬펐는데 충주 그란폰도 맘에 듭니다. 물론 양양 그란폰도는 충분히 재밌게 타고 왔습니다.

 

그란폰도 코스 고도표? 큐시트? 자린이에겐 신기한게 많네요. 평지가 거의 어...없는데..... 

 

아직 자린이 인지라 전반기에 양양 그란폰도 대회 메디오 폰도에 참가하고

열심히 타서 충주 그란폰도에 참가하겠다는 나름의 계획을 세웠는데 대회가 코앞으로 다가오니 컷오프 될까 두렵네요.

 

충주 그란폰도는 산티니 져지를 주기 때문에 참가비가 비싼편이에요.

경품으로는 라 스텔비오 산티니 대회 참가권과 왕복 항공권이 메인이고 그외에도 여러가지가 있더라구요. (휠이나 헬멧이 더 받고 싶은데..)

 

작년에는 비가 내려서 메디오폰도로만 진행했던데 올해는 맑은 날을 기대해봅니다.

728x90
반응형
반응형
let { type } = req.params;

위의 코드는 구조 분해 할당 (Destructuring Assignment)을 사용한 것입니다. . 아래는 이에 대한 상세 설명입니다.

 

1. req.params:

  • 이 코드는 Express.js 애플리케이션에서 사용됩니다. 여기서 req는 **요청 객체(request object)**입니다.
  • req.params는 URL에서 **경로 매개변수(route parameters)**를 담고 있는 객체입니다. 이 매개변수들은 일반적으로 경로에서 : 기호로 정의됩니다. 예를 들어:
app.get('/user/:type', (req, res) => {
  // req.params.type은 ':type'의 값을 가집니다
});
  • 경로가 /user/:type일 경우, type은 경로 매개변수가 되며, req.params는 다음과 같은 객체가 됩니다
{ type: 'someValue' }

 

2. 구조 분해 할당 (Destructuring Assignment):

  • { type } 구문은 구조 분해 할당입니다. 이는 객체에서 속성을 추출하는 간편한 방법입니다.
  • 원래는 다음과 같이 작성될 수 있습니다:
let type = req.params.type;

이를 아래와 같이 간략하게 작성할 수 있습니다:

let { type } = req.params;
 
  • 이 코드는 req.params 객체에서 type 속성을 추출하여 새로운 변수 type에 할당합니다.

요약

let { type } = req.params;는 req.params 객체에서 type이라는 매개변수를 추출하여 type이라는 변수에 저장하는 코드입니다. 이는 주로 Express.js에서 URL 경로의 매개변수를 쉽게 접근하기 위해 사용됩니다.

728x90
반응형
반응형

docker-compose ps 실행시 발생할 수 있는 오류

Traceback (most recent call last):
  File "urllib3/connectionpool.py", line 670, in urlopen
  File "urllib3/connectionpool.py", line 392, in _make_request
  File "http/client.py", line 1255, in request
  File "http/client.py", line 1301, in _send_request
  File "http/client.py", line 1250, in endheaders
  File "http/client.py", line 1010, in _send_output
  File "http/client.py", line 950, in send
  File "docker/transport/unixconn.py", line 43, in connect
ConnectionRefusedError: [Errno 61] Connection refused

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "requests/adapters.py", line 439, in send
  File "urllib3/connectionpool.py", line 726, in urlopen
  File "urllib3/util/retry.py", line 410, in increment
  File "urllib3/packages/six.py", line 734, in reraise
  File "urllib3/connectionpool.py", line 670, in urlopen
  File "urllib3/connectionpool.py", line 392, in _make_request
  File "http/client.py", line 1255, in request
  File "http/client.py", line 1301, in _send_request
  File "http/client.py", line 1250, in endheaders
  File "http/client.py", line 1010, in _send_output
  File "http/client.py", line 950, in send
  File "docker/transport/unixconn.py", line 43, in connect
urllib3.exceptions.ProtocolError: ('Connection aborted.', ConnectionRefusedError(61, 'Connection refused'))

 

 

연결 거부라는 메시지가 포함이 되어 있어 혹시나 싶어 docker ps 명령을 실행하니 

Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?

 

위와 같은 메시지가 출력이 되었네요.

 

이전에 docker desktop을 종료시켜 두었는데 다시 실행시키고 docker ps, docker-compose ps 명령을 실행하니 이상없이 실행이 됐습니다.

 

관련 오류를 검색해보면 환경변수같은 다른 이유도 있는 듯 한데 일단 docker가 실행되고 있는지 확인 필수 인거 같습니다.

728x90
반응형
반응형

카시오 리니지의 가격이 생각보다 높아서 그간 보류했던 카시오 흑새치를 구매했습니다.

오리지널 흑새치나 청새치보다 배트맨이나 펩시가 좋을거 같아 고민하다 펩시로 정했습니다.

 

역시 심플한 카시오 시계 박스와 내부 포장이네요.  플라스틱 시계 거치대가 들어있는게 신기했습니다.

에디피스나 지샥 시계 샀을때는 못본거 같은데 말이죠

플라스틱 거치대 아래를 보면 설명서가 들어있습니다. 

 

 

사진이나 유튜브에 올라온 소개 영상보다 실물이 괜찮은거 같습니다. 

 

보호필름을 떼보면 더더욱 맘에 드네요.

펩시를 상징하는 파랑 빨강 베젤 색감도 맘에 듭니다. 

 

티셀 마린다이버와 시티즌 에코질라와 함께 크기를 비교해봤습니다.

티셀 마란다이버는 케이스 사이즈 40mm

카시오 흑새치 케이스 사이즈 44mm

시티즌 에코질라 케이스 사이즈 48mm

티셀보다는 커보이긴 한데 에코질라의 넓은 베젤과 작은 다이얼 때문인지 비슷해 보이네요.

 

러버밴드는 확실히 저렴해 보이지만 지샥의 밴드처럼 뻣뻣할 줄 알았는데 엄청 부드럽네요

하지만 포인트 없이 원컬러인게 맘에 들진않네요. 조만간 줄질을 해야겠어요

 

쿼츠 시계는 초침과 인덱스의 정렬이 잘 맞지 않는 특징이 있는데 로만손의 로레게 보다 인덱스 정렬이 잘 된듯 해요.

 

44mm사이즈 답게 손목에 올리는 꽉 차는 느낌이 있는데 저는 큰 사이즈를 선호해서 부담없고 만족스럽습니다.

 

베젤은 다이버워치 답게 단방향으로만 회전이 되는데 반대방향으로 돌려보면 살짝 움직임이 있네요.

쿼츠시계와 카시오의 저렴한 이미지에 거부감이 없다면 충분히 만조할만한 다이버 시계이지 않을까 싶네요.

728x90
반응형
반응형

Step1: 프로젝트 초기 설정

패키지 관리자는 yarn을 사용였습니다. 

먼저 프로젝트에 대한 새 디렉토리를 만들고 해당 디렉토리로 이동 후  Yarn 프로젝트를 초기화합니다.

mkdir my-project
cd my-project
yarn init -y

 

Step2: 프로젝트 초기 설정

Node.js, TypeScript, Express, TypeORM 및 PostgreSQL에 대한 패키지를 설치합니다.

yarn add express typeorm reflect-metadata pg
yarn add -D typescript ts-node @types/node @types/express

 

1. 'yarn add express typeorm reflect-metadata pg'

이 명령어는 express, typeorm, reflect-metadata, pg 패키지를 설치합니다. 이 패키지들은 프로젝트의 런타임 의존성으로 설치됩니다.

  • express: Node.js를 위한 빠르고 간단한 웹 프레임워크입니다. HTTP 서버를 쉽게 구축할 수 있게 해줍니다.
  • typeorm: TypeScript와 JavaScript(ES7, ES6, ES5)를 위한 ORM(Object Relational Mapper)입니다. 데이터베이스와 상호작용을 쉽게 해줍니다.
  • reflect-metadata: 메타데이터를 사용하여 객체지향 프로그래밍을 지원하는 데 필요한 라이브러리입니다. TypeORM에서 데코레이터 기능을 사용할 때 필요합니다.
  • pg: PostgreSQL 데이터베이스와 상호작용하기 위한 PostgreSQL 클라이언트입니다.

2. 'yarn add -D typescript ts-node @types/node @types/express'

이 명령어는 typescript, ts-node, @types/node, @types/express 패키지를 개발 의존성으로 설치합니다. 즉, 이 패키지들은 개발 중에만 필요하며, 프로덕션 빌드에는 포함되지 않습니다.

  • typescript: TypeScript 컴파일러입니다. TypeScript 코드를 JavaScript로 변환해줍니다.
  • ts-node: TypeScript 실행 환경입니다. TypeScript 코드를 실행할 수 있게 해줍니다.
  • @types/node: Node.js의 타입 정의 파일입니다. TypeScript에서 Node.js 내장 모듈을 사용할 때 타입 정보를 제공합니다.
  • @types/express: Express의 타입 정의 파일입니다. TypeScript에서 Express를 사용할 때 타입 정보를 제공합니다.

Step3: TypeScript 설정

프로젝트 루트경로에 tsconfig.json 파일을 생성하고 TypeScript 설정을 구성합니다.

{
  "compilerOptions": {
    "target": "ES6",
    "module": "commonjs",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "outDir": "./dist",
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true
  },
  "include": ["src/**/*.ts"],
  "exclude": ["node_modules"]
}

 

Step4: TypeORM 구성 설정

프로젝트 루트경로에 src/data-source.ts 파일을 생성하고 설정을 구성합니다.

import "reflect-metadata";
import { DataSource } from "typeorm";
import { User } from "./entity/User";

export const AppDataSource = new DataSource({
  type: "postgres",
  host: "localhost",
  port: 5432,
  username: "your-username",
  password: "your-password",
  database: "your-database",
  synchronize: true,
  logging: false,
  entities: [User],
  migrations: [],
  subscribers: [],
});

 

'your-username', 'your-password', 'your-database'는 PostgreSQL 설치할때 설정 값으로 바꿉니다

 

Step:5 엔티티 생성

User 및 GenderStatistics 엔티티를 생성합니다.

User 엔티티

import { Entity, PrimaryGeneratedColumn, Column } from "typeorm";

@Entity()
export class User {
  @PrimaryGeneratedColumn()
  id!: number;

  @Column()
  firstName!: string;

  @Column()
  lastName!: string;

  @Column()
  age!: number;
}

 

GenderStatistics 엔티티

import { Entity, PrimaryGeneratedColumn, Column } from "typeorm";

@Entity()
export class GenderStatistics {
  @PrimaryGeneratedColumn()
  num!: number;

  @Column({ nullable: true })
  poll_id!: string;

  @Column({ nullable: true })
  trait!: string;

  @Column({ nullable: true })
  gender!: string;

  @Column({ nullable: true })
  gender_cnt!: number;

  @Column("float", { nullable: true })
  rate!: number;
}

 

rate 필드는 소수점 값으로 저장할 수 있도록 설정하였습니다.

 

Step6: 리포지토리 생성

위의서 만든 각 엔티티에 해당하는 리포지토리를 생성하여 데이터베이스 작업을 처리합니다.

 

userRepository.ts

import { AppDataSource } from "../data-source";
import { User } from "../entity/User";

const userRepository = AppDataSource.getRepository(User);

export const createUser = async (userData: Partial<User>): Promise<User> => {
  const user = userRepository.create(userData);
  return await userRepository.save(user);
};

export const getUserById = async (id: number): Promise<User | null> => {
  return await userRepository.findOneBy({ id });
};

 

genderStatisticsRepository.ts

import { AppDataSource } from "../data-source";
import { GenderStatistics } from "../entity/GenderStatistics";

const genderStatisticsRepository = AppDataSource.getRepository(GenderStatistics);

export const createGenderStatistics = async (data: Partial<GenderStatistics>): Promise<GenderStatistics> => {
  const genderStat = genderStatisticsRepository.create(data);
  return await genderStatisticsRepository.save(genderStat);
};

export const getGenderStatisticsByNum = async (num: number): Promise<GenderStatistics | null> => {
  return await genderStatisticsRepository.findOneBy({ num });
};

 

Step7: 컨트롤러 생성

컨트롤러를 생성하여 HTTP 요청을 처리합니다.

 

userController.ts

import { Request, Response } from "express";
import { createUser, getUserById } from "../repositories/userRepository";

export const createUserHandler = async (req: Request, res: Response) => {
  try {
    const user = await createUser(req.body);
    res.status(201).json(user);
  } catch (error) {
    if (error instanceof Error) {
      res.status(500).json({ message: error.message });
    } else {
      res.status(500).json({ message: "An unknown error occurred" });
    }
  }
};

export const getUserByIdHandler = async (req: Request, res: Response) => {
  try {
    const user = await getUserById(parseInt(req.params.id));
    if (user) {
      res.json(user);
    } else {
      res.status(404).json({ message: "User not found" });
    }
  } catch (error) {
    if (error instanceof Error) {
      res.status(500).json({ message: error.message });
    } else {
      res.status(500).json({ message: "An unknown error occurred" });
    }
  }
};

 

genderStatisticsController.ts

import { Request, Response } from "express";
import { createGenderStatistics, getGenderStatisticsByNum } from "../repositories/genderStatisticsRepository";

export const createGenderStatisticsHandler = async (req: Request, res: Response) => {
  try {
    const genderStat = await createGenderStatistics(req.body);
    res.status(201).json(genderStat);
  } catch (error) {
    if (error instanceof Error) {
      res.status(500).json({ message: error.message });
    } else {
      res.status(500).json({ message: "An unknown error occurred" });
    }
  }
};

export const getGenderStatisticsByNumHandler = async (req: Request, res: Response) => {
  try {
    const genderStat = await getGenderStatisticsByNum(parseInt(req.params.num));
    if (genderStat) {
      res.json(genderStat);
    } else {
      res.status(404).json({ message: "Gender statistics not found" });
    }
  } catch (error) {
    if (error instanceof Error) {
      res.status(500).json({ message: error.message });
    } else {
      res.status(500).json({ message: "An unknown error occurred" });
    }
  }
};

 

Step8: 라우트 설정

userRoutes.ts

import { Router } from "express";
import { createUserHandler, getUserByIdHandler } from "../controllers/userController";

const router = Router();

router.post("/users", createUserHandler);
router.get("/users/:id", getUserByIdHandler);

export default router;

 

genderStatisticsRoutes.ts

import { Router } from "express";
import { createGenderStatisticsHandler, getGenderStatisticsByNumHandler } from "../controllers/genderStatisticsController";

const router = Router();

router.post("/gender-statistics", createGenderStatisticsHandler);
router.get("/gender-statistics/:num", getGenderStatisticsByNumHandler);

export default router;

 

Step9: Express 서버 설정

index.ts

import "reflect-metadata";
import express from "express";
import { AppDataSource } from "./data-source";
import userRoutes from "./routes/userRoutes";
import genderStatisticsRoutes from "./routes/genderStatisticsRoutes";

AppDataSource.initialize().then(() => {
  const app = express();

  app.use(express.json());

  app.use(userRoutes);
  app.use(genderStatisticsRoutes);

  const port = process.env.PORT || 3000;
  app.listen(port, () => {
    console.log(`Server is running on port ${port}`);
  });
}).catch(error => console.log(error));

 

모두 작성 되었다면 yarn dev로 개발 서버를 실행합니다.

 

자바스크립트 계열은 자료를 찾다보면 작성자마다 구조와 형식이 달라 늘 어렵네요.

728x90
반응형
반응형

JavaScript의 옵셔널 체이닝(Optional Chaining) 연산자 ?.는 객체의 속성에 접근할 때, 해당 속성이 존재하지 않더라도 에러를 발생시키지 않고 undefined를 반환하는 유용한 문법입니다. 이는 깊게 중첩된 객체 구조에서 속성에 접근할 때 특히 유용하며, 코드의 가독성과 안전성을 크게 향상시켜줍니다.

왜 옵셔널 체이닝이 필요한가?

객체의 속성에 접근할 때, 종종 해당 속성이 존재하지 않을 가능성을 고려해야 합니다. 예를 들어, 서버로부터 받은 데이터가 항상 동일한 구조를 가지지 않거나, 어떤 필드가 조건에 따라 존재하지 않을 수 있습니다. 이러한 상황에서 안전하게 속성에 접근하기 위해서는 많은 방어적 코드를 작성해야 합니다.

let person = {}; // person 객체는 비어있습니다.

console.log(person.contactInfo.address); // TypeError: Cannot read property 'address' of undefined

 

위의 코드에서 user.address가 undefined이기 때문에 user.address.street에 접근하려고 하면 오류가 발생합니다. 이 문제를 해결하기 위해 보통 아래와 같은 방어적 코드를 작성합니다.

let person = {};

if (person && person.contactInfo && person.contactInfo.address) {
  console.log(person.contactInfo.address);
} else {
  console.log('주소가 없습니다.');
}

 

하지만 이러한 방어적 코드는 가독성을 떨어뜨리고 작성하기 번거로울 수 있습니다. 이를 해결하기 위해 등장한 것이 옵셔널 체이닝 연산자입니다.

옵셔널 체이닝의 사용법

옵셔널 체이닝 연산자를 사용하면 중첩된 객체의 속성에 안전하게 접근할 수 있습니다. 옵셔널 체이닝은 ?. 형태로 사용되며, 해당 속성이 존재하지 않을 경우 undefined를 반환합니다.

let person = {}; // person 객체는 여전히 비어있습니다.

console.log(person?.contactInfo?.address); // undefined

 

위의 코드에서 user.address가 undefined이더라도 오류가 발생하지 않고 undefined를 반환합니다.

옵셔널 체이닝의 다양한 사용 예

1. 객체 속성 접근

let person = {
  fullName: 'John Doe',
  contactInfo: {
    address: '456 Elm St'
  }
};

console.log(person?.contactInfo?.address); // '456 Elm St'
console.log(person?.employment?.position); // undefined

 

2. 함수 호출

옵셔널 체이닝은 함수 호출에도 사용할 수 있습니다. 함수가 존재하지 않을 경우 undefined를 반환합니다.

let person = {
  sayHello: function() {
    console.log('Hi there!');
  }
};

person.sayHello?.(); // 'Hi there!'
person.sayGoodbye?.(); // 아무 일도 일어나지 않음

 

3. 배열 요소 접근

옵셔널 체이닝은 배열의 요소 접근에도 사용할 수 있습니다.

let employees = [{ fullName: 'John Doe' }, { fullName: 'Jane Smith' }];

console.log(employees[0]?.fullName); // 'John Doe'
console.log(employees[3]?.fullName); // undefined

 

결론

옵셔널 체이닝 연산자는 객체의 속성에 안전하게 접근할 수 있게 해주는 강력한 도구입니다. 이를 통해 코드의 가독성을 높이고, 중첩된 객체 구조를 다룰 때 발생할 수 있는 오류를 예방할 수 있습니다. JavaScript 코드에서 옵셔널 체이닝을 적절히 활용하면 보다 안정적이고 유지보수하기 쉬운 코드를 작성할 수 있습니다.

728x90
반응형
반응형

PostgreSQL에서 real, float, float8, double precision, numeric 타입은 모두 부동 소수점 숫자 또는 고정 소수점 숫자를 저장하는 데 사용됩니다. 각각의 차이점과 사용 방법, 그리고 활용 방안에 대해 알아보겠습니다.

데이터 타입 설명

  1. real
    • 설명: 4바이트 단정밀도 부동 소수점 숫자.
    • 정밀도: 약 6자리의 소수점 자릿수를 가짐.
    • 범위: -3.4E+38 ~ +3.4E+38.
    • 사용: 메모리가 제한적이고, 매우 높은 정밀도가 필요하지 않은 경우에 사용.
  2. float (또는 float8)
    • 설명: 8바이트 배정밀도 부동 소수점 숫자. float8은 double precision의 별칭입니다.
    • 정밀도: 약 15자리의 소수점 자릿수를 가짐.
    • 범위: -1.7E+308 ~ +1.7E+308.
    • 사용: 높은 정밀도가 필요한 경우에 사용.
  3. double precision
    • 설명: 8바이트 배정밀도 부동 소수점 숫자.
    • 정밀도: float와 동일, 약 15자리의 소수점 자릿수를 가짐.
    • 범위: float와 동일, -1.7E+308 ~ +1.7E+308.
    • 사용: 매우 높은 정밀도가 필요한 경우에 사용.
  4. numeric (또는 decimal)
    • 설명: 가변 길이의 정확한 숫자. 소수점 이하 자릿수와 전체 자릿수를 지정할 수 있음.
    • 정밀도: 사용자가 지정한 자릿수까지 정확함.
    • 범위: 매우 넓음, 제한이 없다고 볼 수 있음.
    • 사용: 금액 계산 등 매우 높은 정밀도가 요구되는 경우에 사용.

사용 방법과 예제

real

CREATE TABLE example_real ( id serial PRIMARY KEY, value real ); 
INSERT INTO example_real (value) VALUES (3.14), (2.71); 
SELECT * FROM example_real;

float (float8), double precision

CREATE TABLE example_float ( id serial PRIMARY KEY, value float8 ); 
CREATE TABLE example_double_precision ( id serial PRIMARY KEY, value double precision ); 
INSERT INTO example_float (value) VALUES (3.141592653589793), (2.718281828459045); 
INSERT INTO example_double_precision (value) VALUES (3.141592653589793), (2.718281828459045); 
SELECT * FROM example_float; SELECT * FROM example_double_precision;

numeric (decimal)

CREATE TABLE example_numeric ( id serial PRIMARY KEY, value numeric(10, 2) ); 
INSERT INTO example_numeric (value) VALUES (12345.67), (98765.43); 
SELECT * FROM example_numeric;
 

활용 방안

  1. real: 센서 데이터, 간단한 계산 등 정밀도가 크게 필요 없는 경우에 사용합니다.
  2. float (float8), double precision: 과학 계산, 통계 분석 등 높은 정밀도가 필요한 경우에 사용합니다. float8과 double precision은 동일한 타입이므로 동일한 용도로 사용됩니다.
  3. numeric (decimal): 금액, 금융 데이터 등 매우 높은 정밀도와 정확성이 필요한 경우에 사용합니다. 특히, 소수점 이하 자릿수가 중요한 경우 유용합니다.

요약

  • real은 4바이트 단정밀도 부동 소수점으로, 정밀도가 크게 필요 없는 경우에 사용됩니다.
  • float와 double precision은 8바이트 배정밀도 부동 소수점으로, 높은 정밀도가 필요한 경우에 사용됩니다.
  • numeric은 고정 소수점으로, 정밀도가 매우 중요한 경우에 사용됩니다.
728x90
반응형
반응형

1년에 한두번 방문하는 코엑스 팝마트

들리면 무조건 한두개의 피규어를 사서 나오는데 이번에 피치라이엇이라는 시리즈가 맘에 들어 픽업해왔습니다.

 

팝마트 피규어는 가챠처럼 랜덤이라 뜯어서 확인할때 은근 기대와 긴장감이 있습니다. 

하지만 이번에 바로 뜯지 않고 알리익스프레스에서 같은 제품을 구매해 비교해 보기로 했습니다.

알리익스프레스와 테무가 한창 인기가 있어 국내 커머스업계도 긴장하게 했지만 짝퉁 이슈가 많기에 비교가 해보고 싶어졌습니다.

 

그래서 검색 후 바로 구매해 봤습니다.

가격은 요즘 달러가 강세라 환율탓에 국매에서 사는게 더 쌌어요. ㅠㅠ 그런데 만약 짝퉁이라면.......

중국제 피규어는 자체 퀄리티보단 도색이 많이 떨어지는지라 많이 싸보이는 단점이 있죠.

 

왼쪽은 국매 팝마트에서 구매한 상품이고 오른쪽이 알리익스프레스에서 구매한 제품입니다.

 

 

박스는 어디를 봐도 완전 동일했습니다.  알리익스프레스에서 온 제품은 조금 찌그러졌지만요.

박스만 봐선 동일한 제품이라고 판단이 되더라구요. 그래도 내용물은 확인해봐야겠죠.

 

국내에서 구매한 제품은 Frankie The Rhythm이 나왔네요. 원하는 모델은 아니네요.

 

하지만 실물은 맘에 드네요. 퀄리티도 좋고 흔들림없이 균형도 잘 맞았어요. 드럼치는 멤버입니다.제가 원하는건 기타리스트였지만 만족합니다. 고양

 

알리에서 구매한 제품을 은근 기대하게 됐는데 전혀 관심없던 모델이 나왔네요. Frankie The Boss라고 하네요. 

이전에 열어본 아이도 Frankie인데 머리색도 같은걸 보니 포지션만 다르고 같은 아이인가봐요. 

 

도색이 동일하게 잘 되어 있네요. 이 아이는 스텐드 없이 세워야 하기에 균형이 중요한데 제품은 깔끔하게 잘 만들어진거 같아요. 팝마트 제품은 국내판과 동일한 듯 합니다. 결국엔 같은 제품이라는거겠죠. 팝마트는 중국에 본사가 있어서 짝퉁을 팔지는 않는거 같아요. 

 

알리익스프레스에서 가장 저렴한 제품을 구매했지만 결국엔 국내판보다 비싸게 샀다는게 가장 큰 단점이네요.  카드 수수료 무시 못합니다.

 

국내 팝마트에서 제품을 더 이상 구할 수 없다면 알리익스프레스를 이용하는것도 괜찮겠지만 제품이 있다면 국내에서 구매하는걸 추천합니다. 

 

 

728x90
반응형

+ Recent posts