728x90
반응형

최종발표회를 앞둔 마지막 날

발표때는 들어가지 않지만 admin 관련해서 신고엔티티 및 기능을 작성했다.

아예 새로 만드는 기능이기에 팀원들과 튜터님의 도움을 받아서

ERD작성하고 다대다 관계 등을 고민하며 기능을 만들 수 있었다.

생각한대로 완벽하게 만들지는 못했지만,

처음부터 만드는 작업이 흥미롭고 재미있었다.

 

import {
  Entity,
  Column,
  PrimaryGeneratedColumn,
  OneToMany,
  ManyToOne,
  JoinColumn,
  CreateDateColumn,
  UpdateDateColumn,
  DeleteDateColumn,
} from 'typeorm';
import { Post } from '../../post/entities/post.entity';
import { User } from '../../user/entities/user.entity';
import { Comment } from '../../comment/entities/comment.entity';

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

  @ManyToOne(() => User, (reporter) => reporter.reports)
  reporter: User;

  @ManyToOne(() => User)
  @JoinColumn({ name: 'user_id', referencedColumnName: 'id' })
  userId: User;

  @ManyToOne(() => Post)
  @JoinColumn({ name: 'post_id', referencedColumnName: 'id' })
  postId: Post;

  @ManyToOne(() => Comment)
  @JoinColumn({ name: 'comment_id', referencedColumnName: 'id' })
  commentId: Comment;

  @Column()
  description: string;

  @Column({ type: 'varchar', default: 'checking' })
  status: string;

  @Column({ type: 'varchar' })
  type: string;

  @CreateDateColumn({ name: 'created_at' })
  createdAt: Date;

  @UpdateDateColumn({ name: 'updated_at' })
  updatedAt: Date;

  @DeleteDateColumn({ name: 'deleted_at' })
  deletedAt: Date;
}
728x90
반응형
728x90
반응형

1. 문제

ban.entity.ts를 새로 만들어서 데이터베이스에 추가하려 했으나 에러문구 발생

 

[Nest] ERROR [TypeOrmModule] Unable to connect to the database. Retrying (1)... 
TypeORMError: Entity metadata for User#bans was not found. 
Check if you specified a correct entity object and 
if it's connected in the connection options.

 

2. 시도해본 것들

엔티티..메타데이터..not found.. 자주봤던 것 같다.

일단 entity를 만들고, .env에 있는 DATABASE_SYNC=true로 만들면 자동으로 동기화가 될 거라 생각했다.

 

3. 해결과정

그러나!! 이 모든 것이 진행되는 config의 typeorm.config.service.ts에서 Ban 엔티티를 추가해줘야한다.

@Injectable()
export class TypeOrmConfigService implements TypeOrmOptionsFactory {
  constructor(private readonly configService: ConfigService) {} //필수

  createTypeOrmOptions(): TypeOrmModuleOptions {
    return {
      type: 'mysql',
      host: this.configService.get<string>('DATABASE_HOST'),
      port: this.configService.get<number>('DATABASE_PORT'),
      username: this.configService.get<string>('DATABASE_USERNAME'),
      password: this.configService.get<string>('DATABASE_PASSWORD'),
      database: this.configService.get<string>('DATABASE_NAME'),
      namingStrategy: new SnakeNamingStrategy(),
      logging: Boolean(this.configService.get<string>('DATABASE_logging')),
      synchronize: Boolean(this.configService.get<string>('DATABASE_SYNC')), // 배포 시 false
      entities: [
        Collection,
        CollectionItem,
        Comment,
        CommentLike,
        CommentUserTag,
        Post,
        Hashtag,
        Image,
        PostLike,
        PostUserTag,
        Restaurant,
        User,
        Follow,
        Reports,
        Ban,
      ],
    };
  }
}

 

4. 알게 된 점

엔티티 작성, DATABASE_SYNC=true 뿐만아니라 config에서

entities에도 엔티티가 추가됬음을 알려줘야 한다.

728x90
반응형
728x90
반응형

1. 문제

신고엔티티에서 신고당한사람(reportedId)는

