묻고 답해요
167만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결[코드팩토리] [초급] NestJS REST API 백엔드 완전 정복 마스터 클래스 - NestJS Core
@Column({unique: true})와 @PrimaryColumn()의 차이
3:23 (nickname에 unique: true 적용)다름이 아니라 중복을 허용하지 않을 때 @Column({ unique: true })를 해도 되지만 @PrimaryColumn()을 해도 되지 않나해서 여쭤봅니다! 혼자 리서치해본 바로는 PrimaryColumn은 식별자로써 쓰일 수 있으면 쓰고 @Column({ unique: true})는 식별자로 쓰진 않아도 될 때 적용한다는 얘기를 들었습니다. 그런데 식별자가 많아서 나쁠건 없지 않나? 싶기도 하고 nickname을 식별자로 쓸 가능성도 있으면 좋을거 같기도 해서 PrimaryColumn으로 해도 괜찮을거 같다는 생각이 들었습니다.PrimaryColumn이 한 테이블에 너무 여러개 존재하면 안 좋다거나 그런 컨벤션이 있는 것일까요?
-
미해결[코드팩토리] [초급] NestJS REST API 백엔드 완전 정복 마스터 클래스 - NestJS Core
PUT 요청 시 @Body()에 ?를 붙이면 서비스 함수 인자도 optional이어야 하나요?
코드팩토리 디스코드에 질문하면 더욱 빠르게 질문을 받아 볼 수 있습니다![코드팩토리 디스코드]https://bit.ly/3HzRzUM - 학습 관련 질문을 남겨주세요. 상세히 작성하면 더 좋아요! - 먼저 유사한 질문이 있었는지 검색해보세요. - 서로 예의를 지키며 존중하는 문화를 만들어가요. - 잠깐! 인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요.강사님, PUT 요청에서 컨트롤러에서는 @Body()를 optional (?)로 받았는데,서비스 함수에서는 인자를 필수(string)로 선언하면 TypeScript 에러가 납니다.이럴 땐 서비스 함수의 author, title, content를 string? 또는 string | undefined로 바꿔줘야 하는 게 맞을까요?
-
해결됨[코드팩토리] [초급] NestJS REST API 백엔드 완전 정복 마스터 클래스 - NestJS Core
pagination Frontend
안녕하세요!pagination 강의를 듣고 서버에서 front로 보내는 방법은 정확히 이해했습니다.감사합니다. 그런데 frontend에서 어떠한 방식으로 처리해야 하는지 감이 안 옵니다. 대략적으로 front에서 20개씩 요청하는 방식을 어떻게 해야 하는지 설명 부탁 드립니다. 그리고 혹시, 강사님이 해주시는 frontend pagination 강의가 있으면 추천 부탁 드립니다.
-
해결됨[코드팩토리] [초급] NestJS REST API 백엔드 완전 정복 마스터 클래스 - NestJS Core
@IsPublic( )
37강 (모든 Route 기본 Private로 만들고 IsPublic Annotation 작업하기) 강의 에서8분 50초에 아래의 코드에 @IsPublic을 해줘도 아래 가드를 통과해야 해서 괜찮다고 말씀해주셨는데요. //access 토큰 재발급 @Post('token/access') @IsPublic() // 여기가 퍼블릭이여도 밑에서 가드를 통과해야하기 때문에 괜찮다. @UseGuards(RefreshTokenGuard) postTokenAccess(@Headers('authorization') rawToken: string) { // 여기서 받는 rawToken은 Bearer 이다. const token = this.authService.extractTokenFromHeader(rawToken, true); // token은 refresh 토큰이다. false를 같이 던져줘서 acess 토큰이 나온다. const newToken = this.authService.rotateToken(token, false); /** * {accessToken: {token}} 이러한 형태로 리턴 */ return { accessToken: newToken }; } //refresh 토큰 재발급 @Post('token/refresh') @IsPublic() @UseGuards(RefreshTokenGuard) postTokenRefresh(@Headers('authorization') rawToken: string) { // 여기서 받는 rawToken은 Bearer 이다. const token = this.authService.extractTokenFromHeader(rawToken, true); // token은 refresh 토큰이다. true를 같이 던져줘서 acess 토큰이 나온다. const newToken = this.authService.rotateToken(token, true); /** * {refreshToken: {token}} 이러한 형태로 리턴 */ return { refreshToken: newToken }; } AccessTokenGuard, RefreshTokenGuard 모두 BearerTokenGuard를 먼저 수행하기 때문에 req에 IsRoutePublic가 true로 되어 있어서 AccessTokenGuard, RefreshTokenGuard 이 두 개 모두 바로 통과하는 것으로 알고 있습니다.이렇게 되면 IsPublic 어노테이션을 사용한 상황에서는 전역으로 설정된 AccessTokenGuard는 통과하게 됩니다. 그리고 "token/access" API에 설정된 RefreshTokenGuard도 물론 통과하게 됩니다. 이렇게 되면 RefreshTokenGuard는 어디에서도 사용할 수 없는 게 아닐까요??///////////////정리////////////////////////////////% 토큰 재 발급하는 상황이라고 가정 %IsPublic 어노테이션 설정됨 -> AccessToken 통과, RefreshTokenGuard 통과 BearerTokenGuard 통과RefreshTokenGuard도 통과즉, refreshToken 인지 검증 불가능 IsPublic 어노테이션 설정됨 -> AccessToken 검증 재검증 로직이므로 refresh 토큰을 보냈으므로 AccessToken 검증에서 accessToken이 아니라고 걸림 즉, RefreshTokenGuard는 사용할 수 없게 되는게 아닌가요?
-
미해결[코드팩토리] [초급] NestJS REST API 백엔드 완전 정복 마스터 클래스 - NestJS Core
회원가입
안녕하세요 @Post('register/email') @IsPublic() // 여기가 퍼블릭이여도 밑에서 가드를 통과해야하기 때문에 괜찮다. postRegisterEmail(@Body() body: RegisterUserDto) { return this.authService.registerWithEmail(body); }위 코드처럼 회원가입을 할 때, 클라이언트에서 email, password를 보내주게 됩니다.로그인할 때는 basic 토큰으로 email, password를 base64해서 암호화하여 보내는데 회원가입할 때는 클라이언트측에서 그냥 Body에 email, password를 노출시켜서 보내도 상관없는 건가요?
-
미해결풀스택 리액트 토이프로젝트 - REST, GraphQL (for FE개발자)
질문있습니다 !
typescript 버전 코드를 보고 있는데 package.json에 module:common.js로 되어있는데 어떻게 Import 구문을 사용할 수 있는지 궁금합니다
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 백엔드 코스
도커볼륨 마운트 관련
프로젝트 구성DockerfileFROM node:14 RUN apt-get update && apt-get install -y bash COPY ./package.json /myfolder/ COPY ./yarn.lock /myfolder/ WORKDIR /myfolder/ RUN yarn install COPY . /myfolder/ CMD ["yarn", "start:dev"]docker-compose.yamlversion: "3.7" services: node-server: build: context: . dockerfile: Dockerfile volumes: - ./index.js:/myfolder/index.js - ./email.js:/myfolder/email.js ports: - 3000:3000 database-server: image: mongo:5 ports: - 27017:27017 Window 환경입니다.위와 같을 때index.js 파일을 수정하여도docker로 연동된 nodemon 재 실행이 안됩니다. docker-desktop 에서 container 에서보면 mount 라고 표기되어있고위의 새로고침 버튼을 누르면 제대로 적용 됩니다.원인이 뭘까요?
-
미해결[개정판 2023-11-27] Spring Boot 3.x 를 이용한 RESTful Web Services 개발
강의에서나온 화면 피피티
강의에서나온 화면 피피티같은 파일은 없나요?
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 백엔드 코스
findOne 타입스크립트오류
import { Injectable } from '@nestjs/common'; import { Repository } from 'typeorm'; import { Product } from './entities/product.entity'; import { InjectRepository } from '@nestjs/typeorm'; import { IProductServiceCreate, IProductServiceFindOne, } from './interfaces/products-service.interface'; @Injectable() export class ProductsService { constructor( @InjectRepository(Product) private readonly productsRepository: Repository<Product>, ) {} findAll(): Promise<Product[]> { return this.productsRepository.find(); } findOne({ productId }: IProductServiceFindOne): Promise<Product> { // @ts-ignore return this.productsRepository.findOne({ where: { id: productId } }); } create({ createProductInput }: IProductServiceCreate): Promise<Product> { const result = this.productsRepository.save({ ...createProductInput, // 하나하나 직접 나열하는 방식 // name: '마우스', // description: '좋은 마우스', // price: 3000, }); return result; } } 이코드가 제코드인데 findOne 메서드에서 // @ts-ignore를 하지 않으면 Promise<Product | null>' 형식은 'Promise<Product>' 형식에 할당할 수 없습니다. 'Product | null' 형식은 'Product' 형식에 할당할 수 없습니다. 'null' 형식은 'Product' 형식에 할당할 수 없습니다.라는 에러가 뜹니다 어떻게 해야하나요?
-
미해결[코드팩토리] [초급] NestJS REST API 백엔드 완전 정복 마스터 클래스 - NestJS Core
@VersionColumn() save 관련 질문
@VersionColumn() 관련하여'save()함수가 몇번 불렸는지 기억한다' 라고 하셔서 save함수가 불린 횟수에 따라 1씩 증가하는 것으로 처음에 이해를 했었는데, 강의 영상과 조금 다르게 service & controller 나눠 작성하는 연습을 하다가 아래와 같이 title을 동일한 값으로 수정하는 코드를 작성했었습니다async PatchUsers(id: string) { const user = await this.userRepository.findOne({ where: { id, }, }); if (!user) { throw new NotFoundException(); } console.log('Before save - Version:', user.version); if (user) { user.title = '수정하기'; } const newUser = await this.userRepository.save(user); console.log('After save - Version:', user.version); return newUser; }이때 title이 이전과 동일하면 실제로 save함수는 실행이 되지만 DB상에 변화가 없기 때문에 @VersionColumn() 으로 정의한 version에는 변화가 없는 것 같은데 save함수의 실행횟수보다 db의 변화가 있는지에 초점을 맞춰서 생각하면 될까요 ?
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 백엔드 코스
http => htrtps 호출 인증서 신뢰 오류
self-signed certificate in certificate chain 발생합니다.1번process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';2번// SSL 인증 무시를 위한 Agent 생성 const httpsAgent = new https.Agent({ rejectUnauthorized: false });await axios.get("target_url", { httpsAgent: agent });1,2 번 외 해결 방법이 있을까요?또는 2번을 적용하려면 어떻게 해야하나요? 또는 Java에서 로컬 톰캣 서버에서 HTTPS 설정하듯이 할수있는 방법이 있나요?
-
해결됨[코드캠프] 부트캠프에서 만든 고농축 백엔드 코스
self-signed certificate in certificate chain 에러 발생
안녕하세요.self-signed certificate in certificate chain에러 발생합니다,
-
미해결[개정판 2023-11-27] Spring Boot 3.x 를 이용한 RESTful Web Services 개발
HelloWorldBean 관련 에러
`java: constructor HelloWorldBean in class mystudy.myrestfulservice.bean.HelloWorldBean cannot be applied to given types;required: no argumentsfound: java.lang.Stringreason: actual and formal argument lists differ in length`라는 오류 메시지가 자꾸 떠서 강의 진행이 어렵습니다.package mystudy.myrestfulservice.bean; import lombok.AllArgsConstructor; import lombok.Data; @Data @AllArgsConstructor public class HelloWorldBean { private String message; } package mystudy.myrestfulservice.controller; import mystudy.myrestfulservice.bean.HelloWorldBean; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; @RestController public class HelloWorldController { // GET // URI - /hello-world // @RequestMapping(method = RequestMethod.GET , path = "/hello-world") @GetMapping(path = "/hello-world") public String helloWorld() { return "Hello World!"; } @GetMapping(path = "/hello-world-bean") public HelloWorldBean helloWorldBean() { return new HelloWorldBean("Hello World"); } @GetMapping(path = "/hello-world-bean/path-variable/{name}") public HelloWorldBean helloWorldBeanPathVariable(@PathVariable String name) { return new HelloWorldBean(String.format("Hello World %s", name)); } }Enable Annotation Processing 체크하기 ,리빌드, 캐시 삭제, 재부팅, 롬복 재설치, 프로젝트 다시 생성하기 별에 별 방법을 써도 안됩니다...
-
해결됨Open API 사용 with 파이썬
참고 사이트는 어디에서 확인이 가능할가요
참고 사이트 다운 받을 수 있는 경로는 어디일가요교수님.
-
해결됨한 번에 끝내는 자바스크립트: 바닐라 자바스크립트로 SPA 개발까지
TabBar.js 오류가 자꾸 발생하는데 무슨이유인지 모르겠습니다;;
전체 사진 처음 화면은 로딩 되서 잘나오는데 펭귄이나 다른탭을 클릭하면 아래와 같은 오류가 나오는데 TabBar.js onclick 함수가 아니라는데;; 왜이런건지 함수가 맞는데 아래에 제가 작성한 코드 입니다 검토 좀 부탁드립니다.^^;;TabBar.jsexport default function TabBar({ $app, initialState, onClick }) { // TabBar 클래스를 생성합니다. 초기값과 클릭 이벤트를 받습니다. this.state = initialState; // 초기값 설정 this.onClick = onClick; // 클릭 이벤트 설정 this.$target = document.createElement("div"); // 새로운 div 요소를 생성합니다. this.$target.className = "tab-bar"; // div 요소에 클래스 이름을 추가합니다. $app.appendChild(this.$target); // $app 요소에 div 요소를 추가합니다. this.template = () => { let temp = `<div id="all">전체</div><div id="penguin">펭귄</div> <div id ="koala">코알라</div><div id ="panda">판다</div>`; // 전체 탭을 추가합니다. return temp; // temp를 반환합니다. }; this.render = () => { // 렌더링 함수 this.$target.innerHTML = this.template(); // div 요소의 innerHTML을 template 함수의 반환값으로 설정합니다. let $currentTab = document.getElementById(this.state); // 현재 탭을 선택합니다. // $currentTab ? ($currentTab.className = "clicked") : ""; // 현재 탭이 존재하면 clicked 클래스를 추가합니다. 없으면 변화없음. $currentTab && ($currentTab.className = "clicked"); // && 연산자를 사용하여 현재 탭이 존재하면 clicked 클래스를 추가합니다. const $tabBar = this.$target.querySelectorAll("div"); // 모든 div 요소를 tabBar 요소에 담아온다. $tabBar.forEach((elm) => { elm.addEventListener("click", () => { // 각 div 요소에 클릭 이벤트 리스너를 추가합니다. this.onClick(elm.id); // 클릭한 div 요소의 id를 onClick 함수에 전달합니다. }); }); }; this.setState = (newState) => { // state를 변경하는 함수 this.state = newState; // state를 새로 받은 newState로 업데이트합니다. this.render(); // state가 변경되면 렌더링 함수를 다시 호출하여 화면을 업데이트합니다. }; this.render(); // 렌더링 함수를 호출합니다. } App.jsimport TabBar from "./components/TabBar.js"; // TabBar.js 파일을 불러옵니다. import Content from "./components/Content.js"; // Content.js 파일을 불러옵니다. import { request } from "./components/api.js"; // api.js 파일을 불러옵니다. export default function App($app) { // App 생성자 함수를 생성합니다. // $app은 App 컴포넌트가 렌더링될 DOM 요소입니다. this.state = { //state 초기값 설정 currentTab: "all", // 탭 초기값 설정 tabbar 컴포넌트에 전달할 현재 탭 데이터 photos: [], // 사진 초기값 설정 content 컴포넌트에 전달할 사진 데이터 }; const tabbar = new TabBar({ $app, // App 컴포넌트가 렌더링될 DOM 요소를 전달합니다. initialState: "", // 초기값 설정 oncClick: async (name) => { // 클릭 이벤트 설정 변경값을 currentTab에 저장 this.setState({ // 클릭한 탭의 데이터를 state에 저장합니다. ...this.State, // 기존 state를 복사합니다. 스프레드 연산자 currentTab: name, // 클릭한 탭의 이름을 currentTab에 저장합니다. photos: await request(name === "all" ? "" : name), // 클릭한 탭의 새로운 사진을 request 이름으로 함수를 불러와 저장합니다. // request 함수는 비동기 함수로 async await를 사용하여 데이터를 받아옵니다. }); }, }); const content = new Content({ $app, // App 컴포넌트가 렌더링될 DOM 요소를 전달합니다. initialState: [], // 초기값 설정 }); this.setState = (newState) => { // 업데이트 값을 newState로 받습니다. this.state = newState; // state를 새로 받은 newState로 업데이트합니다. tabbar.setState(this.state.currentTab); // tabbar 컴포넌트에 state를 전달합니다. content.setState(this.state.photos); // content 컴포넌트에 state를 전달합니다. }; const init = async () => { //웹페이지가 로드되면 실행되는 함수 try { const initialPhotos = await request(); // request 함수를 불러와 initialPhotos에 저장합니다. this.setState({ // state를 initialPhotos로 업데이트합니다. ...this.state, // 기존 state를 복사합니다. 스프레드 연산자 photos: initialPhotos, // initialPhotos를 photos에 저장합니다. }); } catch (err) { console.log(err); } }; init(); // 웹애플리케이션이 실행될때 init 함수를 실행합니다. } index.jsimport App from "../src/App.js"; const $app = document.getElementById("app"); new App($app); api.jsconst API_URL = "https://animal-api-two.vercel.app"; // 이미지 url을 변수에 저장 // const $content = document.querySelector("div.content"); //(api 불러오는 코드만 남겨놓기 위해 삭제제) // let template = []; // (api 불러오는 코드만 남겨놓기 위해 삭제제) //API export const request = async (name) => { const res = await fetch(name ? `${API_URL}/${name}` : API_URL); // fetch 함수를 사용하여 API_URL을 호출합니다. name이 있으면 name을 호출합니다. 없으면 API_URL을 호출합니다. try { if (res) { let data = await res.json(); return data.photos; } } catch (err) { console.log(err); } }; index.html<!DOCTYPE html> <head> <title>Animal Album</title> <meta charset="UTF-8" /> <link rel="stylesheet" href="../project2/src/style.css" /> <script type="module" src="../project2/src/index.js" defer></script> </head> <body> <div id="app"> <!-- TAB BAR --> <!-- CONTENT --> </div> </body> content.jsexport default function Content({ $app, initialState }) { this.state = initialState; this.$target = document.createElement("div"); this.$target.className = "Content"; $app.appendChild(this.$target); this.template = () => { let temp = []; if (this.state) { this.state.forEach((elm) => { temp += `<img src="${elm.url}"></img>`; }); } return temp; }; this.render = () => { this.$target.innerHTML = this.template(); }; this.setState = (newState) => { this.state = newState; this.render(); }; this.render(); } 콘솔 오류코드 TabBar.js:26 Uncaught TypeError: this.onClick is not a function at HTMLDivElement.<anonymous> (TabBar.js:26:14)
-
해결됨실리콘밸리 엔지니어가 가르치는 파이썬 장고 웹프로그래밍
Logging 질문
LOGGING ={ 'version':1, 'disable_existing_loggers':False, 'handlers':{ 'file':{ 'level':'DEBUG', 'class':'logging.FileHandler', 'filename':os.path.join(BASE_DIR, 'logs/django.log'), 'formatter':'json', }, 'console':{ 'class':'logging.StreamHandler', 'formatter':'json', }, }, 'formatters':{ 'json':{ 'class': 'pythonjsonlogger.jsonlogger.JsonFormatter', 'format': '%(asctime)s %(levelname)s %(name)s %(message)s', }, }, 'root':{ 'handlers':['file','console'], 'level':'DEBUG', }, 'loggers':{ 'django':{ 'handlers':['file','console'], 'level': 'DEBUG', 'propagate':False, }, }, runserver 하는 순간 {"asctime": "2025-02-14 20:41:50,823", "levelname": "DEBUG", "name": "django.utils.autoreload", "message": "File C:\\Users\\moon\\miniforge3\\envs\\workout\\Lib\\site-packages\\PIL\\__init__.py first seen with mtime 1739352505.781736"} 이런 변경한 적 없는 것들이 자동리로드 되면서 콘솔에 계속 올라옵니다. 이유가 궁금합니다.
-
해결됨한 번에 끝내는 자바스크립트: 바닐라 자바스크립트로 SPA 개발까지
Header에서 정렬기준
Header에서 total, cost, fun 등 정렬 값이 바뀌는 건 알겠는데, 이 값이 바뀔 때 점수가 높은순으로 정렬이 되는데, 이 정렬을 지정해주는 실행 코드가 어디에 있는지 모르겠어요. <div class="filter"> <select id="sortList" class="sort-list"> <option value="total" ${sortBy === 'total' ? 'selected' : ''}>Total</option> <option value="cost" ${sortBy === 'cost' ? 'selected' : ''}>Cost</option> <option value="fun" ${sortBy === 'fun' ? 'selected' : ''}>Fun</option> <option value="safety" ${sortBy === 'safety' ? 'selected' : ''}>Safety</option> <option value="internet" ${sortBy === 'internet' ? 'selected' : ''}>Internet</option> <option value="air" ${sortBy === 'air' ? 'selected' : ''}>Air Quality</option> <option value="food" ${sortBy === 'food' ? 'selected' : ''}>Food</option> </select> </div>
-
미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part6: 웹 서버
클래스 라이브러리 (.NET Core)이 없으면 클래스 라이브러리 선택하시면 됩니다.
클래스 라이브러리 (.NET Framework)는 아니에요~
-
미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part6: 웹 서버
NET 9.0 버전에서의 레이아웃 적용
아래 내용과 함께 .css파일도 추가해보세요https://learn.microsoft.com/ko-kr/aspnet/core/blazor/components/layouts?view=aspnetcore-9.0 레이아웃 네임스페이스를 사용할 수 있도록 설정프레임워크에 대해 시간이 지남에 따라 레이아웃 파일 위치 및 네임스페이 Blazor 스가 변경되었습니다. 빌드하는 앱의 BlazorBlazor 버전 및 유형에 따라 레이아웃의 네임스페이스를 사용할 때 표시해야 할 수 있습니다. 레이아웃 구현을 참조할 때 레이아웃의 네임스페이스를 표시하지 않고 레이아웃을 찾을 수 없는 경우 다음 방법 중 어느 것이든 수행합니다.@using 레이아웃의 위치에 대한 지시문을 _Imports.razor 파일에 추가합니다. 다음 예제에서는 이름이 Layout 있는 레이아웃 폴더가 폴더 내에 Components 있고 앱의 네임스페이스는 다음과 같습니다 BlazorSample.razor복사@using BlazorSample.Components.Layout 레이아웃이 @using 사용되는 구성 요소 정의의 맨 위에 지시문을 추가합니다.razor복사@using BlazorSample.Components.Layout @layout DoctorWhoLayout 사용되는 레이아웃의 네임스페이스를 정규화합니다.razor복사@layout BlazorSample.Components.Layout.DoctorWhoLayout
-
미해결[개정판 2023-11-27] Spring Boot 3.x 를 이용한 RESTful Web Services 개발
Swagger API 3.x 오류..
사진과 같이 뜹니다. 강사님과 다른 코드가 없는 것 같은데 이러네요..ㅠ 방법이 있을까요?