LifeSports Application(ReactNative & Nest.js) - 11. wayfinding-service
#1 wayfinding-service
wayfinding-service는 공공데이터를 http 로컬 서버로 만들기 위한 서비스입니다.
- 데이터는 github wayfinding-service data폴더에 있습니다.
http 로컬 서버에 모든 데이터를 띄우고 이후에 만들 map-service에서 이 데이터를 받아오도록 하겠습니다.
nest new wayfinding-service
nest generate module wayfinding
nest generate service wayfinding
wayfinding-service의 포트번호를 7900번으로 설정하겠습니다.
- ./src/main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.enableCors();
await app.listen(7900);
}
bootstrap();
mongodb compass를 이용하여 데이터를 넣어주도록 하겠습니다. mongodb compass에서는 import를 통해 json, execl 데이터를 한번에 넣어줄 수 있습니다.
app.controller에서 데이터를 띄우기 위한 엔드포인트를 만들도록 하겠습니다.
- ./src/app.controller.ts
import { Controller, Get, HttpStatus, Param, Query } from '@nestjs/common';
import { Builder } from 'builder-pattern';
import { statusConstants } from './constants/status.constant';
import { ResponseMaps } from './vo/response.maps';
import { WayfindingService } from './wayfinding/wayfinding.service';
@Controller("wayfinding-service")
export class AppController {
constructor(private readonly wayfindingService: WayfindingService) {}
@Get('/')
public async getAll(): Promise<any> {
try {
const result: any = await this.wayfindingService.getAll();
if(result.status === statusConstants.ERROR) {
return await Object.assign({
status: HttpStatus.INTERNAL_SERVER_ERROR,
payload: null,
message: "Error message: " + result.message
});
}
const responseMaps: Array<ResponseMaps> = [];
for(const el of result.payload) {
responseMaps.push(el);
}
return await Object.assign({
status: HttpStatus.OK,
payload: responseMaps,
message: "Get list of map"
});
} catch(err) {
return await Object.assign({
status: HttpStatus.BAD_REQUEST,
payload: null,
message: "Error message: " + err
});
}
}
@Get(':_id')
public async getOne(@Param('_id') _id: string): Promise<any> {
try {
const result: any = await this.wayfindingService.getOne(_id);
if(result.status === statusConstants.ERROR) {
return await Object.assign({
status: statusConstants.ERROR,
payload: null,
message: "Server error!"
});
}
console.log(result);
return await Object.assign({
status: HttpStatus.OK,
payload: Builder(ResponseMaps)._id(result.payload._id)
.ycode(result.payload.ycode)
.type_nm(result.payload.type_nm)
.gu_nm(result.payload.gu_nm)
.parking_lot(result.payload.parking_lot)
.bigo(result.payload.bigo)
.xcode(result.payload.xcode)
.tel(result.payload.tel)
.addr(result.payload.addr)
.in_out(result.payload.in_out)
.home_page(result.payload.home_page)
.edu_yn(result.payload.edu_yn)
.nm(result.payload.nm)
.build(),
message: "Get data by _id"
});
} catch(err) {
return await Object.assign({
status: statusConstants.ERROR,
payload: null,
message: "Server error!"
});
}
}
@Get('/list')
public async getListByTypeNm(@Query('type_nm') type_nm: string): Promise<any> {
try {
console.log(type_nm);
const result: any = await this.wayfindingService.getListByTypeNm(type_nm);
if(result.status === statusConstants.ERROR) {
return await Object.assign({
status: HttpStatus.INTERNAL_SERVER_ERROR,
payload: null,
message: "Error message: " + result.message
});
}
const responseMaps: Array<ResponseMaps> = [];
for(const el of result.payload) {
responseMaps.push(el);
}
return await Object.assign({
status: HttpStatus.OK,
payload: responseMaps,
message: "Get list of map"
});
} catch(err) {
return await Object.assign({
status: HttpStatus.BAD_REQUEST,
payload: null,
message: "Error message: " + err
});
}
}
@Get('/list')
public async getListByGuNm(@Query('gu_nm') gu_nm: string) : Promise<any> {
try {
const result: any = await this.wayfindingService.getListByGuNm(gu_nm);
if(result.status === statusConstants.ERROR) {
return await Object.assign({
status: HttpStatus.INTERNAL_SERVER_ERROR,
payload: null,
message: "Error message: " + result.message
});
}
const responseMaps: Array<ResponseMaps> = [];
for(const el of result.payload) {
responseMaps.push(el);
}
return await Object.assign({
status: HttpStatus.OK,
payload: responseMaps,
message: "Get list of map"
});
} catch(err) {
return await Object.assign({
status: HttpStatus.BAD_REQUEST,
payload: null,
message: "Error message: " + err
});
}
}
@Get('/list')
public async getListGuNmAndTypeNm(
@Query('gu_nm') gu_nm: string,
@Query('type_nm') type_nm: string
): Promise<any> {
try {
const result: any = await this.wayfindingService.getListGuNmAndTypeNm(gu_nm, type_nm);
if(result.status === statusConstants.ERROR) {
return await Object.assign({
status: HttpStatus.INTERNAL_SERVER_ERROR,
payload: null,
message: "Error message: " + result.message
});
}
const responseMaps: Array<ResponseMaps> = [];
for(const el of result.payload) {
responseMaps.push(el);
}
return await Object.assign({
status: HttpStatus.OK,
payload: responseMaps,
message: "Get list of map"
});
} catch(err) {
return await Object.assign({
status: HttpStatus.BAD_REQUEST,
payload: null,
message: "Error message: " + err
});
}
}
}
컨트롤러의 메서드는 총 5가지입니다. 우선 rest endpoint로 설정을 하고, 후에 map-service를 구현하면서 map-service와 wayfinding-service 간 메시지 브로커 기반으로 통신할 수 있게 수정하도록 하겠습니다.
1) getAll: 전체 맵 리스트를 가져오는 메서드입니다.
2) getOne: 마커 클릭 시 해당 맵의 상세 데이터를 불러오는 메서드입니다.
3) getListByTypeNm: type_nm(운동장소)를 기반으로 맵 리스트를 가져오는 메서드입니다.
4) getListByGuNm: gu_nm(구)를 기반으로 맵 리스트를 가져오는 메서드입니다.
5) getListGuNmAndType: gu_nm, type_nm을 기반으로 맵 리스트를 가져오는 메서드입니다.
그러면 dto, vo, schema를 작성하도록 하겠습니다.
#2 mongoose설치
npm install --save @nestjs/mongoose mongoose
- ./src/app.modules.ts
import { Module } from '@nestjs/common';
import { MongooseModule } from '@nestjs/mongoose';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { WayfindingModule } from './wayfinding/wayfinding.module';
@Module({
imports: [
MongooseModule.forRoot("mongodb://localhost:27017/WAYFINDINGSERVICE?readPreference=primary&appname=MongoDB%20Compass&directConnection=true&ssl=false"),
WayfindingModule
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
- ./src/wayfinding/wayfinding.module.ts
import { Module } from '@nestjs/common';
import { MongooseModule } from '@nestjs/mongoose';
import { Maps, MapsSchema } from 'src/schema/maps.schema';
import { WayfindingService } from './wayfinding.service';
@Module({
imports: [MongooseModule.forFeature([{
name: Maps.name,
schema: MapsSchema
}])],
providers: [WayfindingService],
exports: [WayfindingService],
})
export class WayfindingModule {}
앞서 compass를 이용하여 맵 데이터를 mongodb에 저장하는 작업을 진행하였습니다. 그러면 이 데이터를 가져오기 위해 mongoose를 연동하여 wayfinding-service에서 schema를 작성하도록 하겠습니다.
npm install --save class-transformer builder-pattern
- ./src/schema/maps.schema.ts
import { Prop, Schema, SchemaFactory } from "@nestjs/mongoose";
import { Transform } from "class-transformer";
export type MapsDocument = Maps & Document;
@Schema()
export class Maps {
@Transform(({ value }) => value.toString())
_id: String;
@Prop({ required: true })
ycode: Number;
@Prop({ required: true })
type_nm: string;
@Prop({ required: true })
gu_nm: string;
@Prop({ required: true })
parking_lot: string;
@Prop({ required: true })
bigo: string;
@Prop({ required: true })
xcode: Number;
@Prop({ required: true })
tel: string;
@Prop({ required: true })
addr: string;
@Prop({ required: true })
in_out: string;
@Prop({ required: true })
home_page: string;
@Prop({ required: true })
edu_yn: string;
@Prop({ required: true })
nm: string;
}
export const MapsSchema = SchemaFactory.createForClass(Maps);
MapsSchema의 문서 구조는 mongodb에 저장된 문서 데이터 타입을 그대로 이용하였습니다.
vo, dto클래스를 작성하도록 하겠습니다.
- ./src/vo/response.vo.ts
export class ResponseMaps {
_id: string;
ycode: Number;
type_nm: string;
gu_nm: string;
parking_lot: string;
bigo: string;
xcode: Number;
tel: string;
addr: string;
in_out: string;
home_page: string;
edu_yn: string;
nm: string;
}
- ./src/dto/maps.dto.ts
export class MapsDto {
_id: string;
ycode: Number;
type_nm: string;
gu_nm: string;
parking_lot: string;
bigo: string;
xcode: Number;
tel: string;
addr: string;
in_out: string;
home_page: string;
edu_yn: string;
nm: string;
}
작성한 코드들을 이용하여 컨트롤러에 클래스를 import를 하고나면 service클래스만 오류가 나타날텐데 service클래스도 마저 작성하고 테스트를 진행해보도록 하겠습니다.
- ./src/wayfinding/wayfinding.service.ts
import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model } from 'mongoose';
import { statusConstants } from 'src/constants/status.constant';
import { MapsDto } from 'src/dto/maps.dto';
import { Maps, MapsDocument } from 'src/schema/maps.schema';
@Injectable()
export class WayfindingService {
constructor(@InjectModel(Maps.name) private mapsModel: Model<MapsDocument>) {}
public async getAll(): Promise<any> {
try {
const maps = await this.mapsModel.find();
if(!maps) {
return await Object.assign({
status: statusConstants.ERROR,
payload: null,
message: "Database error!"
});
}
const result: Array<MapsDto> = [];
for(const element of maps) {
result.push(element);
}
return await Object.assign({
status: statusConstants.SUCCESS,
payload: result,
message: "Successfully get list of map in database"
});
} catch(err) {
return await Object.assign({
status: statusConstants.ERROR,
payload: null,
message: "Database error!"
});
}
}
public async getOne(_id: string): Promise<any> {
try {
const map = await this.mapsModel.findOne({ _id: _id });
if(!map) {
return await Object.assign({
status: statusConstants.ERROR,
payload: null,
message: "Database error!"
});
}
return await Object.assign({
status: statusConstants.SUCCESS,
payload: map,
message: "Successfully get one data in database"
});
} catch(err) {
return await Object.assign({
status: statusConstants.ERROR,
payload: null,
message: "Database error!"
});
}
}
public async getListByTypeNm(type_nm: string): Promise<any> {
try {
const maps = await this.mapsModel.find({ type_nm: type_nm });
if(!maps) {
return await Object.assign({
status: statusConstants.ERROR,
payload: null,
message: "Database error!"
});
}
const result: Array<MapsDto> = [];
for(const element of maps) {
result.push(element);
}
return await Object.assign({
status: statusConstants.SUCCESS,
payload: result,
message: "Successfully get list of map in database"
});
} catch(err) {
return await Object.assign({
status: statusConstants.ERROR,
payload: null,
message: "Database error!"
});
}
}
public async getListByGuNm(gu_nm: string): Promise<any> {
try {
const maps = await this.mapsModel.find({ gu_nm: gu_nm });
if(!maps) {
return await Object.assign({
status: statusConstants.ERROR,
payload: null,
message: "Database error!"
});
}
const result: Array<MapsDto> = [];
for(const element of maps) {
result.push(element);
}
return await Object.assign({
status: statusConstants.SUCCESS,
payload: result,
message: "Successfully get list of map in database"
});
} catch(err) {
return await Object.assign({
status: statusConstants.ERROR,
payload: null,
message: "Database error!"
});
}
}
public async getListGuNmAndTypeNm(gu_nm: string, type_nm: string): Promise<any> {
try {
const maps = await this.mapsModel.find({
gu_nm: gu_nm,
type_nm: type_nm
});
if(!maps) {
return await Object.assign({
status: statusConstants.ERROR,
payload: null,
message: "Database error!"
});
}
const result: Array<MapsDto> = [];
for(const element of maps) {
result.push(element);
}
return await Object.assign({
status: statusConstants.SUCCESS,
payload: result,
message: "Successfully get list of map in database"
});
} catch(err) {
return await Object.assign({
status: statusConstants.ERROR,
payload: null,
message: "Database error!"
});
}
}
}
service클래스는 굉장히 단순합니다. find메서드를 이용하여 전달받은 인자를 조건으로 사용하여 그에 맞는 리스트를 가져오도록 합니다. 테스트를 진행하도록 하겠습니다.
#3 테스트
1) GET /wayfinding-service/
2) GET /wayfinding-service/map/:_id
3) GET /wayfinding-service/maps/list-type-nm/:type_nm
4) GET /wayfinding-service/maps/list-gu-nm/:gu_nm
5) GET /wayfinding-service/maps/list-gu-type?query-string
테스트 결과 데이터를 잘 받아오는 모습을 볼 수 있습니다.
다음 포스트에서는 map-service를 만들고 wayfinding-service와 통신을 진행해보도록 하겠습니다.
Author And Source
이 문제에 관하여(LifeSports Application(ReactNative & Nest.js) - 11. wayfinding-service), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@biuea/LifeSports-ApplicationReactNative-Nest.js-11.-wayfinding-service저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)