유저,게시물,코멘트와 조인할 필요가 있다.

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

  @ManyToOne(() => User, (reporter) => reporter.reports)
  reporter: User;
  @Column()
  reporterId: number;

  // 다대다 테이블? 릴레이션 테이블? 아니면 3개 노가다?
  @Column()
  reportedId: number;

  @Column()
  description: string;

  @Column({
    type: 'enum',
    enum: ['checking', 'rejected', 'completed'],
    default: 'checking',
  })
  status: 'checking' | 'rejected' | 'completed';

  @Column({ type: 'enum', enum: ['user', 'post', 'comment'] })
  type: 'user' | 'post' | 'comment';

  @CreateDateColumn({ name: 'created_at' })
  createdAt: Date;

  @UpdateDateColumn({ name: 'updated_at' })
  updatedAt: Date;

  @DeleteDateColumn({ name: 'deleted_at' })
  deletedAt: Date;
}


2. 시도해본 것들

조인을 안하고 기능을 완성해보려고 했다.

그런데 기능을 만들면서 마지막 신고내역을 구현할때,

reportedId를 통해서 유저,코멘트,포스트 정보와 조인을 해서 정보를 가져와야 했다.

그럴때 우리는 어떻게 해야할지 고민이 되었다.

 

릴레이션 테이블

이 부분이 감이 오지않아서 튜터님에게 물어봐야 할 것 같다. (한번도 안해본 테이블)

 

다대다 테이블

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

  @ManyToOne((type) => Collection, (collection) => collection.collectionItems)
  @JoinColumn({ name: 'collection_id' })
  collection: Collection;

  @ManyToOne((type) => Restaurant, (restaurant) => restaurant.collectionItems)
  @JoinColumn({ name: 'restaurant_id' })
  restaurant: Restaurant;

  @ManyToOne((type) => Post, (post) => post.collectionItems)
  @JoinColumn({ name: 'post_id' })
  post: Post;
}

 

기존에 진행했던 테이블

 

각각 테이블과 조인

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

  @Column()
  reportedId: number;

  @Column()
  type: string;

  @ManyToOne(() => User)
  @JoinColumn({ name: 'reportedId', referencedColumnName: 'id' })
  user: User;

  @ManyToOne(() => Post)
  @JoinColumn({ name: 'reportedId', referencedColumnName: 'id' })
  post: Post;

  @ManyToOne(() => Comment)
  @JoinColumn({ name: 'reportedId', referencedColumnName: 'id' })
  comment: Comment;
}

단순하면서 무식해보일 것 같은 방법

 

3. 해결과정

해결방법은 찾지 못했다.

내일 튜터님에게 상담받으면서 어떤 방향으로 나가야 할지 고민하고 정해야겠다.

 

4. 알게 된 점

엔티티간의 관계를 정의하는것이 이렇게 복잡할 줄 몰랐다....

팀원들과 엔티티 얘기하면서 배운 점도 많아서 좋았다.

728x90
반응형
728x90
반응형

공부방법 => 한번 쭉 읽고 생각나는대로 적기 (모르면 컨닝하기)

                     + 추가 정보 기입하기


1. HTTP METHOD에서 GET과 POST에 대해 설명해주세요.

더보기

Get은 가져온다는 개념이고, Post는 수행한다는 개념으로 받아들이면 쉽습니다.

 

GET - 클라이언트에서 서버로부터 어떠한 리소스를 요청할때 사용되는 method

          요청된 값은 프론트에서 변경되지 않고 사용된다.

       + get메소드는 주로 데이터를 읽거나 검색할 때 사용되며, 모든 필요한 데이터를 URL에 포함하여 요청합니다.

 

POST - 리소스를 생성/업데이트 하기 위해 서버에 데이터를 보내기 위해 사용되는 메서드

             서버 상의 데이터 값을 바꾸기 위해 사용되는 method

          + POST메소드는 주로 리소스를생성하거나 업데이트를 하기 위해 서버에 데이터를 보내는데 사용합니다.

 

주요 차이점은 get은 브라우저에 기록되지만, post는 기록되지 않음

GET은 요청을 전송할때 URL 주소 끝에 파라미터로 포함되어 존송되며, 이 부분을 쿼리스트링이라 부릅니다.

POST는 요청 데이터를 Body에 담겨 있기 때문에 링크 정보를 가져올 수 없습니다.

 

--------------

 

GET은 캐시 될 수 있지만 POST는 캐시되지 않습니다.

GET은 브라우저 기록에 남지만 POST는 남지 않습니다.

