묻고 답해요
141만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
해결됨Practical Testing: 실용적인 테스트 가이드
시간대에 따라서 변화하는 로직 테스트 하는 가이드
안녕하세요. 우빈님 시간대에 따라 다른 결과를 주는 로직을 테스트 하는 과정에서 고민이 있어 질문을 드립니다. 우빈님이 강의에서도 언급하셨지만, 시간과 같이 관측할 때마다 달라지는 영역은 외부로 분리하면 테스트하기 쉬워진다고 말씀하셨습니다.!하지만, 현재 서비스 레이어 까지만 분리가 가능하고 컨트롤러에서 LocalDateTime을 파라미터로 받지 못하는 상황입니다. 그래서 컨트롤러를 테스트할 때 어떻게 해야할까 고민을 좀 해봤는데요. 저의 결론은 TimeProvider라는 클래스를 하나 만들어서컨트롤러를 테스트할 때는 이를 mocking하는 방식으로 테스트 코드를 작성했습니다. TimeProvider/** * 시간을 고정하여 테스트하기 위해 사용 */ @Component public class TimeProvider { public LocalDateTime getCurrentLocalDateTime() { return LocalDateTime.now(); } } ControllerGET을 사용하고 싶은데, 외부와 연동해야해서 POST를 사용할 수 밖에 없습니다. ㅠㅠ/** * 인기 메뉴 조회 * 현재 시간대의 식사종류와 일치하는 가장 조회수가 많은 금일 식사 메뉴 조회 */ @PostMapping("/menu/top1-view") public ResponseEntity<SkillResponse> getTop1RestaurantMenuByView(@RequestBody SkillPayload payload, @PageableDefault(size = 1) Pageable pageable) { log.info("request={}", payload); Page<RestaurantMenuResponse> top1RestaurantMenuByView = restaurantService.findTop1RestaurantMenuByView(pageable, timeProvider.getCurrentLocalDateTime()); RestaurantsMenuResponse response = new RestaurantsMenuResponse(top1RestaurantMenuByView.getContent()); return new ResponseEntity<>(response.toSkillResponseUseTextCard(apiVersion), HttpStatus.OK); } Test Code@Test @DisplayName("추천수 가장 많은 메뉴를 1개 조회한다.") void getTop1UosRestaurantMenuByView() throws Exception { // given // 현재 시간을 고정할 시간 생성 LocalDateTime fixedDateTime = LocalDateTime.of(2023, 8, 16, 10, 59, 59); when(timeProvider.getCurrentLocalDateTime()).thenReturn(fixedDateTime); String date = CrawlingUtils.toDateString(fixedDateTime); restaurant restaurant1 = createUosRestaurant(date, STUDENT_HALL, MealType.BREAKFAST, "라면", 0, 0); restaurant restaurant2 = createUosRestaurant(date, MAIN_BUILDING, MealType.BREAKFAST, "김밥", 1, 0); restaurant restaurant3 = createUosRestaurant(date, WESTERN_RESTAURANT, MealType.BREAKFAST, "돈까스", 2, 0); restaurant restaurant4 = createUosRestaurant(date, MUSEUM_OF_NATURAL_SCIENCE, MealType.BREAKFAST, "제육", 2, 1); restaurantRepository.saveAll(List.of(restaurant1, restaurant2, restaurant3, restaurant4)); SkillPayload skillPayload = createSkillPayload(RestaurantName.STUDENT_HALL.name(), MealType.BREAKFAST.name()); // when // then mockMvc.perform(post("/api/v1/text-card/restaurant/menu/top1-view") .contentType(MediaType.APPLICATION_JSON) .content(om.writeValueAsBytes(skillPayload)) .content(om.writeValueAsString(PageRequest.of(0, 1)))) .andDo(print()) .andExpect(status().isOk()) .andExpect(jsonPath("$.version").value(SkillResponse.apiVersion)) .andExpect(jsonPath("$.template").isNotEmpty()) .andExpect(jsonPath("$.template.outputs").isArray()) .andExpect(jsonPath("$.template.outputs[0].textCard").isNotEmpty()) .andExpect(jsonPath("$.template.outputs[0].textCard.text").isString()); } 이런식으로 작성하는 것이 최선일까요?LocalDateTime fixedDateTime = LocalDateTime.of(2023, 8, 16, 10, 59, 59); when(timeProvider.getCurrentLocalDateTime()).thenReturn(fixedDateTime);TimeProvider 클래스를 만들어서 mocking 하는 방법이 최선일까요?혹시 더 좋은 방법을 말씀주시면 감사하겠습니다.! 좋은 강의 만들어 주셔서 감사합니다.^^
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 백엔드 코스
상품 알러지 정보에 아무것도 없는 경우
상품 알러지에 아무 것도 없는 경우에는 어떻게 구조를 잡아야할까요?'만다린 버베나 피지오'의 경우에는 알러지 정보가 없어서 이런 식으로 정규화를 진행했는데, 다른 방법이 있는지 궁금합니다!
-
해결됨Practical Testing: 실용적인 테스트 가이드
예외 처리에 대한 rest doc 작성하기
안녕하세요!강사님 덕분에 테스트에 많은 관심이 생겨 개인 프로젝트에도 적용을 해보고 있습니다! Rest doc 작성 중 궁금한 점이 생겨 질문드립니다.API의 정상 응답이 아닌 예외 발생 시의 응답도 Rest doc으로 작성하고자 합니다.예를 들어 인증, 인가 관련하여 예외가 발생하는 경우가 있을 때 다음과 같이 생각했습니다.예외 케이스 별로 에러 코드를 상세하게 나누어 세밀한 응답을 전달하기 (ex. 아이디가 틀렸을 때 - 401A, 비밀번호가 틀렸을 때 - 401B, 아이디가 존재하지 않을 때 - 401C 등등..)공통 예외코드로 처리하기 (ex. 인증 실패 시 어떤 경우라도 401 코드 반환)위의 2가지 경우에 어떤 식으로 rest doc을 작성하는 것이 좋을까요? 1번 케이스의 경우는 특정 API 문서마다 함께 적는 것이 좋을 것 같긴 한데 2번 케이스의 경우는 프로젝트 전반적인 공통 예외처리라 별도의 문서 항목으로 1개만 작성하는 게 좋을 지 고민이 됩니다. 혹시 현업에서는 예외 발생 시 응답에 대한 문서도 작성하시는 지 궁금하고 1번, 2번 케이스에 대하여 어떻게 rest doc을 작성하는 것이 다른 인원과 소통하기 편할지 의견 부탁드리겠습니다! 감사합니다.
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 백엔드 코스
map(el,index)가 어디에 나와있나요?
강의 보다가 map(el,index)이 나와있길래, 개념을 자세히 설명하는 강의를 찾을려고 했는데 어디에 있는지 모르겠습니다 목차 좀 알려주세요
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 백엔드 코스
구현역량에 대한 질문
안녕하세요 강의 완강후 오랜만에 질문드립니다!그동안 클린코드, sql, oop, cs등을 공부해보고 강의도 다시 복습중입니다.다름이 아니라 구현능력에 대한 질문입니다. 강의코드를 이해하거나 복붙, 수정해서 api를 구현하는 것은 가능한데, 백지상태에서 구현하라고 하면 머리가 하얘집니다… 아직 부족하다고 생각돼서 회사에 지원은 안해봤는데 막상 과제테스트를 하게되면 정말 막막할 것 같네요..(어떤 회사들은 과제테스트 할 때 라이브러리를 사용하지 않고 구현해야된다고 하더군요)새로운 api를 구현하려고 하면 일단 강의코드를 참고해서 복붙 ,수정 작업을 반복하는데 이게 맞나하는 생각이 드네요.그래서 코드를 한줄 한줄 따라 치면서 이해하고 외우는 방법으로 구현능력을 키워보려 하는데 괜찮은 방법일까요? 아니면 그냥 코드를 참고하더라도 무작정 구현을 많이 해보는게 좋을까요?그리고 코파일럿을 쓰고있는데 굉장히 편리하긴 하지만 구현능력을 키우려면 쓰지 않는게 좋겠죠?독학으로 하다보니 여러 생각이 많아지는 것 같습니다. 조언 부탁드릴게요!
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 백엔드 코스
docker-compose 실행후 페이지 실행안됨
nest.js docker파일을 실행하였는데 정상적으로 돌아가는데 이상하게 매번 [Nest] 42 - 08/13/2023, 7:22:38 AM ERROR [ExceptionHandler] Access denied for user ''@'172.19.0.3' (using password: YES)이 오류가 나더라구요 그래서 확인해보니까 user 권한을 주면된다는데 제가 env파일 root로 두개다 설정을 했는데 왜 저러는지 모르겠는거랑 error에 user부분이 ''이렇게만 나오는 이유를 잘모르겠습니다그리고 페이지에 들어가니 페이지가 작동되지않는다는 오류와 전송된 데이터가 없다는 오류만 나옵니다. FROM node:16 COPY ./package.json /myfolder/ COPY ./yarn.lock /myfolder/ WORKDIR /myfolder/ RUN yarn install # packge.json이 변경되지않았는데 매번 새롭게 다운받는게 비효율적이라서 packge.json과 yarn.lock을 미리 복사 # 캐시에서 확인할때 변경되지않으면 다음부터는 다운받지않고 바로 가져올수있기때문에 # 코드를 변경하면 이부분만 캐시가 깨지기때문에 속도가 더빠르다 COPY . /myfolder/ # WORKDIR /myfolder/ # RUN yarn install # . 했을 당시의 소스코드를 기억함으로 캐시에서의 소스코드와 다르면 다시 카피해서 가져옴 # 한번 캐시가 깨지기 시작하면 그아래부분부터는 전부깨서 전부다시 다운받거나 새로시작 -> 어디가 변경된지 몰라서 영향을 줄수있기때문에 CMD yarn start:devversion: '3.7' # 컴퓨터들 # 들여쓰기가 부모자식관계로 인식해서 중요함 services: # 변수명처럼 자유롭게 작성할수있음 / 컴퓨터명 my-backend: build: # 파일경로 context: . # 파일명 dockerfile: Dockerfile volumes: - ./src:/myfolder/src # 포트포워딩 ports: - 3000:3000 env_file: - ./.env.docker # 도커를 실행할때 사용하는 환경변수파일설정 my-database: # platform: linux/86_64 # cpu등의 문제가있을때 # 설치해서 바로실행되는경우 dockerfile없이 image: mysql:latest # mysql은 비밀번호가 있어야지 작동한다 설치하고 사용할 database도 만들어주어야 작동한다 # mysql에 접속해서 자동적으로 myproject명으로 설정된 데이터베이스를 만들어준다 environment: MYSQL_DATABASE: 'starbucksDB' MYSQL_ROOT_PASSWORD: 'root' # 처음으로 들어갈때 비밀번호를 설정 ports: - 3306:3306 # 하지만 네임리졸루션으로 express에서 접속가능
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 백엔드 코스
포트번호 때문에 에러 날 수 있나요
프론트,백엔드,몽고db로 api 조회하는게 강의 듣고복습폴더에서 포트번호 똑같이 4000으로 했다가 에러나서 3000으로 바꿨더니 해결됐어요근데 어쩔땐 복습폴더에서 포트번호 4000으로 맞춰놓고 도커 접속했더니 잘만 되더라구요에러나는 기준이 궁금해요
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 백엔드 코스
백엔드는 창의성을 필요로 하나요?
그냥 서버만 관리하면 되니까 새로운 아이디어가 떠오르거나 창의성 같은 거는 필요하지 않나요?
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 백엔드 코스
grpahql-upload이슈
안녕하세요 원두멘토님! 13챕터에서 graphql-upload 버전이슈로 버전을 낮춰 대응하셔 작동이 되게 알려주셨습니다.확인을 해보니 apollo server에서 원래 패키지에 포함시켰던 디펜젼시를 csrf문제로 포함시키지 않고 분리를 해서 버전관리가 되지 않아서 생긴 문제인것 같았습니다.제가 궁금한 점은 graphql-upload로 클라이언트에게 업로드 기능을 제공해주는 것이 아닌 다른 방법으로 grpahql에서 upload기능을 제공해 줄수있는지 궁금합니다.보안상 좋지 않고 버전관리가 되지 않는 패키지는 사용하는것이 나중을 생각했을때 더 개발난이도가 올라갈 것 같다 생각이 들었습니다.제가 생각한 방법은 multer를 사용하는 건데 그렇게 하려면 restapi로 제공을 해줘야 하는데 grpahql 과 restapi를 같이 사용해서 api를 제공해줘야하는데 이 또한 가능하거나 추천하시는지 궁금합니다.
-
미해결Practical Testing: 실용적인 테스트 가이드
외부 세계에 영향을 주는 코드
관측할 때마다 다른 값의 의존하는 코드는즉, 현재시각, 랜덤 값 등등은 이해 하겠는데외부 세계에 영향을 주는 코드는 어떤 건지 이해가 잘 안되서요.혹시 간단한 예제를 들어주실수 있으실까요?
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 백엔드 코스
entity.ts파일의 class 데이터 타입지정안됨 오류
entity.ts파일에서 input으로 사용할 틀을 resolver에서 Mutation쪽 service의 매개변수로 넘겨줄려고 사용했는데Argument of type '{ inputStarbucks: InputStarbucks; }' is not assignable to parameter of type 'InputStarbucks'이러한 오류가 나서 찾아보니 해당 타입으로는 변수타입을 지정할수없어서 변경하라고했는데class틀도 문제가 없는데 왜 오류가 나는지 잘모르겠습니다.import { Args, Mutation, Query, Resolver } from '@nestjs/graphql'; import { StarbucksService } from './starbucks.service'; import { InputStarbucks } from './entities/starbucks.input'; import { Starbucks } from './entities/starbucks.entity'; @Resolver() export class StarbucksResolver { constructor( private readonly starbucksService: StarbucksService, // prettier때문에 아래로 내려쓰기가 안되니까 주석달기 ) {} @Query(() => [Starbucks], { nullable: true }) // graphql에서는 배열을 [Board]식으로 사용 아래에서는 Board[]라고 사용했는데 fetchBoards(): Starbucks[] { return this.starbucksService.findAll(); } @Mutation(() => String) creatBoard( // 한번에 사용하는 방식 @Args('inputStarbucks') inputStarbucks: InputStarbucks, // graphql에서 데이터를 입력받고 변수명과 타입을 지정 // graphql에서 writer로 입력받은값을 writer라는 변수에 받고 데이터 타입은 string으로 지정 ): string { return this.starbucksService.create({ inputStarbucks }); // return을 작성해야 사용한 api쪽 리턴이 module쪽까지 전달됨 } }import { Injectable, Scope } from '@nestjs/common'; import { Starbucks } from './entities/starbucks.entity'; import { InputStarbucks } from './entities/starbucks.input'; @Injectable({ scope: Scope.DEFAULT }) export class StarbucksService { findAll(): Starbucks[] { // entity에서 만든 Board의 배열형태를 가져와서 사용 const result = [ { number: 1, writer: '짱구', title: '제목', contents: '내용이요' }, { number: 2, writer: '짱구2', title: '제목2', contents: '내용이요2' }, { number: 3, writer: '짱구3', title: '제목3', contents: '내용이요3' }, ]; return result; } create({ inputStarbucks }: InputStarbucks): string { console.log(inputStarbucks.writer); // 데이터 타입의 클래스의 명과 동일해야한다 .writer이부분이 console.log(inputStarbucks.title); console.log(inputStarbucks.contents); return '게시물 등록 성공'; } }import { Field, InputType } from '@nestjs/graphql'; // @ObjectType() // 이렇게 작성하면 type으로 나옴 . 리턴타입이 type이었을때 // mutation의 경우에는 input으로 작성했다 @InputType() export class InputStarbucks { @Field(() => String) writer: string; @Field(() => String) title: string; @Field(() => String) contents: string; } // Graphql에서 사용하기위해서 graphql 데이터 타입지정
-
해결됨부트캠프에서 알려주지 않는 것들 (리액트) 1편
마지막 onSubmit 에러체크 문제
에러체크할 때 나머지값이 없어도 submit이 되는 문제가 있습니다.<InfoContext.Provider value={{ value: info, setValue: setInfo, error, setError: (e) => setError({...error, ...e}) }}> <Form onSubmit={onSubmit}> <TextField source="name" label="이름" validate={[minLength(3), maxLength(6)]} /> <TextField source="password" label="패스워드" validate={[minLength(6), maxLength(12)]} /> <CheckboxField source="confirm" label="위 내용이 제출됩니다 동의하십니까?" validate={[checked]} /> </Form> </InfoContext.Provider>위 코드에서 setError update해주는 로직을 // before setError: (e) => setError({...error, ...e}) // after setError: (e) => setError(prev => ({...prev, ...e}))아래와 같은 형식으로 바꿔주면, 리팩토링 이전과 같이 동작을 하게됩니다.batch의 문제인지, 불변성의 문제인지 정확히 모르겠네요. 설명해주시면 감사감사!
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 백엔드 코스
nestjs autoSchemaFile에러
import { ApolloDriver, ApolloDriverAsyncConfig as ad } from '@nestjs/apollo'; import { Module } from '@nestjs/common'; import { GraphQLModule } from '@nestjs/graphql'; import { AppController } from './app.controller'; import { AppService } from './app.service'; @Module({ imports: [ GraphQLModule.forRoot<ad>({ // forRoot의 데이터타입지정 <> -> 제네릭 부분 driver: ApolloDriver, autoSchemaFile: 'src/commons/graphql/schema.gql', }), ], controllers: [AppController], providers: [AppService], }) export class AppModule {} import { Field, Int, ObjectType } from '@nestjs/graphql'; @ObjectType() // graphql에서 type을 의미함 예)type Board export class Board { @Field(() => Int) // Int를 import를 해서 사용해야한다 number: number; // ;을 기준으로 구분함 @Field(() => String) // graphql을 위한 용도 writer: string; @Field(() => String) title: string; @Field(() => String) contents: string; } 단순히 graphql shema를 자동생성 해주는 거만 테스트할려고했는데 경로를 잡아주니 에러가나와서 true도 해보고 playground : true도 추가해보고했는데 계속 해서 오류가 나고 계속해서 오류는 type이 존재하지않는다고해서 이유를 모르겠습니다 Argument of type '{ driver: typeof ApolloDriver; autoSchemaFile: string; }' is not assignable to parameter of type 'ApolloDriverAsyncConfig'.Object literal may only specify known properties, and 'autoSchemaFile' does not exist in type 'GqlModuleAsyncOptions<ApolloDriverConfig, GqlOptionsFactory<ApolloDriverConfig>>'.ts(2345)
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 백엔드 코스
관계등록 강의에서 product service 파일의 create 함수 생성시 문법 관련 질문
해당 강의에서 product service의 create 함수를 아래와 같이 코딩하는 것을 가르쳐주셨는데요.아래 코드에서const tags = [...prevTags, ...newTags.indentifiers];부분에서 prevTags에도 .identifiers가 붙어야 될 것같다는 생각을 했습니다.prevTags는 this.productsTagsRepository.find 함수를 통해서 찾아오는데, 이는 where 조건문에 의해 name이 tagNames인 것을 찾아내어 productTags의 프로퍼티인 id와 name을 둘다 return 하지 않나요?이전 조회API를 만드는 강의에서도 find 함수를 통해 id만 가져오는 것이 아닌 다른 칼럼들도 모두 가져왔었습니다.그런데 prevTags 뒤에 .indentifiers를 붙이니 에러가 뜨더라구요...분명 조회API 강의에서는 find를 통해 모든 칼럼을 다 가져왔던것 같은데, 왜 이번에는 똑같은 find 함수를 통해 id만 리턴이 되는 건가요? async create({ createProductInput }: IProductServiceCreate): Promise<Product> { const { productSalesLocation, productCategory, productTags, ...product } = createProductInput; const result = await this.productsSalesLocationService.create({ productSalesLocation }); const tagNames = productTags.map((el) => el.replace('#', '')); const prevTags = await this.productsTagsRepository.find({ where: { name: In(tagNames) }, }); const temp = []; tagNames.forEach((el) => { const isExist = prevTags.find((prevEl) => el === prevEl.name); if (!isExist) temp.push({ name: el }); }); const newTags = await this.productsTagsRepository.insert(temp); const tags = [...prevTags, ...newTags.identifiers]; const result2 = this.productsRepository.save({ ...product, productSalesLocation: result, productCategory: productCategory, productTags: tags, }); return result2; }
-
미해결따라하며 배우는 리액트 A-Z[19버전 반영]
컴파일 에러
- 학습 관련 질문을 남겨주세요. 상세히 작성하면 더 좋아요! - 먼저 유사한 질문이 있었는지 검색해보세요. - 서로 예의를 지키며 존중하는 문화를 만들어가요. - 잠깐! 인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요. const movieId = request.data.result[Math.floor(Math.random() * request.data.results.length)].id; 부분 작성 후 컴파일 시 리액트에서 Cannot read properties of undefined 에러가 발생합니다. 하나가 아니라 여러개 발생하는데 조치방법이 있을까요?
-
해결됨부트캠프에서 알려주지 않는 것들 (리액트) 1편
코드샌드박스 주소
강의하시는 예제를 코드샌드박스에서 열고싶은데 링크가 어디있나요??
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 백엔드 코스
API 1:1 관계등록 및 1:다 관계등록 관련 질문
안녕하세요!강의 잘 듣고 있는 학생입니다. 1:1관계등록 강의에서는 product sales location 관계를 등록할 때는 따로 sale location에 대한 모듈 파일과 리졸버 파일은 만들지 않고 서비스 파일만 만들어서 관계를 등록하였는데,1:다 관계등록 강의에서는 product category에 대한 모듈파일과 리졸버 파일까지 만들어 관계등록을 하는 것으로 가르쳐주셨습니다.코드 구성은 크게 다르지 않은 것 같은데, 카테고리 관계등록 강의에서는 일대다 관계이기 때문에 리졸버와 모듈파일까지 만들어서 관계등록을 하는 것인가요? 그렇다면 이유를 좀 알 수 있을까요..?코드 구성은 비슷하고, 차이라고 할 것은 1대1이냐 1대다이냐 밖에 없는 것 같은데 이렇게 모듈파일을 만들어주고 안만들어주고의 차이가 발생하는 이유가 이해가 안가서요 ㅠ
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 백엔드 코스
ERROR [TypeOrmModule] Unable to connect to the database
ERROR [TypeOrmModule] Unable to connect to the database이 에러가 일어났다 안일어났다가해요. nestjs에서 typeorm으로 mysql에 table entity를 저장해주는 과정에서 db에 접속이 안되었다. 1. TypeOrmModul.forRoot안의 오타확인 -> 없었다 2. Entity에 이상이 있는지확인 -> 없었다 3. 구글링에서는 대부분이 오타문제이거나 데이터베이스를 생성해주지않았다는 문제라고했다 -> 데이터베이스도 켜져있었고 티미널이랑 dbeaver에서도 mysql과 접속이 되고있는것으로 확인 4. 컴퓨터가 버그로 안되는 걸로 예상해 잠시 종료했다가 실행 -> 역시안됐다 5. 비밀번호를 숫자로 입력해서 string이아닌 number형식으로 작성했는데 password는 string 타입만 작성가능하다고 오류가나왔다 - 문제해결 -> root 비밀번호를 string타입으로 변경하니까 오류가 해결되었다 -> 숫자로 입력하니 넘어오는 과정에서 숫자가 string형태로 변경되어 접속오류로 판명 -> 비밀번호는 문자열로.....-> 이게 전날에 연결이 안되어서 해본결과였고 오늘 했을때에는 연결이되었는데 두번째 접속을 하니까 연결이 안되서dbeaver에서랑 터미널에서 접속을 했을때는 문제가 없었습니다.왜계속해서 이런오류가 불규칙적으로 일어나는지 모르겠습니다.그리고 두번째 질문은 nestjs독스에서는 synchronize: true,이부분을 false로 권장하고있는데 그이유로는 데이터 손상?유실이 있을수있다고 써져있는데 수업중에는 true로되어야지 동기화가 된다고 하셔서 이부분도 설명 부탁드릴수있을까요마지막으로 세번째 질문으로는 dbeaver에서재연결요청을 했을때 Datasource was invalidatedLive connection count: 2/2이렇게 나오는데 이러면 mysql이 켜져있는 상태인건가요? 해당 database는 다볼수있는데 offline인데 그전에 연결이되서 볼수있는건가하는 의심이 들어서질문드렸습니다import { ApolloDriver, ApolloDriverConfig as ad } from '@nestjs/apollo'; import { Module } from '@nestjs/common'; import { GraphQLModule } from '@nestjs/graphql'; import { BoardsModule } from './apis/boards/boards.module'; import { TypeOrmModule } from '@nestjs/typeorm'; import { Board } from './apis/boards/entities/board.entity'; @Module({ imports: [ BoardsModule, // ProductsModule, // UsersModule, GraphQLModule.forRoot<ad>({ // forRoot의 데이터타입지정 <> -> 제네릭 부분 driver: ApolloDriver, autoSchemaFile: 'src/commons/graphql/schema.gql', // 자동으로 스키마 파일을 생성 .gql로마무리 해주기 // 실행은 package.json이 있는 위치에선 // graphql은 스키마 파일이 있어야 실행이 가능하다 // 자동이든 직접 작성하든 작성해주어야한다. }), TypeOrmModule.forRoot({ type: 'mysql', host: 'localhost', // 도커할때는 네임레졸루션이 들어가야함 port: 3306, username: 'root', password: 'root', database: 'myproject', entities: [Board], // 해당하는 테이블을 작성 logging: true, // 어떻게 변형되어서 넘어가는지 디버깅 synchronize: true, // entity.ts와 db를 동기화 해주는 작업 }), ], // 합치는 부분 }) export class AppModule {}
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 백엔드 코스
면접볼 떄 알아햐 하는 것
CS는 기본으로 물어볼테고,node 개발자라면 node,자바스크립트 개념,뜻,장점,단점,예시 같은거 알면 되나요?
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 백엔드 코스
의존성주입으로 발생하는 장점 설명 질문
발생하는 장점을 다음과 같이 설명해주셨는데요.1. new 한 번으로 모든 곳에서 재사용 가능2. 의존성 주입으로 몽땅 한꺼번에 변경 가능다음과 같은 예시를 들어주셨는데, ProductController의 constructor에서 this.cashService = new CashService()와 같은 사용을 하면 constructor에서 변경점을 가져가고 해당 클래스의 모든 함수에서는 this.cashService를 통해 사용할 수 있고요.class ProductController { cashService constructor() { this.cashService = new CashService() } }CashService 대신 CashService2로 변경하고 싶을때는 다음처럼 변경하면 2번 장점도 동일해지구요.class ProductController { cashService constructor() { //this.cashService = new CashService() this.cashService = new CashService2() } }의존성 주입을 통해 얻을 수 있는 이점은 위와 같은 재사용이나 변경에 대한 장점보다도 말 그래도 의존성을 없애는 것에 있다고 보는데요.의존성 주입을 통해 ProductController에서 구현체인 CashService에 대한 의존성을 없애고, 외부에서 CashService에 대한 의존성을 가져갈 수 있게 되니까요.CashService에 대한 코드의 변경으로 인한 ProductController의 코드 변경이 발생하지 않도록 하는 것이 의존성 주입의 핵심이라고 보는데, tight-coupling을 왜 loose-coupling으로 변경해주어야 하는지에 대한 설명은 없었던 거 같아서요. 이 부분에 대해 어떻게 생각하시는지 궁금합니다!