From 5005b9f63084d0e262619ad61d952bc351b129f4 Mon Sep 17 00:00:00 2001 From: Minhyung Cho Date: Fri, 19 Sep 2025 11:58:31 +0900 Subject: [PATCH 1/7] =?UTF-8?q?feat:=20=EA=B0=9C=EB=B0=9C=20=ED=99=98?= =?UTF-8?q?=EA=B2=BD=EC=9D=84=20=EC=9C=84=ED=95=9C=20Docker=20Compose=20?= =?UTF-8?q?=EB=B0=8F=20Nginx=20=EC=84=A4=EC=A0=95=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/kokomen-server/compose.dev.yml | 28 +++++++++++++++++++++++++++ apps/kokomen-server/nginx.conf | 30 +++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 apps/kokomen-server/compose.dev.yml create mode 100644 apps/kokomen-server/nginx.conf diff --git a/apps/kokomen-server/compose.dev.yml b/apps/kokomen-server/compose.dev.yml new file mode 100644 index 00000000..d8ac0388 --- /dev/null +++ b/apps/kokomen-server/compose.dev.yml @@ -0,0 +1,28 @@ +services: + kokomen-nest-server: + build: + context: . + dockerfile: Dockerfile + container_name: kokomen-nest-server + environment: + - NODE_ENV=development + networks: + - dev-kokomen-net + depends_on: + - kokomen-local-redis + nginx: + image: nginx:alpine + container_name: kokomen-nginx + ports: + - "80:80" + - "443:443" + volumes: + - ./nginx.conf:/etc/nginx/nginx.conf:ro + networks: + - dev-kokomen-net + depends_on: + - kokomen-nest-server + +networks: + dev-kokomen-net: + driver: bridge diff --git a/apps/kokomen-server/nginx.conf b/apps/kokomen-server/nginx.conf new file mode 100644 index 00000000..12894a09 --- /dev/null +++ b/apps/kokomen-server/nginx.conf @@ -0,0 +1,30 @@ +events { + worker_connections 1024; +} + +http { + upstream backend { + server kokomen-nest-server:3000; + } + + server { + listen 80; + server_name localhost; + + location / { + proxy_pass http://backend; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + + location /graphql { + proxy_pass http://backend/graphql; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + } +} \ No newline at end of file From ffafef07282644aefb12f60cd0751b2c21d2176e Mon Sep 17 00:00:00 2001 From: Minhyung Cho Date: Fri, 19 Sep 2025 11:59:26 +0900 Subject: [PATCH 2/7] =?UTF-8?q?feat:=20=EC=B9=B4=ED=85=8C=EA=B3=A0?= =?UTF-8?q?=EB=A6=AC=20=EB=8F=84=EB=A9=94=EC=9D=B8,=20=EC=84=9C=EB=B9=84?= =?UTF-8?q?=EC=8A=A4,=20=EB=AA=A8=EB=93=88=20=EB=B0=8F=20=EB=A6=AC?= =?UTF-8?q?=EC=A1=B8=EB=B2=84=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/interview/domains/category.ts | 182 ++++++++++++++++++ .../src/interview/modules/category.ts | 8 + .../src/interview/resolvers/category.ts | 20 ++ .../src/interview/services/category.ts | 14 ++ 4 files changed, 224 insertions(+) create mode 100644 apps/kokomen-server/src/interview/domains/category.ts create mode 100644 apps/kokomen-server/src/interview/modules/category.ts create mode 100644 apps/kokomen-server/src/interview/resolvers/category.ts create mode 100644 apps/kokomen-server/src/interview/services/category.ts diff --git a/apps/kokomen-server/src/interview/domains/category.ts b/apps/kokomen-server/src/interview/domains/category.ts new file mode 100644 index 00000000..b044ca46 --- /dev/null +++ b/apps/kokomen-server/src/interview/domains/category.ts @@ -0,0 +1,182 @@ +import { ObjectType, Field, registerEnumType } from "@nestjs/graphql"; + +export enum CategoryType { + ALGORITHM_DATA_STRUCTURE = "ALGORITHM_DATA_STRUCTURE", + DATABASE = "DATABASE", + NETWORK = "NETWORK", + OPERATING_SYSTEM = "OPERATING_SYSTEM", + JAVA_SPRING = "JAVA_SPRING", + INFRA = "INFRA", + FRONTEND = "FRONTEND", + REACT = "REACT", + JAVASCRIPT_TYPESCRIPT = "JAVASCRIPT_TYPESCRIPT" +} + +registerEnumType(CategoryType, { + name: "CategoryType" +}); + +const CATEGORY_DATA: Record< + CategoryType, + { title: string; description: string; imageUrl: string } +> = { + [CategoryType.ALGORITHM_DATA_STRUCTURE]: { + title: "알고리즘/자료구조", + description: ` + 알고리즘과 자료구조는 문제를 효율적으로 해결하기 위한 핵심 +요소입니다. + 자료구조는 데이터를 저장하고 관리하는 방법을 정의하며, +배열·리스트·스택·큐·트리·그래프 등 다양한 구조를 통해 데이터를 +체계적으로 다룰 수 있습니다. + 알고리즘은 이러한 자료구조를 기반으로 문제를 해결하는 단계별 + 절차를 의미하며, 정렬·탐색·그래프 탐색·동적 프로그래밍 등 다양한 +기법이 존재합니다. + 적절한 자료구조와 알고리즘을 선택하고 구현하는 것은 +프로그램의 성능과 효율성을 결정짓는 중요한 요소입니다. + `, + imageUrl: "kokomen-algorithm-data-structure.png" + }, + [CategoryType.DATABASE]: { + title: "데이터베이스", + description: ` + 데이터베이스는 대량의 데이터를 효율적으로 저장하고 관리하는 +시스템입니다. + 관계형 데이터베이스(RDBMS)는 테이블 구조와 SQL을 기반으로 +데이터를 관리하고, + NoSQL은 비정형 데이터와 대규모 분산 처리를 지원합니다. + 적절한 인덱스 설계는 빠른 데이터 조회와 시스템 성능에 중요한 + 영향을 미칩니다. + `, + imageUrl: "kokomen-database-v2.png" + }, + [CategoryType.NETWORK]: { + title: "네트워크", + description: ` + 네트워크는 여러 컴퓨터와 시스템이 서로 데이터를 주고받을 수 +있도록 구성된 통신 구조입니다. + 네트워크 계층 구조(OSI 7계층, TCP/IP 4계층), 프로토콜(TCP, +UDP, HTTP 등), + 라우팅, 패킷 전송 방식 등 다양한 개념을 이해하는 것이 +네트워크의 핵심입니다. + `, + imageUrl: "kokomen-network-v2.png" + }, + [CategoryType.OPERATING_SYSTEM]: { + title: "운영체제", + description: ` + 운영체제는 하드웨어와 소프트웨어 자원을 효율적으로 관리하고, + 사용자와 응용 프로그램이 시스템을 효과적으로 사용할 수 있도록 +지원하는 핵심 소프트웨어입니다. + 프로세스 및 스레드 관리, 메모리 관리, 파일 시스템, +입출력(I/O) 제어, 그리고 CPU 스케줄링과 같은 기능을 담당합니다. + OS의 구조와 동작 원리를 이해하는 것은 시스템 개발 및 +최적화의 기초가 됩니다. + `, + imageUrl: "kokomen-operating-system-v2.png" + }, + [CategoryType.JAVA_SPRING]: { + title: "자바/스프링", + description: ` + 자바와 스프링은 안정적이고 확장성 있는 백엔드 개발을 위한 +핵심 기술입니다. + 자바는 강력한 객체지향 언어로, 대규모 시스템에서도 일관성과 +유지보수성을 보장합니다. + 스프링은 의존성 주입, 트랜잭션 관리, 보안, 데이터 접근 등 +백엔드 개발에 필수적인 기능을 제공하여 복잡한 애플리케이션을 +효율적으로 구현할 수 있게 합니다. + 특히 스프링 부트를 활용하면 설정과 배포가 간소화되어, 빠르게 + 안정적인 서비스를 개발하고 운영할 수 있습니다. + `, + imageUrl: "kokomen-java-spring.png" + }, + [CategoryType.INFRA]: { + title: "인프라", + description: ` + 인프라는 안정적이고 확장 가능한 서비스를 구축하기 위해 +필수적인 기반 기술을 의미합니다. + 데이터베이스는 서비스의 핵심 데이터를 안전하게 저장하고, +Redis와 같은 인메모리 캐시는 + 빠른 응답 속도를 보장합니다. Kafka와 같은 메시지 큐는 대규모 + 트래픽 환경에서도 안정적인 + 비동기 처리를 가능하게 합니다. 이러한 인프라 기술들은 눈에 +잘 드러나지는 않지만, + 대규모 서비스의 안정성과 성능을 지탱하는 든든한 토대가 되며, + 백엔드 개발자가 반드시 + 이해하고 다뤄야 할 영역입니다. + `, + imageUrl: "kokomen-infra.png" + }, + [CategoryType.FRONTEND]: { + title: "프론트엔드", + description: ` + 프론트엔드 전반적인 지식에 대한 문제가 출제됩니다. 특히, +프론트엔드 개발에서 필요한 실무적 지식이나 브라우저에 관한 심도 깊은 + 질문들이 출제됩니다. + `, + imageUrl: "kokomen-frontend.png" + }, + [CategoryType.REACT]: { + title: "리액트", + description: ` + 리액트는 사용자 인터페이스를 만들기 위한 자바스크립트 +라이브러리입니다. + 리액트에 관한 지식들을 중심으로 출제됩니다. 특히, 리액트에서 + 사용되는 API나 리액트 내에서 사용되는 주요 기술들이 출제됩니다. + `, + imageUrl: "kokomen-react.png" + }, + [CategoryType.JAVASCRIPT_TYPESCRIPT]: { + title: "자바스크립트/타입스크립트", + description: ` + 자바스크립트는 웹 브라우저와 서버에서 실행되는 동적 +프로그래밍 언어로, 현대 웹 개발의 핵심 기술입니다. + 주로 자바스크립트의 언어에 대한 이해도를 묻는 질문과 +자바스크립트를 동작시키는 엔진, 추가적으로 정적 분석을 위한 +타입스크립트에 대한 질문 또한 일부 출제됩니다. + `, + imageUrl: "kokomen-javascript-typescript.png" + } +}; + +@ObjectType() +export class Category { + @Field(() => CategoryType) + type: CategoryType; + + @Field() + title: string; + + @Field() + description: string; + + @Field() + imageUrl: string; + + constructor( + type: CategoryType, + title: string, + description: string, + imageUrl: string + ) { + this.type = type; + this.title = title; + this.description = description; + this.imageUrl = imageUrl; + } + + static getCategories(): Category[] { + const BASE_URL = process.env.CLOUD_FRONT_DOMAIN_URL + "category-image/"; + console.log(Object.values(CategoryType)); + return Object.values(CategoryType) + .filter((type) => typeof type === "number") + .map((type: CategoryType) => { + const data = CATEGORY_DATA[type]; + return new Category( + type, + data.title, + data.description, + BASE_URL + data.imageUrl + ); + }); + } +} diff --git a/apps/kokomen-server/src/interview/modules/category.ts b/apps/kokomen-server/src/interview/modules/category.ts new file mode 100644 index 00000000..f664b8f1 --- /dev/null +++ b/apps/kokomen-server/src/interview/modules/category.ts @@ -0,0 +1,8 @@ +import { Module } from "@nestjs/common"; +import { CategoryResolver } from "src/interview/resolvers/category"; +import { CategoryService } from "src/interview/services/category"; + +@Module({ + providers: [CategoryService, CategoryResolver] +}) +export class CategoryModule {} diff --git a/apps/kokomen-server/src/interview/resolvers/category.ts b/apps/kokomen-server/src/interview/resolvers/category.ts new file mode 100644 index 00000000..1a7efc78 --- /dev/null +++ b/apps/kokomen-server/src/interview/resolvers/category.ts @@ -0,0 +1,20 @@ +import { Resolver, Query, Args } from "@nestjs/graphql"; +import { Category, CategoryType } from "src/interview/domains/category"; +import { CategoryService } from "src/interview/services/category"; + +@Resolver(() => Category) +export class CategoryResolver { + constructor(private readonly categoryService: CategoryService) {} + + @Query(() => [Category]) + async categories(): Promise { + return this.categoryService.findAll(); + } + + @Query(() => Category, { nullable: true }) + async category( + @Args("type", { type: () => CategoryType }) type: CategoryType + ): Promise { + return this.categoryService.findOne(type); + } +} diff --git a/apps/kokomen-server/src/interview/services/category.ts b/apps/kokomen-server/src/interview/services/category.ts new file mode 100644 index 00000000..a32da433 --- /dev/null +++ b/apps/kokomen-server/src/interview/services/category.ts @@ -0,0 +1,14 @@ +import { Injectable } from "@nestjs/common"; +import { Category, CategoryType } from "../domains/category"; + +@Injectable() +export class CategoryService { + async findAll(): Promise { + return Category.getCategories(); + } + + async findOne(type: CategoryType): Promise { + const categories = Category.getCategories(); + return categories.find((category) => category.type === type) || null; + } +} From 00b58692e9692b03d0f150a94dc4737c61ec8794 Mon Sep 17 00:00:00 2001 From: Minhyung Cho Date: Fri, 19 Sep 2025 12:00:55 +0900 Subject: [PATCH 3/7] =?UTF-8?q?feat:=20RootQuestion=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8,=20=EC=84=9C=EB=B9=84=EC=8A=A4,=20=EB=AA=A8=EB=93=88?= =?UTF-8?q?=20=EB=B0=8F=20=EB=A6=AC=EC=A1=B8=EB=B2=84=20=EC=B6=94=EA=B0=80?= =?UTF-8?q?=20=EB=B0=8F=20=EC=B9=B4=ED=85=8C=EA=B3=A0=EB=A6=AC=20=ED=83=80?= =?UTF-8?q?=EC=9E=85=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/interview/domains/rootQuestion.ts | 23 ++++--------------- .../src/interview/modules/rootQuestion.ts | 11 +++++++++ .../src/interview/resolvers/rootQuestion.ts | 21 +++++++++++++++++ .../src/interview/services/rootQuestion.ts | 20 ++++++++++++++++ 4 files changed, 56 insertions(+), 19 deletions(-) create mode 100644 apps/kokomen-server/src/interview/modules/rootQuestion.ts create mode 100644 apps/kokomen-server/src/interview/resolvers/rootQuestion.ts create mode 100644 apps/kokomen-server/src/interview/services/rootQuestion.ts diff --git a/apps/kokomen-server/src/interview/domains/rootQuestion.ts b/apps/kokomen-server/src/interview/domains/rootQuestion.ts index 9563877d..ab262f06 100644 --- a/apps/kokomen-server/src/interview/domains/rootQuestion.ts +++ b/apps/kokomen-server/src/interview/domains/rootQuestion.ts @@ -7,22 +7,7 @@ import { } from "typeorm"; import { Interview } from "./interview"; import { Field, ID, Int, ObjectType, registerEnumType } from "@nestjs/graphql"; - -export enum QuestionCategory { - ALGORITHM_DATA_STRUCTURE, - DATABASE, - NETWORK, - OPERATING_SYSTEM, - JAVA_SPRING, - INFRA, - FRONTEND, - REACT, - JAVASCRIPT_TYPESCRIPT -} - -registerEnumType(QuestionCategory, { - name: "QuestionCategory" -}); +import { CategoryType } from "src/interview/domains/category"; export enum QuestionState { ACTIVE, @@ -48,9 +33,9 @@ export class RootQuestion { @Column({ type: "varchar", length: 1000 }) content: string; - @Field(() => QuestionCategory) - @Column({ type: "enum", enum: QuestionCategory }) - category: QuestionCategory; + @Field(() => CategoryType) + @Column({ type: "enum", enum: CategoryType }) + category: CategoryType; @Field(() => QuestionState) @Column({ type: "enum", enum: QuestionState }) diff --git a/apps/kokomen-server/src/interview/modules/rootQuestion.ts b/apps/kokomen-server/src/interview/modules/rootQuestion.ts new file mode 100644 index 00000000..e89530aa --- /dev/null +++ b/apps/kokomen-server/src/interview/modules/rootQuestion.ts @@ -0,0 +1,11 @@ +import { Module } from "@nestjs/common"; +import { TypeOrmModule } from "@nestjs/typeorm"; +import { RootQuestion } from "src/interview/domains/rootQuestion"; +import { RootQuestionResolver } from "src/interview/resolvers/rootQuestion"; +import { RootQuestionService } from "src/interview/services/rootQuestion"; + +@Module({ + imports: [TypeOrmModule.forFeature([RootQuestion])], + providers: [RootQuestionService, RootQuestionResolver] +}) +export class RootQuestionModule {} diff --git a/apps/kokomen-server/src/interview/resolvers/rootQuestion.ts b/apps/kokomen-server/src/interview/resolvers/rootQuestion.ts new file mode 100644 index 00000000..edb6ce58 --- /dev/null +++ b/apps/kokomen-server/src/interview/resolvers/rootQuestion.ts @@ -0,0 +1,21 @@ +import { Args, Query, Resolver } from "@nestjs/graphql"; +import { CategoryType } from "src/interview/domains/category"; +import { RootQuestion } from "src/interview/domains/rootQuestion"; +import { RootQuestionService } from "src/interview/services/rootQuestion"; + +@Resolver(() => RootQuestion) +export class RootQuestionResolver { + constructor(private readonly rootQuestionService: RootQuestionService) {} + + @Query(() => [RootQuestion]) + async rootQuestions(): Promise { + return this.rootQuestionService.findAll(); + } + + @Query(() => [RootQuestion]) + async rootQuestionByCategory( + @Args("category") category: CategoryType + ): Promise { + return this.rootQuestionService.findByCategory(category); + } +} diff --git a/apps/kokomen-server/src/interview/services/rootQuestion.ts b/apps/kokomen-server/src/interview/services/rootQuestion.ts new file mode 100644 index 00000000..a55d2e8d --- /dev/null +++ b/apps/kokomen-server/src/interview/services/rootQuestion.ts @@ -0,0 +1,20 @@ +import { Injectable } from "@nestjs/common"; +import { InjectRepository } from "@nestjs/typeorm"; +import { CategoryType } from "src/interview/domains/category"; +import { RootQuestion } from "src/interview/domains/rootQuestion"; +import { Repository } from "typeorm"; + +@Injectable() +export class RootQuestionService { + constructor( + @InjectRepository(RootQuestion) + private readonly rootQuestionRepository: Repository + ) {} + findAll(): Promise { + return this.rootQuestionRepository.find(); + } + + findByCategory(category: CategoryType): Promise { + return this.rootQuestionRepository.find({ where: { category } }); + } +} From 483f64a3fa785656bbb48b9d470ffcb9ab2712a0 Mon Sep 17 00:00:00 2001 From: Minhyung Cho Date: Fri, 19 Sep 2025 12:03:04 +0900 Subject: [PATCH 4/7] =?UTF-8?q?feat:=20CategoryModule=20=EB=B0=8F=20RootQu?= =?UTF-8?q?estionModule=20=EC=B6=94=EA=B0=80,=20CORS=20=EC=84=A4=EC=A0=95?= =?UTF-8?q?=20=EA=B0=9C=EC=84=A0=20=EB=B0=8F=20DB=20=ED=8F=AC=ED=8A=B8=20?= =?UTF-8?q?=EA=B8=B0=EB=B3=B8=EA=B0=92=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/kokomen-server/src/app.module.ts | 16 +++++++++------- apps/kokomen-server/src/config/db.config.ts | 2 +- apps/kokomen-server/src/main.ts | 5 ++--- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/apps/kokomen-server/src/app.module.ts b/apps/kokomen-server/src/app.module.ts index fc9a0764..0746d0b7 100644 --- a/apps/kokomen-server/src/app.module.ts +++ b/apps/kokomen-server/src/app.module.ts @@ -10,13 +10,14 @@ import { Member } from "./member/domains/member"; import { MemberResolver } from "./member/member.resolver"; import { MemberService } from "./member/member.service"; import { RedisModule } from "src/redis/redis.module"; -import { TestResolver } from "src/test.resolver"; +import { CategoryModule } from "src/interview/modules/category"; +import { RootQuestionModule } from "src/interview/modules/rootQuestion"; @Module({ imports: [ ConfigModule.forRoot({ isGlobal: true, - envFilePath: [`.env.${process.env.NODE_ENV || "development"}`, ".env"], + envFilePath: [".env.development", ".env"], load: [appConfig] }), TypeOrmModule.forRoot({ @@ -26,18 +27,19 @@ import { TestResolver } from "src/test.resolver"; username: process.env.DB_USERNAME, password: process.env.DB_PASSWORD, database: process.env.DB_DATABASE, - entities: [__dirname + "/**/domains/*.{ts,js}"], - synchronize: true + entities: [__dirname + "/**/domains/*.{ts,js}"] }), TypeOrmModule.forFeature([Member]), GraphQLModule.forRoot({ driver: ApolloDriver, - playground: true, + graphiql: true, autoSchemaFile: true }), - RedisModule + RedisModule, + CategoryModule, + RootQuestionModule ], controllers: [AppController], - providers: [AppService, MemberResolver, MemberService, TestResolver] + providers: [AppService, MemberResolver, MemberService] }) export class AppModule {} diff --git a/apps/kokomen-server/src/config/db.config.ts b/apps/kokomen-server/src/config/db.config.ts index 9b8ae0a8..b8c34efb 100644 --- a/apps/kokomen-server/src/config/db.config.ts +++ b/apps/kokomen-server/src/config/db.config.ts @@ -3,7 +3,7 @@ import { registerAs } from "@nestjs/config"; export default registerAs("db", () => ({ type: "mysql", host: process.env.DB_HOST, - port: parseInt(process.env.DB_PORT, 10), + port: parseInt(process.env.DB_PORT || "3306", 10), username: process.env.DB_USERNAME, password: process.env.DB_PASSWORD, database: process.env.DB_DATABASE diff --git a/apps/kokomen-server/src/main.ts b/apps/kokomen-server/src/main.ts index 4e54cd02..208deb7f 100644 --- a/apps/kokomen-server/src/main.ts +++ b/apps/kokomen-server/src/main.ts @@ -4,15 +4,14 @@ import { AppModule } from "./app.module"; async function bootstrap() { const app = await NestFactory.create(AppModule); - // CORS 설정 app.enableCors({ origin: [ "http://localhost:3000", "http://localhost:3001", "http://local.kokomen.kr:3000", "https://dev.kokomen.kr" - ], // 클라이언트 도메인 - credentials: true, // 쿠키 포함 허용 + ], + credentials: true, methods: ["GET", "POST", "PUT", "DELETE", "OPTIONS"], allowedHeaders: ["Content-Type", "Authorization", "Cookie"] }); From fe7a5f083d5fcd645602bce7a6b11e839d7f327e Mon Sep 17 00:00:00 2001 From: Minhyung Cho Date: Fri, 19 Sep 2025 17:00:17 +0900 Subject: [PATCH 5/7] =?UTF-8?q?feat:=20Info.plist=20=ED=8C=8C=EC=9D=BC=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20-=20=EB=B2=84=EC=A0=84=20=EB=B2=88?= =?UTF-8?q?=ED=98=B8=EB=A5=BC=200.0.1=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= =?UTF-8?q?=ED=95=98=EA=B3=A0,=20=EC=82=AC=EC=A7=84=20=EB=9D=BC=EC=9D=B4?= =?UTF-8?q?=EB=B8=8C=EB=9F=AC=EB=A6=AC=20=EC=A0=91=EA=B7=BC=20=EC=84=A4?= =?UTF-8?q?=EB=AA=85=20=EC=B6=94=EA=B0=80=20=EB=B0=8F=20=EC=83=81=ED=83=9C?= =?UTF-8?q?=EB=B0=94=20=EC=8A=A4=ED=83=80=EC=9D=BC=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/kokomen-native/ios/kokomennative/Info.plist | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/kokomen-native/ios/kokomennative/Info.plist b/apps/kokomen-native/ios/kokomennative/Info.plist index c75bfe99..4cb7749c 100644 --- a/apps/kokomen-native/ios/kokomennative/Info.plist +++ b/apps/kokomen-native/ios/kokomennative/Info.plist @@ -19,7 +19,7 @@ CFBundlePackageType $(PRODUCT_BUNDLE_PACKAGE_TYPE) CFBundleShortVersionString - 1.0.0 + 0.0.1 CFBundleSignature ???? CFBundleURLTypes @@ -48,6 +48,8 @@ $(PRODUCT_NAME)이 음성 면접 서비스 제공을 위해 마이크 권한이 필요합니다. NSSpeechRecognitionUsageDescription $(PRODUCT_NAME)이 음성 면접 과정에서 음성 인식 권한이 필요합니다. + NSPhotoLibraryUsageDescription + $(PRODUCT_NAME)에서 사진을 업로드하거나 프로필 이미지를 변경할 때 사진 라이브러리 접근이 필요합니다. UILaunchStoryboardName SplashScreen UIRequiredDeviceCapabilities @@ -57,7 +59,7 @@ UIRequiresFullScreen UIStatusBarStyle - + UIStatusBarStyleDefault UISupportedInterfaceOrientations UIInterfaceOrientationPortrait From 1df0a1f66a529afea173da478999be6a25f941bb Mon Sep 17 00:00:00 2001 From: Minhyung Cho Date: Fri, 19 Sep 2025 17:10:27 +0900 Subject: [PATCH 6/7] =?UTF-8?q?refactor:=20getCategories=20=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C=EC=97=90=EC=84=9C=20=EB=B6=88=ED=95=84?= =?UTF-8?q?=EC=9A=94=ED=95=9C=20=EB=A1=9C=EA=B7=B8=20=EC=A0=9C=EA=B1=B0=20?= =?UTF-8?q?=EB=B0=8F=20=EC=BD=94=EB=93=9C=20=EA=B0=84=EC=86=8C=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/interview/domains/category.ts | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/apps/kokomen-server/src/interview/domains/category.ts b/apps/kokomen-server/src/interview/domains/category.ts index b044ca46..7549f288 100644 --- a/apps/kokomen-server/src/interview/domains/category.ts +++ b/apps/kokomen-server/src/interview/domains/category.ts @@ -166,17 +166,14 @@ export class Category { static getCategories(): Category[] { const BASE_URL = process.env.CLOUD_FRONT_DOMAIN_URL + "category-image/"; - console.log(Object.values(CategoryType)); - return Object.values(CategoryType) - .filter((type) => typeof type === "number") - .map((type: CategoryType) => { - const data = CATEGORY_DATA[type]; - return new Category( - type, - data.title, - data.description, - BASE_URL + data.imageUrl - ); - }); + return Object.values(CategoryType).map((type: CategoryType) => { + const data = CATEGORY_DATA[type]; + return new Category( + type, + data.title, + data.description, + BASE_URL + data.imageUrl + ); + }); } } From 4c3ff6e174aa2d438f49a87744c41e5e6bab539a Mon Sep 17 00:00:00 2001 From: Minhyung Cho Date: Fri, 19 Sep 2025 17:14:59 +0900 Subject: [PATCH 7/7] =?UTF-8?q?feat:=20=ED=99=98=EA=B2=BD=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=20=EA=B0=9C=EC=84=A0=20=EB=B0=8F=20=EC=B9=B4=ED=85=8C?= =?UTF-8?q?=EA=B3=A0=EB=A6=AC=20=EC=84=9C=EB=B9=84=EC=8A=A4=20=EC=B5=9C?= =?UTF-8?q?=EC=A0=81=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/kokomen-server/src/app.module.ts | 4 ++-- .../kokomen-server/src/interview/resolvers/rootQuestion.ts | 2 +- apps/kokomen-server/src/interview/services/category.ts | 7 ++++++- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/apps/kokomen-server/src/app.module.ts b/apps/kokomen-server/src/app.module.ts index 0746d0b7..5c4359e6 100644 --- a/apps/kokomen-server/src/app.module.ts +++ b/apps/kokomen-server/src/app.module.ts @@ -17,7 +17,7 @@ import { RootQuestionModule } from "src/interview/modules/rootQuestion"; imports: [ ConfigModule.forRoot({ isGlobal: true, - envFilePath: [".env.development", ".env"], + envFilePath: [`env.${process.env.NODE_ENV || "development"}.`, ".env"], load: [appConfig] }), TypeOrmModule.forRoot({ @@ -32,7 +32,7 @@ import { RootQuestionModule } from "src/interview/modules/rootQuestion"; TypeOrmModule.forFeature([Member]), GraphQLModule.forRoot({ driver: ApolloDriver, - graphiql: true, + graphiql: process.env.NODE_ENV === "development", autoSchemaFile: true }), RedisModule, diff --git a/apps/kokomen-server/src/interview/resolvers/rootQuestion.ts b/apps/kokomen-server/src/interview/resolvers/rootQuestion.ts index edb6ce58..5d09dcd5 100644 --- a/apps/kokomen-server/src/interview/resolvers/rootQuestion.ts +++ b/apps/kokomen-server/src/interview/resolvers/rootQuestion.ts @@ -14,7 +14,7 @@ export class RootQuestionResolver { @Query(() => [RootQuestion]) async rootQuestionByCategory( - @Args("category") category: CategoryType + @Args("category", { type: () => CategoryType }) category: CategoryType ): Promise { return this.rootQuestionService.findByCategory(category); } diff --git a/apps/kokomen-server/src/interview/services/category.ts b/apps/kokomen-server/src/interview/services/category.ts index a32da433..38819c2a 100644 --- a/apps/kokomen-server/src/interview/services/category.ts +++ b/apps/kokomen-server/src/interview/services/category.ts @@ -3,8 +3,13 @@ import { Category, CategoryType } from "../domains/category"; @Injectable() export class CategoryService { + private readonly categories: Category[]; + constructor() { + this.categories = Category.getCategories(); + } + async findAll(): Promise { - return Category.getCategories(); + return this.categories; } async findOne(type: CategoryType): Promise {