GET은 북마크에 추가할 수 있지만, POST는 추가할 수 없습니다.

GET은 데이터 길이에 제한이 있지만 POST는 제한이 없습니다.

 

PUT : 목적 리소스 모든 현재 표시를 요청 payload로 바꿉니다.

PATCH: 리소스의 일부분만 수정하는 데 쓰입니다.

 

2. HTTP 상태 코드

더보기
  • 200 : OK 요청이 성공적으로 되었습니다.
  • 201 : Created 요청이 성공적이며 새로운 리소스가 생성되었습니다.
  • 400 : Bad Requrest 서버가 요청의 구문을 인식하지 못했습니다.
  • 401 : Unauthorized 이 요청은 인증이 필요합니다.
  • 403 : Forbidden 서버가 요청을 거부합니다.
  • 404 : Not Found 서버가 요청한 페이지를 찾을 수 없습니다. (API가 잘못됬을때 자주 겪음)
  • 500 : Internal Server Error 서버가 오류를 발생하여 요청을 수행할 수 없습니다.

 

3. 프로세스와 스레드의 차이

더보기
  • 프로세스 : 운영체제로부터 자원을 할당받은 작업의 단위
  • 스레드 : 프로세스에 포함된 개념이며, 프로세스가 할당받은 자원을 이용하는 실행 흐름의 단위

 

4. RDB(Relational Database)와 NoSQL(Not Only SQL)의 차이

더보기

RDBMS(관계형 데이터베이스)는 정해진 스키마가 존재하고, NoSQL은 정해진 스키마가 없다는 것이 큰 차이

 

RDB의 장점으로는 데이터의 분류, 정렬, 탐색 속도가 빠르며, 스키마가 명확하게 정의되어 있어

데이터의 무결성을 보장합니다. 하지만 단점으로는 스키마가 정적이기 때문에 데이터가 유연하지 못하며,

시스템이 커질 경우 JOIN문이 많은 복잡한 쿼리가 만들어질 수 있습니다.

NoSQL(Not Only SQL)의 장점으로는 스키마가 없기 때문에 유연하며 자유로운 데이터 구조를 가질 수 있습니다.

또한 데이터 분산이 용이하며 성능 향상을 위한 Scale-up 뿐만 아니라 Scale-out도 가능합니다. 하지만 단점으로는 데이터 중복이 발생할 수 있으며 중복된 데이터가 변경될 경우 수정을 모든 컬렉션에서 수행해야 합니다.

 

5. DB 인덱스 사용 시 장점

더보기

DB 인덱스를 잘 사용하면 데이터를 검색하는 시점에 성능 차이에 큰 영향을 미침

대용량 데이터를 담고 있는 DB 테이블에서는 필요한 데이터를 빨리 찾기 위해 인덱스가 필요함

 

DB 인덱스의 가장 큰 장점은 데이터 검색 속도의 향상입니다. 인덱스는 DB 내 저장된 데이터의 주소를 가지고 있기 때문에 원하는 데이터를 빠르게 찾을 수 있습니다.

반면 단점은 인덱스는 데이터 조회(SELECT)를 제외한 모든 동작, 즉 INSERT/UPDATE/DELETE 성능에 영향을 미칩니다. 이러한 동작으로 인해 인덱스를 걸어둔 컬럼의 데이터가 바뀌면 인덱스 테이블의 수정도 필요하기 때문에 데이터의 삽입/수정/삭제 작업이 두 번 이루어지게 됩니다 . 인덱스는 DB 내 저장된 데이터의 "주소"를 갖고 있기 때문에 별도의 공간에 저장하므로 추가 저장 공간이 필요합니다 .

 

6. 데이터베이스 정규화

더보기

 데이터베이스의 중복을 최소화하고, 데이터의 무결성을 유지하기 위한 기술

정규화의 목표는 테이블 간에 중복된 데이터의 존재를 허용하지 않는 것

실무에서는 보통 1,2,3 정규화까지만 다룸

 

제1정규화 : 테이블의 모든 컬럼은 원자값(분해할 수 없는 값)을 가져야합니다.

제2정규화 : 테이블의 모든 컬럼은 기본키에 완전 함수적 종속을 만족해야합니다.

제3정규화 : 테이블의 모든 컬럼은 기본키에 이행적 종속을 만족하지 않아야 합니다.

(이행적 종속이라는 것은 A -> B, B -> C가 성립할 때 A -> C가 성립되는 것을 의미)

 

7. 데이터베이스 비정규화

더보기

정규형 테이블을 비정규형으로 바꾸는 걸 의미함(중복허용)

정규화 시 테이블이 여러 개로 나눠지므로, 조인 연산을 사용하는 경우가 빈번해짐

일반적으로 조회에 대한 처리 성능이 중요할 경우, 부분적으로 비정규화를 고려  

 

8. 데이터베이스 인젝션(Database Injection)

더보기

데이터베이스 인젝션은 웹 페이지의 입력을 통해 SQL문에 악의적인 코드를 삽입하는 기법

이는 데이터베이스를 파괴할 수 있으며, SQL 인젝션은 가장 일반적인 웹 해킹 기법

 

공격자는 SQL 인젝션을 통해 일반적으로 검색할 수 없는 데이터를 검색할 수 있습니다.

이는 다른 사용자의 데이터 또는 애플리케이션이 접근할 수 있는 다른 데이터를 포함할 수 있습니다.

많은 경우 공격자는 이 데이터를 수정하거나 삭제하여 콘텐츠 또는 동작에 영구적인 변경을 일으킬 수 있습니다.

 

9. ORM이 편하고 좋은데, SQL을 알아하는 이유

더보기

ORM(Object-Relational Mapping)은 객체와 관계형 데이터베이스의 데이터를 자동으로 매핑시켜주는 프레임워크. ORM을 사용하면 SQL 쿼리가 아닌 직관적인 코드(메소드)로 데이터를 조작할 수 있어서 가독성이 좋습니다.

ORM이 편리하고 좋지만, SQL을 알아야 하는 이유는 ORM이 RDBMS에 대한 종속성을 줄여주지만,

개발자가 높은 RDBMS 지식을 요구합니다. ORM을 사용하는 경우에도 SQL 쿼리의 성능 최적화와 같은 작업이 필요

 

10. RDBMS와 NoSQL은 언제 사용하는 것이 좋을까요?

더보기

RDBMS는 정형화된 데이터를 저장하고 관리하는데 적합합니다. 

반면 NoSQL은 비정형화된 데이터를 저장하고 관리하는데 적합합니다.

 

11. Node.js가 싱글스레드이지만 여러가지 병렬작업이 되는 이유

더보기

Node.js는 싱글 스레드이지만, worker_threads 모듈을 사용하여 여러 작업을 동시에 처리할 수 있습니다. worker_threads 모듈을 사용하지 않더라도 Node.js 애플리케이션에서 병렬 처리가 가능합니다.

코드를 별도의 노드 프로세스로 분기하거나 자식 프로세스를 생성하여 멀티 코어 머신에서

처리 병렬성을 얻을 수 있습니다 . 이를 통해 여러 작업을 동시에 처리할 수 있습니다.

 

12. 세션과 쿠키의 차이점

내가 썼던 세션과 쿠키 정보 : https://pyoja.tistory.com/119

더보기

쿠키 = 그냥 옮기는 시스템 매개체

토큰 = 서버가 기억하는 이상하게 생긴 텍스트 (ID카드처럼 서버에게 보여줘야 함)

JWT = 정보를 갖고 있는 토큰. DB없이 검증가능!

세션 = 요청받으면 서버에서 DB에 있는 데이터를 전달

 

세션과 쿠키의 가장 큰 차이점은 상태 정보의 저장위치. 쿠키는 클라이언트에 저장하고, 세션은 서버에 저장합니다.

보안면에서는 세션이 우수하고, 요청 속도는 쿠키가 세션보다 빠릅니다.

쿠키와 세션에 대한 자세한 설명

더보기

쿠키와 세션은 HTTP의 특징이자 약점을 보완하기 위해 사용됩니다. HTTP는 비연결성(Connectionless)과 비상태성(Stateless)의 특징을 가지고 있습니다. 즉, 클라이언트가 서버에 요청을 보내면 서버는 클라이언트에게 요청에 맞는 응답을 해 준 뒤 접속을 끊습니다. 이로 인해 상태 정보를 유지하지 않습니다.

 

쿠키와 세션은 이러한 HTTP의 특징을 보완하기 위해 사용됩니다.
쿠키는 클라이언트 측에 저장되는 작은 데이터 파일로, 서버가 클라이언트의 웹 브라우저에 저장합니다.

반면 세션은 서버 측에 저장되며, 클라이언트는 세션 ID만 가지고 있습니다.

 

쿠키와 세션의 가장 큰 차이점은 사용자의 정보가 저장되는 위치입니다.

쿠키는 서버의 자원을 전혀 사용하지 않으며, 세션은 서버의 자원을 사용합니다.

보안 면에서 세션이 더 우수하며, 요청 속도는 쿠키가 세션보다 더 빠릅니다
.

쿠키와 세션은 각각 장단점이 있습니다. 쿠키는 클라이언트 측에 저장되기 때문에 임의로 고치거나 지울 수 있고, 가로채기가 어렵지 않아 보안에 취약합니다. 반면 세션은 서버 측에 저장되기 때문에 비교적 보안성이 높습니다.
하지만 세션은 서버의 자원을 사용하기 때문에 많은 양의 데이터를 저장하면 서버에 부하가 발생할 수 있습니다.

 

13. http와 https의 차이

더보기

HTTP와 HTTPS의 가장 큰 차이점은 보안입니다. HTTP는 암호화가 전혀 되어 있지 않은 프로토콜이므로 

보안에 취약합니다. 반면 HTTPS는 안전하게 데이터를 주고받을 수 있습니다. 

하지만 HTTPS를 이용하면 암/복호화의 과정이 필요해서 HTTP보다 속도가 좀 느릴 수 있습니다.

 

14. google.com을 쳤을 때 벌어지는 일을 설명해주세요 (이해 못해서 생략)

 

15. 알고 있는 자료구조에 대해 설명해주세요.

더보기
  1. 배열(Array) : 배열은 인덱스(Index)와 인덱스에 해당하는 요소(Element)로 구성된 가장 기본적인 데이터 구조입니다. 길이가 고정되어 생성되며, 인덱스를 통해서 각 요소에 직접 접근할 수 있는 특징이 있습니다.
  2. 연결 리스트(Linked List) : 배열의 추가/삭제 연산에 대한 비효율성을 극복하고자 등장한 데이터 구조입니다.    각 요소는 다음 노드 연결에 대한 정보를 담은 포인터 또는 주소와 함께 노드에 저장됩니다. 단일 연결 리스트, 이중 연결 리스트, 원형 연결 리스트 등의 종류가 있습니다.
  3. 스택(Stack) : 순서가 보존되는 선형 자료구조의 일종으로, LIFO(Last In First Out) 메커니즘을 갖고 있습니다. 데이터를 받는 순서대로 정렬하며, 가장 마지막으로 입력된 것을 순차적으로 가져오는 방법을 갖고 있는 것이 특징입니다.
  4. 큐(Queue): 순서가 보존되는 선형 자료구조의 일종으로, FIFO(First In First Out) 메커니즘을 갖고 있습니다. 데이터를 받는 순서대로 정렬하며, 가장 먼저 입력된 것을 순차적으로 가져오는 방법을 갖고 있는 것이 특징입니다.
  5. 해시 테이블(Hash Table): 해시 테이블은 키(Key)와 값(Value)으로 데이터를 저장하는 자료구조 중 하나로 빠른 검색이 필요할 때 용이합니다. 해시 테이블을 구현하기 위해서는 연결 리스트와 해시 함수(Hash Function)가 필요합니다 .

 

16. 큐와 스택의 차이에 대해 설명해주세요.

더보기

큐(Queue)와 스택(Stack)은 모두 선형 자료구조의 일종입니다. 가장 큰 차이점은 데이터를 처리하는 순서에 있습니다. 스택은 가장 마지막으로 입력된 데이터부터 처리하는 LIFO(Last In First Out) 메커니즘을 갖고 있습니다. 

반면에 큐는 가장 먼저 입력된 데이터부터 처리하는 FIFO(First In First Out) 메커니즘을 갖고 있습니다.

스택은 재귀 알고리즘, 깊이 우선 탐색(DFS), 실행 취소(undo), 웹 브라우저 방문 기록 등에서 사용됩니다. 

큐는 너비 우선 탐색(BFS), CPU 스케줄링, 캐시 구현 등에서 사용됩니다.

따라서 어떤 상황에서 스택을 사용할지, 큐를 사용할지는 문제의 특성과 요구사항에 따라 결정됩니다. 

예를 들어, 가장 마지막으로 입력된 데이터부터 처리해야 하는 경우 스택을 사용하고, 

가장 먼저 입력된 데이터부터 처리해야 하는 경우 큐를 사용합니다.

 

17. 리팩토링에 대해 설명해주세요.

더보기

코드 리팩토링이란 현재 코드의 동작은 그대로 유지하면서 더 이해하기 쉽고, 생각하기 쉽고, 확장하기 쉽게

재구성하는 것입니다. 리팩토링의 목적은 소프트웨어를 보다 이해하기 쉽고, 수정하기 쉽도록 만드는 것입니다.

리팩토링은 겉으로 보이는 소프트웨어의 기능을 변경하지 않습니다.

코드 가독성과 질을 높이기 위한 목적으로 정리(Clean Up)를 한다고 생각해도 됩니다.

리팩토링은 코드의 구조가 망가지는 효과를 누적되지 않게 하며, 중복을 제거함으로써 각각의 작업에 대한 코드가 오직 한 곳에만 있게 할 수 있습니다. 이로 인해 소프트웨어의 디자인이 개선되고,

소프트웨어를 더 이해하기 쉽게 만들며, 버그를 찾도록 도와주고, 프로그램을 빨리 작성하도록 도와줍니다.

 

18. OOP에서 지향하는 바가 무엇일까요?

더보기

OOP (Object-Oriented Programming)은 객체 지향 프로그래밍이며, 프로그래밍 패러다임 중 하나입니다. 

OOP는 데이터와 기능을 객체라는 개념으로 묶어서 프로그래밍하는 방식으로, 코드의 재사용성과 유지보수성을 높이는 것을 지향합니다. OOP의 주요 개념으로는 클래스, 객체, 상속, 캡슐화, 다형성 등이 있습니다.

 

19. JOIN에 대해 설명해주세요.

더보기

JOIN은 SQL에서 두 개 이상의 테이블을 결합하여 하나의 테이블처럼 보이게 해주는 것입니다. 

JOIN에는 여러 종류가 있습니다. INNER JOIN은 두 테이블 모두에 데이터가 존재하는 행에 대해서만 

결과를 가져오는 것입니다. OUTER JOIN은 매칭되는 행이 없어도 결과를 가져오며, 매칭되는 행이 없으면 NULL로 출력합니다. OUTER JOIN에는 LEFT OUTER JOIN과 RIGHT OUTER JOIN이 있습니다

 

20. ORM이란 무엇인가요?

더보기

ORM(Object-Relational Mapping)은 객체와 관계형 데이터베이스의 데이터를 자동으로 매핑시켜주는 프레임워크

ORM은 객체 지향 프로그래밍에서 데이터를 쉽게 조작할 수 있게 해줍니다.

ORM은 객체 지향적인 방법으로 데이터베이스와의 상호작용을 할 수 있도록 도와주며,

Model class를 통해 객체를 만들고 이 객체를 통해 데이터베이스에 접근합니다.

이를 통해 개발자는 SQL문을 직접 작성하지 않고도 데이터베이스를 조작할 수 있습니다.

 

21. hoisting이란?

더보기

호이스팅(Hoisting)은 자바스크립트에서 변수나 함수 선언을 함수 유효 범위(또는 함수 외부의 경우 전역 범위)의

맨 위로 이동하는 메커니즘입니다. 자바스크립트 인터프리터가 변수와 함수의 메모리 공간을 선언 전에

미리 할당하는 것을 의미합니다. var로 선언한 변수의 경우 호이스팅 시 undefined로 변수를 초기화합니다.

이는 자바스크립트 Parser가 함수 실행 전 해당 함수를 한 번 훑어서 필요한 값들을 끌어올리는 것으로,

실제로 코드가 끌어올려지는 것은 아니며 자바스크립트 Parser 내부적으로 끌어올려서 처리하는 것입니다.

 

22. TDZ란?

더보기

TDZ는 Temporal Dead Zone의 약자로, 일시적인 사각지대를 의미합니다. 

스코프의 시작 지점부터 초기화 시작 지점까지의 구간을 TDZ라고 합니다.

이 구간에서 선언 이전에 참조한 변수는 참조 에러가 발생합니다.

 

console.log(x); // ReferenceError: Cannot access 'x' before initialization
let x = 10;

 

23. Closure 함수란?

더보기

클로저(Closure)는 어떤 함수의 내부 함수가 외부 함수의 변수(*프리변수)를 참조할 때, 외부 함수가 종료된 후에도 내부 함수가 외부 함수의 변수를 참조할 수 있도록 어딘가에 저장하는 함수를 의미합니다. 클로저는 일급함수로서 전달할 수 있는 함수인데, 함수를 이리 저리 전달해서 사용할 때, 그 함수가 처음 정의될 때의 Context를 그대로 가지고 있을 필요가 있는 경우가 있습니다

클로저의 예제

더보기

function outer() {
  let x = 10;
  function inner() {
    console.log(x);
  }
  return inner;
}

let closure = outer();
closure(); // 10

 

24. 실행컨텍스트가 무엇인가요?

더보기

실행 컨텍스트(Execution Context)는 코드가 실행되는 환경을 제공하고 변수의 유효 범위를 관리합니다. 

실행 컨텍스트는 스코프 체인, 호이스팅, 클로저 등 다양한 핵심적인 내용들을 이해하기 위해서는

필수적으로 알아야 하는 개념입니다.

 

25. Node.js란 무엇이며, 사용하는 이유는 어떻게 되나요?

더보기

Node.js는 Chrome V8 JavaScript 엔진으로 빌드된 JavaScript 런타임입니다. Node.js는 확장성 있는 네트워크 애플리케이션(특히 서버 사이드) 개발에 사용되는 소프트웨어 플랫폼입니다. 작성 언어로 자바스크립트를 활용하며 Non-blocking I/O와 단일 스레드 이벤트 루프를 통한 높은 처리 성능을 가지고 있습니다.

Node.js를 사용하는 이유 중 하나는 자바스크립트를 동일하게 사용해서 서버단 로직을 처리할 수 있다는 점입니다. 새로운 언어를 습득하지 않고도 자바스크립트를 활용해 서버기술을 빨리 개발/응용할 수 있습니다.

또한 개발이 빠르고 쉽습니다. 서버 설치부터 화면 띄우는 것까지 금방 처리됩니다.

 

 

 

 

 

728x90
반응형
728x90
반응형

1. 문제

프론트에서 북마크 토글시 제공하는 반환값


2. 시도해본 것들

프론트와의 소통이 중요했다. 제가 어떤 값을 보내드리면 되죠? 라고 물었더니

컬렉션 id, name, hasPost: true & false값이 필요하다고 했다.

hasPost는 데이터베이스에 없는 컬럼인데 어떻게 반환해야 할까?

 

3. 해결과정

프론트 담당자에게 Res에 대한 대답을 듣고나니

코드 짜기는 수월했다. 일단 해당 컬렉션에 포스트가 있는지, 없는지

체크하는 hasPost가 제일 고민이었는데 생각보다 간단했다.

그냥 만들어서 전달해주면 되었다.

 

/*
    ### 23.03.29
    ### 표정훈
    ### 북마크 토글 API🔥
    */
  async selectBookmark(postId: number, collectionId: number, userId: number) {
    try {
      //해당 포스트가 각각 컬렉션에 존재있는지 없는지만 알면 된다.
      //⭐ 필요정보 : [{id:36, name: "", hasPost: false}] ⭐
      const collectionItem = await this.collectionItemRepository.findOne({
        where: {
          post: { id: postId },
          collection: { id: collectionId },
        },
        relations: ['collection'],
      });

      if (collectionItem) {
        return {
          id: collectionItem.collection.id,
          name: collectionItem.collection.name,
          hasPost: true,
        };
      } else {
        //Post가 없을땐 해당 북마크만 찾아서 아이디와 이름값 반환
        const collection = await this.collectionRepository.findOne({
          where: { id: collectionId },
        });
        return {
          id: collection.id,
          name: collection.name,
          hasPost: false,
        };
      }
    } catch (err) {
      console.error(err);
      throw new InternalServerErrorException(
        'Something went wrong while processing your request. Please try again later.',
      );
    }
  }

 

 

4. 알게 된 점

가상컬럼을 만들어야 하는가?

어떠한 어려운 방법을 써야하는가? 등등 많은 고민을 했는데

프론트분의 원하는 대답을 듣고 목표가 정해지니

조금씩 생각을 정리하니 금방 답을 얻었다.

return에 그냥 hasPost : true를 담아서 보낼 수 있다니 정말 간단하게 해결 할 수 있어서 뿌듯했다.

 

728x90
반응형
728x90
반응형

1. 문제

북마크에서 기본으로 제공하는 기본 북마크에 포스트를 저장하는 기능


2. 시도해본 것들

우선 기본 북마크는 어떻게 찾을 것인가?

회원가입하자마자 모두에게 주어지는 기본 북마크이므로

제일 먼저 생성된 북마크이다.


3. 해결과정

findOne 메서드로 찾으면 가장 먼저 나오는 것이 기본 북마크였다.

 

/*
        ### 23.03.28
        ### 표정훈
        ### 기본 북마크에 포스팅 더하기
        */
  async basicCollectionPlusPosting(postId: number, userId: number) {
    try {
      //본인의 첫번째 북마크(모든 게시물)의 id를 찾는다.
      const basicBookmark = await this.collectionRepository.findOne({
        where: {
          user_id: userId,
        },
        select: {
          id: true,
        },
      });

      const existingItem = await this.collectionItemRepository.findOne({
        where: {
          post: { id: postId },
          collection: { id: basicBookmark.id }, // 기본 북마크의 ID를 사용하여 조건문을 지정
        },
      });

      if (existingItem) {
        return; // 이미 있다면 종료
      }

      const collectionItem = this.collectionItemRepository.create({
        post: { id: postId },
        collection: { id: basicBookmark.id }, // 기본 북마크의 ID를 사용하여 컬렉션 아이템을 생성
      });

      await this.collectionItemRepository.save(collectionItem);
      return collectionItem;
    }

 

4. 알게 된 점

막연하게 기본 북마크는 어떤 방법으로 찾을 수 있을까 생각했는데

알고리즘 문제처럼 어떠한 방식으로 접근할 수 있을까 생각하다보면 쉽게 접근 할 수 있는 문제였다.

 

 

728x90
반응형
728x90
반응형

1. 문제

회원정지시 3일,7일,30일로 하려고 할때, 자동화하여

정지 풀어주는 로직을 고민하고 있었다.


2. 시도해본 것들

처음에는 타이머를 생각했으나, 서버가 꺼지면 자동으로 초기화되는 등

실제 서비스 제공하기는 어렵다.


3. 해결과정

타이머의 대체제를 찾던 도중 'node-cron'이라는 기능을 알게 되었다.

실제 서비스에서도 사용할 수 있고, 사용하는 방법도 간단했다.

 

4. 알게 된 점

타이머와 node-corn의 차이점을 알게 되었고,

corn의 경우, 서비스 코드에서 작성하는것이 아니라

app.module.ts 또는 main.ts 같은 곳에 작성해야 서비스가 사용될때마다 주기적으로

이벤트를 줘서 작동시킬 수 있다.

 

import * as cron from 'node-cron';
import { AdminModule } from './apis/administrator/admin.module';
import { AdminService } from './apis/administrator/admin.service';

@Module({
  imports: [
    ConfigModule.forRoot({ isGlobal: true }),
    TypeOrmModule.forRootAsync({
      useClass: TypeOrmConfigService,
    }),

    AuthModule,

  ],
})
export class AppModule implements OnModuleInit {
  constructor(private adminService: AdminService) {}
  onModuleInit() {
    cron.schedule('* * * * *', async () => {
      await this.adminService.liftBanOnExpiredUsers();
    });
  }
}
728x90
반응형
728x90
반응형

이번 주 알게 된 점

금요일에 작성한 TIL의 내용으로

TypeORM으로는 복잡한 쿼리문을 작성하기 어려웠다.

TypeORM 쿼리빌더를 사용하니 손쉽게 해결했다.

효율성을 생각하니 쿼리빌더를 열심히 공부해야겠다는 생각이 들었다.

 

이번주 목표 달성 여부

북마크 세부기능 모두 완성

마이리스트 세부기능 모두 완성

 

다음주 목표 세우기

최종프로젝트 발표 준비

728x90
반응형

+ Recent posts