10달 전 · 성지수 님의 질문
micro repo 세팅하면서 격은 문제(같은 문제 격는 분들 댁글)
이번 프로젝트에서 하나의 레포지토리에서 client, server, admin, common 4가지 패키지를 만들었습니다. client, server, admin은 common을 의존하도록 모노레포로 만들었고, client는 admin을 의존할 수 있게 micro로 만들었습니다. 간단한 패키지 설명: - client: 메뉴 헤더 등 구현, 페이지는 admin을 remote 해서 사용, React로 구현 - admin: 페이지에 나오는 콘텐츠의 전반적인 부분이 컴포넌트로 되어있음, React로 구현 - server: Node.js로 되어있고 실제 Spring 서버에서 준 데이터를 포맷하는 형태 - common: 공통 컴포넌트, 라벨 등 문제1: 다른 프로젝트에서 expose 되어있는 Next.js 프로젝트(scss로 스타일 구현)를 client에서 사용할 때 의존성 관련 오류가 생깁니다. client의 package.json에서 peerDependencies로 next를 설정해줘야 하는지, 양쪽 패키지(다른 프로젝트와 client)에서 Next.js와 React를 share 설정을 해야 되는지 잘 모르겠습니다. 여러 방법으로 시도는 해봤지만 의존성 오류나 Next.js에서 훅을 사용 못하는 오류 때문에 해결하지 못하고 있습니다. 문제2: 빌드 최적화를 위해 트리쉐이킹이나 코드 스플리팅을 해야 합니다. 웹팩에서 아래와 같이 코드 스플리팅을 하면 청크 파일 이름이 겹치기 때문에 filename을 해시값으로 설정해야 합니다. 여기서 문제가 생기는데, micro의 client처럼 remote 하는 부분에서 remote.js, app.js 청크가 필요하기 때문에 이름이 해시값으로 바뀌면 해당 청크를 찾을 수 없습니다. 또한 ModuleFederationPlugin이 빌드 시 자동으로 코드 스플리팅을 해준다는 이야기도 있는데, 이 부분은 정확하지 않습니다. 저와 같은 문제를 격고 있거나 해결하신 분들 같이 나눴으면 합니다.
개발자
#micro
#react
#monorepo
#nextjs
#build
답변 0
댓글 0
조회 34
일 년 전 · 성지수 님의 질문 업데이트
마이크로 프론트 구현(Nextjs, React)
요구사항 마이크로 프론트엔드로 A라는 프로젝트에서 B라는 프로젝트의 컴포넌트를 사용하고 싶다 프로젝트 설명 ModuleFederationPlugin 사용해서 expose remote 설정 A 프로젝트 (remote) : react, styled-component 사용 B 프로젝트 (expose) : nextjs, scss 사용 첫번째 오류 styled 이 달라서 nextjs 에서 노드가 불러와지지 않는 것 해결 : <noscript id="**next_css__DO_NOT_USE**"></noscript> → 두번째 오류 발생 오류 내용 Cannot read properties of null (reading 'parentNode') TypeError: Cannot read properties of null (reading 'parentNode') at options.insert (webpack- 두번째 오류 Nextjs 에서 expose 할 때 Page 컴포넌트에 있는 useState를 사용 못한다고함 해결 : peerDependencies 로 nextjs 추가 → 오류동일 오류 내용 TypeError: Cannot read properties of null (reading 'useState') at useState (react.development.js:1623:21) at Page (index.js:8:40) react-dom.development.js:18704 The above error occurred in the <Page> component: 참고 : https://dev.to/omher/building-react-app-with-module-federation-and-nextjsreact-1pkh 두번째 오류를 해결해야 되는데 가능한 방법인지 모르겠습니다. 아시는 분은 댁글 남겨주세요~(코드상에 보안상 문제되는 부분은 a b 로 바꿨습니다.
개발자
#micro-frontend-architecture
#react
#next.js
#modulefederationplugin
답변 0
댓글 0
조회 288
일 년 전 · 익명 님의 질문
next js 프로젝트 mfa 구축 질문.
안녕하세요, next js프로젝트로 mfa를 구축중입니다. 모노레프 기반으로 구축중인데요, 타입스크립트를 적용하기 위해서 @module-federation/typescript 모듈설치후 next.config설정을 했는데, 아래와 같은 에러로그가 발생하면서 @mf-types폴더가 자동으로 생성되지않고있습니다.. 덕분에 리모트 파일은 타입에러를 뱉고 있는 상황이구요, 혹시 next js프로젝트로 mfa구축하신분들중 저와같은 사례가 있으신분 계신가요? 에러 내용 [1] <e> [FederatedTypesPlugin] Unable to download 'container' remote types index file: timeout of 3000ms exceeded [1] <e> [FederatedTypesPlugin] Unable to download types from remote 'container'
개발자
#react
#nextjs
#mfa
답변 0
댓글 0
조회 124
일 년 전 · 익명 님의 질문
채팅 디비 설계 질문이요!
안녕하세요:) 저는 ! 웹소켓과 관계형디비+프리즈마 를 이용해서 백엔드를 구성하고, 리액트로 만든 프론트 와 양방향 채팅 서비스를 만들려고 합니다! 채팅방 DB스키마를 작성하는데 어려움을 겪어 질문을 남깁니다. 현재 프리즈마에서 model ChatRoom { id Int @id @default(autoincrement()) name String creatorId Int users ChatRoomUser[] messages Message[] createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } model ChatRoomUser { id Int @id @default(autoincrement()) userId Int // 외부 API에서 가져올 사용자 ID chatRoomId Int chatRoom ChatRoom @relation(fields: [chatRoomId], references: [id]) createdAt DateTime @default(now()) updatedAt DateTime @default(now()) @@unique([userId, chatRoomId]) } model Message { id Int @id @default(autoincrement()) chatRoomId Int senderId Int // 외부 API에서 가져올 사용자 ID receiverId Int? // 선택적 필드, 단체 채팅에서는 null content String timestamp DateTime @default(now()) chatRoom ChatRoom @relation(fields: [chatRoomId], references: [id]) createdAt DateTime @default(now()) updatedAt DateTime @default(now()) } 이런식으로 구현하였는데 조언좀 부탁드립니다.ㅠㅠ
개발자
#db
#스키마
#node
#prisma
#설계
답변 0
댓글 0
보충이 필요해요 1
조회 81
일 년 전 · 익명 님의 새로운 답변
React Native android emulator 질문있습니다.
native 공부중에 제가 React Native Debugger를 다운받아서 사용할려고 하는데, 사진과 같이 Menu에 Debug 혹은 debug js remotely 가 없더라구요 Open Debugger 누르면 filpper 다운 받으라고 하는데... 연결을 못해서 console를 못보면서 하니 어떻게 해야할까요? 기기는 ( android 13.0 Tiramisu 사용중입니다.)
개발자
#native
답변 1
댓글 0
추천해요 1
조회 255
일 년 전 · 방재호 님의 답변 업데이트
[Js] 함수 매개변수 전달에 대하여...
안녕하세요! 이제 막 1년 좀 넘은 주니어 개발자 입니다. 공부 중에 한 가지 궁금한 점이 생겨서 선생님들께 여쭤보려합니다. js 함수를 작성하는 중에 매개변수로 event를 전달하려 했더니 event에 취소선이 생성됩니다... 예시) - html - <div class='.card'> ... <button id="deleteCard" onclick="deleteCard(event)">삭제</button> </div> - js - function deleteCard(event){ let card = $(event.target).closest('.card').remove(); }; 위와 같이 작성했는데 함수 실행은 되긴 하는데 매개변수 event에 취소선이 생기니 잘못된 것 같아서 여쭤봅니다... 취소선이 생기는 이유와 문제가 된다면 어떤 점에서 문제가 생기는지 개선점은 뭐가 있는지 궁금해서 문의 남깁니다.
개발자
#javascript
#매개변수
답변 1
댓글 0
조회 81
일 년 전 · 장성호 님의 답변 업데이트
docker container 내부의 spring boot 서버에서 client 의 ip 주소 알아내는 방법
안녕하세요 지금 만들고 있는 서비스가 설치형 어플리케이션에, 리눅스 파일 시스템을 사용해야해서 처음부터 docker 환경으로 spring boot 서버 환경을 세팅하고 시작했습니다. 순조롭게 진행하다가 한 부분에서 막히게 되었는데요, spring boot 서버 내에서 현재 요청한 클라이언트의 ip를 기존에 등록한 아이피와 비교하여 다른 아이피일 경우 요청을 거부하는 보안 로직을 구현해야하는 부분입니다. 문제가 되는 부분은 요청한 클라이언트의 ip를 알아내는 부분인데요 원래 하던것과 같이 HttpServletRequest 객체에서 getRemoteAddr() 메소드를 호출하여 아이피를 출력해보니 클라이언트의 아이피가 아닌 다른 아이피가 잡히는겁니다. 정황상 host 에서 컨테이너로 포트포워딩을 하다보니 본래 클라이언트의 아이피가 아니라 Docker 네트워크의 아이피가 나온 것 같습니다. 혹시라도 포워딩 헤더가 있을까 하여 헤더를 까봤지만 헤더에 있지도 않더라구요.. GPT에게 자문을 구해보니 두가지를 추천해주더군요. 1. container의 network를 host로 설정하라 이건 알아보니 리눅스에서만 작동하는거랍니다 제 어플리케이션은 리눅스에 설치될수도 있고 윈도우에 설치될 수도 있는데 말이죠.. 2. Nginx 같은 프록시 서버를 둬라 호스트에 프록시를 둬서 본래의 아이피를 헤더에 추가하든 어떻게든 해서 본래의 아이피를 스프링에 전달해주라는 말로 이해했습니다. 플랫폼 독립적으로 설치하기 위해서 Docker를 채용했는데 호스트에 추가적인 서버를 설치하라뇨… 이것도 좀 아닌 것 같습니다.. 막막합니다… 괜히 Docker 들여왔나 싶기도 하고, 보안 인증때문에 이 기능을 지원 안할수도 없고.. 도와주십쇼..!
개발자
#docker
#spring-boot
답변 1
댓글 5
조회 1,269
10달 전 · 이경도 님의 답변 업데이트
Jpa 커스텀 리포지토리 다중 상속 문제
커스텀 리포지토리 사용중 문제가 발생하여 질문 드립니다. @Repository public interface UserRepository extends JpaRepository<User, Long>, CustomRepository { Optional<User> findByUserId(String userId); } public interface CustomRepository { Long search(User user); } public class ACustomRepositoryImpl implements CustomRepository { @Override public Long search(User user) { return 1L; } } 이런식으로 코드를 작성하고 실행 시키면 아래와 같은 에러 메시지가 나옵니다. 그런데 ACustomRepositoryImpl 구현체 이름을 CustomRepositoryImpl 이렇게 바꾸면 정상적으로 실행됩니다. 명명규칙이 그저 개발자들 간의 약속 인줄 알았는데 규칙을 무조건 지켜야 하는 건지 궁금하여 질문 드렸습니다. Caused by: org.springframework.data.mapping.PropertyReferenceException: No property 'search' found for type 'User' at org.springframework.data.mapping.PropertyPath.<init>(PropertyPath.java:90) ~[spring-data-commons-3.2.2.jar:3.2.2] at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:443) ~[spring-data-commons-3.2.2.jar:3.2.2] at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:419) ~[spring-data-commons-3.2.2.jar:3.2.2] at org.springframework.data.mapping.PropertyPath.lambda$from$0(PropertyPath.java:372) ~[spring-data-commons-3.2.2.jar:3.2.2] at java.base/java.util.concurrent.ConcurrentMap.computeIfAbsent(ConcurrentMap.java:330) ~[na:na] at org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:354) ~[spring-data-commons-3.2.2.jar:3.2.2] at org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:332) ~[spring-data-commons-3.2.2.jar:3.2.2] at org.springframework.data.repository.query.parser.Part.<init>(Part.java:81) ~[spring-data-commons-3.2.2.jar:3.2.2] at org.springframework.data.repository.query.parser.PartTree$OrPart.lambda$new$0(PartTree.java:259) ~[spring-data-commons-3.2.2.jar:3.2.2] at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197) ~[na:na] at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179) ~[na:na] at java.base/java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:992) ~[na:na] at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509) ~[na:na] at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499) ~[na:na] at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921) ~[na:na] at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[na:na] at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682) ~[na:na] at org.springframework.data.repository.query.parser.PartTree$OrPart.<init>(PartTree.java:260) ~[spring-data-commons-3.2.2.jar:3.2.2] at org.springframework.data.repository.query.parser.PartTree$Predicate.lambda$new$0(PartTree.java:389) ~[spring-data-commons-3.2.2.jar:3.2.2] at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197) ~[na:na] at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179) ~[na:na] at java.base/java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:992) ~[na:na] at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509) ~[na:na] at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499) ~[na:na] at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921) ~[na:na] at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[na:na] at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682) ~[na:na] at org.springframework.data.repository.query.parser.PartTree$Predicate.<init>(PartTree.java:390) ~[spring-data-commons-3.2.2.jar:3.2.2] at org.springframework.data.repository.query.parser.PartTree.<init>(PartTree.java:100) ~[spring-data-commons-3.2.2.jar:3.2.2] at org.springframework.data.jpa.repository.query.PartTreeJpaQuery.<init>(PartTreeJpaQuery.java:100) ~[spring-data-jpa-3.2.2.jar:3.2.2] ... 79 common frames omitted
개발자
#spring-boot
#java
#interface
#jpa
답변 2
댓글 0
조회 178
일 년 전 · 장성호 님의 새로운 답변
JpaRepository 다중상속 오류
JpaRepository에 다중상속으로 CustomRepository를 상속하려고 합니다. 근데 자꾸 에러가 나서 질문 드립니다. @Repository public interface UserRepository extends JpaRepository<User, Long>, CustomRepository { Optional<User> findByUserId(String userId); } public interface CustomRepository { void search(); } 에러 메시지 ========================================================= Caused by: org.springframework.data.mapping.PropertyReferenceException: No property 'search' found for type 'User' at org.springframework.data.mapping.PropertyPath.<init>(PropertyPath.java:90) ~[spring-data-commons-3.2.2.jar:3.2.2] at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:443) ~[spring-data-commons-3.2.2.jar:3.2.2] at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:419) ~[spring-data-commons-3.2.2.jar:3.2.2] at org.springframework.data.mapping.PropertyPath.lambda$from$0(PropertyPath.java:372) ~[spring-data-commons-3.2.2.jar:3.2.2] at java.base/java.util.concurrent.ConcurrentMap.computeIfAbsent(ConcurrentMap.java:330) ~[na:na] at org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:354) ~[spring-data-commons-3.2.2.jar:3.2.2] at org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:332) ~[spring-data-commons-3.2.2.jar:3.2.2] at org.springframework.data.repository.query.parser.Part.<init>(Part.java:81) ~[spring-data-commons-3.2.2.jar:3.2.2] at org.springframework.data.repository.query.parser.PartTree$OrPart.lambda$new$0(PartTree.java:259) ~[spring-data-commons-3.2.2.jar:3.2.2] at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197) ~[na:na] at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179) ~[na:na] at java.base/java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:992) ~[na:na] at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509) ~[na:na] at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499) ~[na:na] at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921) ~[na:na] at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[na:na] at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682) ~[na:na] at org.springframework.data.repository.query.parser.PartTree$OrPart.<init>(PartTree.java:260) ~[spring-data-commons-3.2.2.jar:3.2.2] at org.springframework.data.repository.query.parser.PartTree$Predicate.lambda$new$0(PartTree.java:389) ~[spring-data-commons-3.2.2.jar:3.2.2] at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197) ~[na:na] at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179) ~[na:na] at java.base/java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:992) ~[na:na] at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509) ~[na:na] at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499) ~[na:na] at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921) ~[na:na] at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[na:na] at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682) ~[na:na] at org.springframework.data.repository.query.parser.PartTree$Predicate.<init>(PartTree.java:390) ~[spring-data-commons-3.2.2.jar:3.2.2] at org.springframework.data.repository.query.parser.PartTree.<init>(PartTree.java:100) ~[spring-data-commons-3.2.2.jar:3.2.2] at org.springframework.data.jpa.repository.query.PartTreeJpaQuery.<init>(PartTreeJpaQuery.java:100) ~[spring-data-jpa-3.2.2.jar:3.2.2] ... 79 common frames omitted
개발자
#spring-boot
#java
답변 1
댓글 0
조회 127
일 년 전 · 익명 님의 질문
백엔드 개발자 선배님들의 조언을 듣고싶습니다!
안녕하세요 선배님들 현재 신입 개발자로 수습기간 3개월, 곧 4개월이 되가는 사회생활을 하고있는 중 입니다. 다름이 아니라 저는 백엔드 개발자를 목표로 Spring Fremework 나 Spring Boot 를 좀더 집중적으로 활용하면서 실력을 늘리고 싶은데 현재 회사에서는 솔루션 회사이다 보니 백엔드 부분은 건드릴 일이 없고 화면단(jsp , javascript)과 쿼리 부분만 하게될 거 같습니다... 제대로 된 자바스크립트를 이용한다면 좋겟지만 자체 프레임워크를 사용하고 있어서 이게 이도저도 아닌 느낌이라 물경력만 쌓을거 같다는 느낌이 듭니다. 또한 서비스단 코드를 조금씩 봤더니 vo나 dto 객체도 없고 map으로만 모든 걸 해결하는 느낌입니다. 졸업 한지 얼마 안된 신입이라 경험이 없어서 여러가지 알아보고는 있지만 먼저 경험을 해보신 선배님들의 의견을 여쭈어보고 싶습니다. 저는 신입이라면 많은 걸 경험하면서 실력을 쌓아야 할 때라고 보는 입장입니다. 회사에 다니면서 다시 백엔드 개발 쪽으로 구직 활동을 하는 게 맞는 판단일까요?
개발자
#개발자
#백엔드-개발자
#back-end
#spring-framework
#spring-boot
답변 0
댓글 0
조회 110
일 년 전 · 다형 님의 답변 업데이트
aws spring boot 배포 오류
안녕하세요 백엔드 공부 중인 학생입니다. aws ec2로 Spring boot 프로젝트를 배포 시도 중에 있습니다. (maven, java 8, jar) java -jar jar파일명.jar 명령어로 배포 시도 중에 에러메세지가 도저히 해결이 안되어서 도움 요청드립니다.. 도와주신다면 감사하겠습니다.. 아 참고로 rds로 데이터베이스 생성하지 않고 mysql(workbench)로 데이터베이스 생성했습니다 <오류메세지> Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled. 2024-02-07 04:33:35.742 ERROR 31012 --- [ main] o.s.boot.SpringApplication : Application run failed org.springframework.context.ApplicationContextException: Failed to start bean 'webServerStartStop'; nested exception is org.springframework.boot.web.server.WebServerException: Unable to start embedded Tomcat server at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:181) ~[spring-context-5.3.22.jar!/:5.3.22] at org.springframework.context.support.DefaultLifecycleProcessor.access$200(DefaultLifecycleProcessor.java:54) ~[spring-context-5.3.22.jar!/:5.3.22] at org.springframework.context.support.DefaultLifecycleProcessor$LifecycleGroup.start(DefaultLifecycleProcessor.java:356) ~[spring-context-5.3.22.jar!/:5.3.22] at java.lang.Iterable.forEach(Iterable.java:75) ~[na:1.8.0_392] at org.springframework.context.support.DefaultLifecycleProcessor.startBeans(DefaultLifecycleProcessor.java:155) ~[spring-context-5.3.22.jar!/:5.3.22] at org.springframework.context.support.DefaultLifecycleProcessor.onRefresh(DefaultLifecycleProcessor.java:123) ~[spring-context-5.3.22.jar!/:5.3.22] at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:935) ~[spring-context-5.3.22.jar!/:5.3.22] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:586) ~[spring-context-5.3.22.jar!/:5.3.22] at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:147) ~[spring-boot-2.7.2.jar!/:2.7.2] at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:734) [spring-boot-2.7.2.jar!/:2.7.2] at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:408) [spring-boot-2.7.2.jar!/:2.7.2] at org.springframework.boot.SpringApplication.run(SpringApplication.java:308) [spring-boot-2.7.2.jar!/:2.7.2] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306) [spring-boot-2.7.2.jar!/:2.7.2] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1295) [spring-boot-2.7.2.jar!/:2.7.2] at com.se.social.SocialApplication.main(SocialApplication.java:13) [classes!/:0.0.1-SNAPSHOT] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_392] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_392] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_392] at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_392] at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49) [social-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT] at org.springframework.boot.loader.Launcher.launch(Launcher.java:108) [social-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT] at org.springframework.boot.loader.Launcher.launch(Launcher.java:58) [social-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT] at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:65) [social-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT] Caused by: org.springframework.boot.web.server.WebServerException: Unable to start embedded Tomcat server at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.start(TomcatWebServer.java:229) ~[spring-boot-2.7.2.jar!/:2.7.2] at org.springframework.boot.web.servlet.context.WebServerStartStopLifecycle.start(WebServerStartStopLifecycle.java:43) ~[spring-boot-2.7.2.jar!/:2.7.2] at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:178) ~[spring-context-5.3.22.jar!/:5.3.22] ... 22 common frames omitted Caused by: java.lang.IllegalArgumentException: standardService.connector.startFailed at org.apache.catalina.core.StandardService.addConnector(StandardService.java:238) ~[tomcat-embed-core-9.0.65.jar!/:na] at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.addPreviouslyRemovedConnectors(TomcatWebServer.java:282) ~[spring-boot-2.7.2.jar!/:2.7.2] at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.start(TomcatWebServer.java:213) ~[spring-boot-2.7.2.jar!/:2.7.2] ... 24 common frames omitted Caused by: org.apache.catalina.LifecycleException: Protocol handler start failed at org.apache.catalina.connector.Connector.startInternal(Connector.java:1077) ~[tomcat-embed-core-9.0.65.jar!/:na] at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) ~[tomcat-embed-core-9.0.65.jar!/:na] at org.apache.catalina.core.StandardService.addConnector(StandardService.java:234) ~[tomcat-embed-core-9.0.65.jar!/:na] ... 26 common frames omitted Caused by: java.net.SocketException: Permission denied at sun.nio.ch.Net.bind0(Native Method) ~[na:1.8.0_392] at sun.nio.ch.Net.bind(Net.java:461) ~[na:1.8.0_392] at sun.nio.ch.Net.bind(Net.java:453) ~[na:1.8.0_392] at sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:222) ~[na:1.8.0_392] at org.apache.tomcat.util.net.NioEndpoint.initServerSocket(NioEndpoint.java:275) ~[tomcat-embed-core-9.0.65.jar!/:na] at org.apache.tomcat.util.net.NioEndpoint.bind(NioEndpoint.java:230) ~[tomcat-embed-core-9.0.65.jar!/:na] at org.apache.tomcat.util.net.AbstractEndpoint.bindWithCleanup(AbstractEndpoint.java:1227) ~[tomcat-embed-core-9.0.65.jar!/:na] at org.apache.tomcat.util.net.AbstractEndpoint.start(AbstractEndpoint.java:1313) ~[tomcat-embed-core-9.0.65.jar!/:na] at org.apache.coyote.AbstractProtocol.start(AbstractProtocol.java:614) ~[tomcat-embed-core-9.0.65.jar!/:na] at org.apache.catalina.connector.Connector.startInternal(Connector.java:1074) ~[tomcat-embed-core-9.0.65.jar!/:na] ... 28 common frames omitted <전체> . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.7.2) 2024-02-07 04:33:27.975 INFO 31012 --- [ main] com.se.social.SocialApplication : Starting SocialApplication v0.0.1-SNAPSHOT using Java 1.8.0_392 on ip-172-31-39-15 with PID 31012 (/home/ubuntu/socialboardPJ/target/social-0.0.1-SNAPSHOT.jar started by ubuntu in /home/ubuntu/socialboardPJ/target) 2024-02-07 04:33:27.980 INFO 31012 --- [ main] com.se.social.SocialApplication : No active profile set, falling back to 1 default profile: "default" 2024-02-07 04:33:29.591 INFO 31012 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFAULT mode. 2024-02-07 04:33:29.681 INFO 31012 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 76 ms. Found 1 JPA repository interfaces. 2024-02-07 04:33:30.960 INFO 31012 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 80 (http) 2024-02-07 04:33:30.986 INFO 31012 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat] 2024-02-07 04:33:30.987 INFO 31012 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.65] 2024-02-07 04:33:31.641 INFO 31012 --- [ main] org.apache.jasper.servlet.TldScanner : At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time. 2024-02-07 04:33:31.880 INFO 31012 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext 2024-02-07 04:33:31.880 INFO 31012 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 3717 ms 2024-02-07 04:33:32.215 INFO 31012 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting... 2024-02-07 04:33:32.569 INFO 31012 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed. 2024-02-07 04:33:32.659 INFO 31012 --- [ main] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [name: default] 2024-02-07 04:33:32.822 INFO 31012 --- [ main] org.hibernate.Version : HHH000412: Hibernate ORM core version 5.6.10.Final 2024-02-07 04:33:33.157 INFO 31012 --- [ main] o.hibernate.annotations.common.Version : HCANN000001: Hibernate Commons Annotations {5.1.2.Final} 2024-02-07 04:33:33.383 INFO 31012 --- [ main] org.hibernate.dialect.Dialect : HHH000400: Using dialect: org.hibernate.dialect.MySQL8Dialect 2024-02-07 04:33:34.255 INFO 31012 --- [ main] o.h.e.t.j.p.i.JtaPlatformInitiator : HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform] 2024-02-07 04:33:34.266 INFO 31012 --- [ main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default' 2024-02-07 04:33:34.906 WARN 31012 --- [ main] JpaBaseConfiguration$JpaWebConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning 2024-02-07 04:33:35.616 WARN 31012 --- [ main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.context.ApplicationContextException: Failed to start bean 'webServerStartStop'; nested exception is org.springframework.boot.web.server.WebServerException: Unable to start embedded Tomcat server 2024-02-07 04:33:35.620 INFO 31012 --- [ main] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default' 2024-02-07 04:33:35.624 INFO 31012 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown initiated... 2024-02-07 04:33:35.646 INFO 31012 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown completed. 2024-02-07 04:33:35.650 INFO 31012 --- [ main] o.apache.catalina.core.StandardService : Stopping service [Tomcat] 2024-02-07 04:33:35.676 INFO 31012 --- [ main] ConditionEvaluationReportLoggingListener : Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled. 2024-02-07 04:33:35.742 ERROR 31012 --- [ main] o.s.boot.SpringApplication : Application run failed org.springframework.context.ApplicationContextException: Failed to start bean 'webServerStartStop'; nested exception is org.springframework.boot.web.server.WebServerException: Unable to start embedded Tomcat server at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:181) ~[spring-context-5.3.22.jar!/:5.3.22] at org.springframework.context.support.DefaultLifecycleProcessor.access$200(DefaultLifecycleProcessor.java:54) ~[spring-context-5.3.22.jar!/:5.3.22] at org.springframework.context.support.DefaultLifecycleProcessor$LifecycleGroup.start(DefaultLifecycleProcessor.java:356) ~[spring-context-5.3.22.jar!/:5.3.22] at java.lang.Iterable.forEach(Iterable.java:75) ~[na:1.8.0_392] at org.springframework.context.support.DefaultLifecycleProcessor.startBeans(DefaultLifecycleProcessor.java:155) ~[spring-context-5.3.22.jar!/:5.3.22] at org.springframework.context.support.DefaultLifecycleProcessor.onRefresh(DefaultLifecycleProcessor.java:123) ~[spring-context-5.3.22.jar!/:5.3.22] at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:935) ~[spring-context-5.3.22.jar!/:5.3.22] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:586) ~[spring-context-5.3.22.jar!/:5.3.22] at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:147) ~[spring-boot-2.7.2.jar!/:2.7.2] at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:734) [spring-boot-2.7.2.jar!/:2.7.2] at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:408) [spring-boot-2.7.2.jar!/:2.7.2] at org.springframework.boot.SpringApplication.run(SpringApplication.java:308) [spring-boot-2.7.2.jar!/:2.7.2] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306) [spring-boot-2.7.2.jar!/:2.7.2] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1295) [spring-boot-2.7.2.jar!/:2.7.2] at com.se.social.SocialApplication.main(SocialApplication.java:13) [classes!/:0.0.1-SNAPSHOT] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_392] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_392] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_392] at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_392] at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49) [social-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT] at org.springframework.boot.loader.Launcher.launch(Launcher.java:108) [social-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT] at org.springframework.boot.loader.Launcher.launch(Launcher.java:58) [social-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT] at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:65) [social-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT] Caused by: org.springframework.boot.web.server.WebServerException: Unable to start embedded Tomcat server at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.start(TomcatWebServer.java:229) ~[spring-boot-2.7.2.jar!/:2.7.2] at org.springframework.boot.web.servlet.context.WebServerStartStopLifecycle.start(WebServerStartStopLifecycle.java:43) ~[spring-boot-2.7.2.jar!/:2.7.2] at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:178) ~[spring-context-5.3.22.jar!/:5.3.22] ... 22 common frames omitted Caused by: java.lang.IllegalArgumentException: standardService.connector.startFailed at org.apache.catalina.core.StandardService.addConnector(StandardService.java:238) ~[tomcat-embed-core-9.0.65.jar!/:na] at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.addPreviouslyRemovedConnectors(TomcatWebServer.java:282) ~[spring-boot-2.7.2.jar!/:2.7.2] at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.start(TomcatWebServer.java:213) ~[spring-boot-2.7.2.jar!/:2.7.2] ... 24 common frames omitted Caused by: org.apache.catalina.LifecycleException: Protocol handler start failed at org.apache.catalina.connector.Connector.startInternal(Connector.java:1077) ~[tomcat-embed-core-9.0.65.jar!/:na] at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) ~[tomcat-embed-core-9.0.65.jar!/:na] at org.apache.catalina.core.StandardService.addConnector(StandardService.java:234) ~[tomcat-embed-core-9.0.65.jar!/:na] ... 26 common frames omitted Caused by: java.net.SocketException: Permission denied at sun.nio.ch.Net.bind0(Native Method) ~[na:1.8.0_392] at sun.nio.ch.Net.bind(Net.java:461) ~[na:1.8.0_392] at sun.nio.ch.Net.bind(Net.java:453) ~[na:1.8.0_392] at sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:222) ~[na:1.8.0_392] at org.apache.tomcat.util.net.NioEndpoint.initServerSocket(NioEndpoint.java:275) ~[tomcat-embed-core-9.0.65.jar!/:na] at org.apache.tomcat.util.net.NioEndpoint.bind(NioEndpoint.java:230) ~[tomcat-embed-core-9.0.65.jar!/:na] at org.apache.tomcat.util.net.AbstractEndpoint.bindWithCleanup(AbstractEndpoint.java:1227) ~[tomcat-embed-core-9.0.65.jar!/:na] at org.apache.tomcat.util.net.AbstractEndpoint.start(AbstractEndpoint.java:1313) ~[tomcat-embed-core-9.0.65.jar!/:na] at org.apache.coyote.AbstractProtocol.start(AbstractProtocol.java:614) ~[tomcat-embed-core-9.0.65.jar!/:na] at org.apache.catalina.connector.Connector.startInternal(Connector.java:1074) ~[tomcat-embed-core-9.0.65.jar!/:na] ... 28 common frames omitted
개발자
#aws
#springboot
#배포
답변 1
댓글 0
조회 614
일 년 전 · 이진영 님의 질문
안녕하세요 HardDelete를 하는 과정속에서 궁금한 점이 생겨 이렇게 질문을 남깁니다.
현재 저는 프로젝트를 진행하고 있습니다. hard delete 특정 연관관계 칼럼까지 삭제를 해야 하는데 이에 있어 보통 어떻게 삭제하는지 궁금합니다. 저희는 프로젝트 용이기 때문에 매 년마다 HardDelete를 구현을 담당하고 있습니다.(내부적인 회의를 통해서 hard delete를 구현하기로 함) 근데 구현에 있어서는 스케줄러를 통해서 삭제를 할 예정이고(코드 참고) @Scheduled(cron = "0 */2 * * * ?") // test cron public void teamDisbandCheckAndDelete() { List<Long> teamIds = teamRepository.findIdsByIsDeleteIsTrue(); teamRepository.deleteAll(teamIds); // cascade remove } 할 생각이었지만 이는 성능상 이슈가 있을 것이라고 생각합니다. 그러한 이유는 팀을 하나만 삭제하는데 다른 연관 관계 테이블은 최소 10배가 최대 100배 넘는 데이터를 가지고 있을 것이라고 예상합니다. 이러한 관점에서 봤을 때 성능상 이슈가 있을 것이라고 예상하고 배치 delete를 구현하려고 했습니다. 근데 만약 이렇게 배치 delete를 아래와 같이 진행을 하려고 합니다.(예시 코드) // 연관된 데이터 삭제 // (예: TeamParticipants, SimpleSchedule, RepeatSchedule 등) teamParticipantsRepository.deleteByTeamIdIn(ids); simpleScheduleRepository.deleteByTeamIdIn(ids); repeatScheduleRepository.deleteByTeamIdIn(ids); // Team 엔터티 삭제 teamRepository.deleteAllByIdIn(ids); 근데 이렇게 삭제하는 게 최선인지도 궁금합니다. 여기서 문제점은 만약 다른 엔티티(TeamParticipants 등등) 삭제 시 제약조건 오류가 났을 때 그렇다면 그 해당 칼럼도 삭제를 해줘야 하는데 이렇게 구현하는 게 맞나?? 싶어서 이렇게 글을 남깁니다.
개발자
#java
#spring
#batch
#delete
#jpa
답변 0
댓글 0
추천해요 1
보충이 필요해요 1
조회 63
2년 전 · 익명 님의 질문
타입스크립트 recoil 타입선언에 대한 질문입니다.
안녕하세요. redux를 recoil로 변경하면서 typescript도 같이 사용해보고 있는데 감이 잘 잡히지 않네요 타입스크립트에서 다른타입의 값을 가져와서 비교후 처리해야한다면 어떻게 해야할지 모르겠어서 질문을 드리게 되었습니다. 애초에 이러한 경우는 성립을 하지가 않는걸까요? 컴포넌트에서 deleteTagHandler에서 Tag타입으로 값을 받아와서 setRemoveToNoteTags()로 Tag타입의 매개변수 tag를 전달해주는데요 selector에서는 NotesList의 타입을 지원하고 있어서 그런거 같습니다... 가르침 부탁드리겠습니다 ㅠㅠㅠ 컴포넌트``` const setRemoveToNoteTags = useSetRecoilState(removeTagsSelector); const deleteTagHandler = (tag: Tag): void => { setTagsState({ type: "delete", tagsList: [tag] }); setRemoveToNoteTags(tag); }; ``` selector``` interface NotesList { mainNotes: Note[]; archiveNotes: Note[]; trashNotes: Note[]; editNote: null | Note; } const initialState: NotesList = { mainNotes: [...notes], archiveNotes: [], trashNotes: [], editNote: null, }; export const notesListState = atom({ key: "notesListState", // 고유한 키 default: initialState, // 초기 상태 }); export const removeTagsSelector = selector({ key: "removeTagsSelector", get: ({ get }) => {}, set: ({ get, set }, newValue: Tag) => { const notesList = get(notesListState); const removeTagFromNotes = (notes: Note[]) => { return notes.map((note) => { return { ...note, tags: note.tags.filter(({ tag }) => tag !== newValue.tag), }; }); ...... ```
개발자
#recoil
#react
#typescript
답변 0
댓글 0
조회 40
2년 전 · 삭제된 사용자 님의 답변 업데이트
파이썬(FastAPI) 도커에 Komoran 추가 하는 방버?
안녕하세요 파이썬도 처음인데 도커도 처음 하게 되었어요 개발로 Fast API를 만들어 pyKomoran을 사용해 문자를 받는 것을 추가했습니다 이제 환경을 도커로 만들어 배포를 하고 싶은데 Komoran는 Java에서 실행이 되다 보니 Java를 설치를 해야 하는데 도커에서 어떻게 추가하는지 잘 모르겠어요 AI 들에게 물어봤지만 오류만 나고 있습니다 -------------------- FROM python:latest WORKDIR /app/ COPY ./main.py /app/ COPY ./routers /app/routers COPY ./pydantics /app/pydantics COPY ./controller /app/controller COPY ./tmp /app/tmp COPY ./requirements.txt /app/ RUN pip3 install -r requirements.txt CMD uvicorn main:app --reload -------------------- 이런 방식으로 만들었는데 어떻게 여기서 Java를 추가 하는지 알려주세요 ㅠㅠ ENV sudo yum install java-1.8.0-openjdk 답답해서 위와 같은 방법을 했는데 (직접 설치하기 ) 이 방법은 에러가 나더라고요 Komoran를 사용하시는 선배님들 배포를 어떻게 하셨는지 궁금합니다 -> 지금 환경에서 서버는 CloudType 이라는 서버를 사용할 거라 제가 추가 설치를 할 수 없습니다 그래서 도커를 이용해 컨테이너화 후 배포할 생각입니다
개발자
#파이썬
#도커
#komoran
#배포
#cloudtype
답변 1
댓글 2
조회 136
2년 전 · 김현진 님의 새로운 답변
useEffect 가 끊임없이 돌고있어요. dependency 의 늪에서 벗어날 수 있게 도와주세요..! 🥹
안녕하세요. 소켓 통신을 사용한 채팅 기능 구현중인 주니어 개발자입니다. 아래와 같은 상황에 보통 어떻게 대처하시나요? 문제: useEffect 사용 시 서버에 채팅 방 말풍선 목록을 요청(publish)하고, 요청한 데이터를 state 에 저장하는 과정에서 loop 가 생겨 useEffect 가 끊임없이 돌고 있습니다. 문제 설명: - 서버에 채팅 방 말풍선 목록을 요청할 때 넘기는 값 중에 direction 이라는 변수가 있는데요, 이 direction 변수는 채팅 방 말풍선 개수에 의존적입니다. 따라서 useEffect 의 dependency에 채팅 방 말풍선 목록이 들어가게 됩니다. - 서버로부터 데이터를 받은 즉시 채팅방 말풍선 목록을 state에 저장하게 됩니다. - 위 두 상황(useEffect의 deps 설정, setState) 때문에 loop 가 생기게 됩니다. 생각해본 해결 방안: - useRef 를 사용하여 deps 에 등록하지 않아도 최신 데이터를 바라볼 수 있습니다. - 말풍선 목록이 배열 데이터이기 때문에, 새로운 배열을 만들지 않고 기존 배열을 계속 사용하여 같은 메모리를 사용합니다. 같은 메모리를 사용하고 있기 때문에 useEffect 의 deps 에 등록하지 않아도 최신 데이터를 바라볼 수 있습니다. - 말풍선 목록을 링크드리스드 자료구조를 사용하고, 한 번 생성한 자료구조를 새로 만들지 않고 재사용하여 같은 메모리를 이용합니다. 같은 메모리를 사용하고 있기 때문에 useEffect 의 deps 에 등록하지 않아도 최신 데이터를 바라볼 수 있습니다. 위 해결 방안의 문제점: - useEffect 의 deps 에 등록하지 않는 방법은 anti pattern 이라는 느낌을 받습니다. 아마도 위 방법을 사용한 데이터를 사용하는 컴포넌트의 re-rendering 이 되지 않기 때문에 이런 느낌을 받는 것 같습니다. 참고 자료: [react 문서](https://react.dev/learn/removing-effect-dependencies#are-you-reading-some-state-to-calculate-the-next-state)
개발자
#react
#useeffect
#dependency
답변 2
댓글 0
조회 140
2년 전 · 익명개발자 님의 질문
애저 함수 앱 배포시 에러
Deployment Log file does not exist in /tmp/oryx-build.log 에러가 뜨고 배포에 실패합니다 로컬 테스트시 결과값잘나오는데 배포만 수행하면 에러가납니다 <requirements.txt> azure-functions openai Pillow regex transformers==4.33.0 nltk==3.8.1 torch==2.0.0
개발자
#azure
#pytorch
#openai
#배포
#클라우드
답변 0
댓글 0
조회 29
2년 전 · salbyul 님의 새로운 댓글
개인 프로젝트중 DB 복합키 관련 질문입니다!
안녕하세요! 개인 프로젝트를 진행하다 궁금증이 생겨 질문드립니다. 우선 저는 Spring Boot, JPA, MySQL로 소모임을 만들고 참여할 수 있는 프로젝트를 진행하고 있습니다. 1. 모임을 등록할 경우 모임 태그를 설정할 수 있고 해당 태그로 검색이 가능하게 구현을 하려고 합니다. 제가 생각했을 때 모임 태그가 굳이 auto_increment로 PK값을 가질 필요가 없다고 생각해서 해당 모임 PK값과, 태그 이름으로 복합키 PK값을 설정하였는데요. 효율을 따졌을 경우 이 경우가 옳은지가 궁금합니다! 2. 모임을 만들 때 지원자들에게 질문을 할 수 있게 지원 양식을 작성하게 되어있습니다. 지원 양식 테이블은 모임 테이블과 다대일 (지원 질문 : 모임) 관계를 가지고 있습니다. 이 경우에도 지원 질문 테이블은 모임 PK값과 orders (질문 순서) 컬럼으로 복합키 PK로 설정하였는데요. 이 경우도 궁금해서 질문드립니다. 저는 굳이 PK값을 따로 두어 해당 PK값을 사용해 질문을 찾거나 할 일이 없기 때문에 PK 값을 따로 설정할 필요가 없다고 생각합니다! (질문을 작성, 수정할 경우 해당 모임의 모든 질문을 제거하고 다시 insert하는 방법) 읽어주셔서 감사합니다!
개발자
#mysql
#database
답변 1
댓글 1
조회 207
2년 전 · 익명 님의 질문 업데이트
api의 첫번째 호출 이후부터 antd Button 렌더링 안되는 이슈가 있습니다.
```jsx import { Popover, Modal, Button, Image, Result } from "antd"; const [prevImg, setPrevImg] = useState(["any"]); const [loading, setLoading] = useState(false); const [removeImgFiles, setRemoveImgFiles] = useState([]); const combinePrevImages = (prevImages, newImages) => { const combinedImages = [...prevImages, ...newImages]; return combinedImages; }; useEffect(() => { const postSeg = async () => { try { const res = await axios.post( "apiurl", { filepath: filePath, clips: sortableList.map(list => `${list.seg.start}-${list.seg.end}`), frame: frameValue }, { proxy: false } ); return res.data; } catch (error) { console.error("Error posting segments:", error); return []; } finally { setLoading(false); } }; const postSegments = async () => { if (segments[0]?.start === 0 && segments[0]?.end === 0) return; if (sortableList && filePath) { setLoading(true); const res = await postSeg(); const combinedPrevImg = combinePrevImages(prevImg, res.results); setPrevImg(combinedPrevImg); console.log("Post Request Success"); } }; postSegments(); }, [filePath, segments, frameValue]); const handleModalOpen = useCallback(() => setModalOpen(true), []); const handleModalClose = useCallback(() => { setRemoveImgFiles([]); setModalOpen(false); }, []); const handleDeleteButtonClick = async () => { if (removeImgFiles.length > 0) { setPrevImg([...removeImgFiles]); setRemoveImgFiles([]); } else { const result = await showSwal({ title: "Are you sure delete?", showCancelButton: true, confirmButtonText: "Confirm", cancelButtonText: "Cancel", confirmButtonColor: "#3085d6", cancelButtonColor: "#d33" }); if (result.isConfirmed) { setRemoveImgFiles([...prevImg]); setPrevImg([]); } const success = await Promise.all(removeImgFiles.map(deleteFiles)); return success; } } const handleRemoveFinish = async () => { if (removeImgFiles) { for (const filePath of removeImgFiles) { try { await removeFile(filePath); } catch (e) { console.log("File Remove Error", e); } } } setRemoveImgFiles([]); handleModalClose(); }; return ( <motion.div initial={{ x: width }} animate={{ x: 0 }} exit={{ x: width }} transition={mySpring} > <div style={{ fontSize: 12, padding: "0 5px", color: "var(--gray12)", display: "flex", justifyContent: "space-between", alignItems: "center" }} > <FaAngleRight title={t("Close sidebar")} size={20} className="angle-right" role="button" onClick={toggleSegmentsList} /> {header} <FaExpandArrowsAlt title={t("Image Inspection")} size={18} className="expand-arrow-alt" style={{ cursor: "pointer" }} role="button" onClick={!loading ? handleModalOpen : handleModalClose} /> <Modal title={t("Image Inspection")} centered onCancel={handleModalClose} open={modalOpen} footer={[]} width="100%" > <div className="imagecontainer"> <Button danger className="toggle-remove" onClick={handleDeleteButtonClick}> {removeImgFiles.length > 0 ? "Add" : "Remove"} </Button> {prevImg?.length > 10 && prevImg.map(img => ( <Popover key={img}> {removeImgFiles?.includes(img) ? ( <span> <Result className="result" icon={<FaSmile />} subTitle="delete" /> </span> ) : <Image key={uuidv4()} src={img} preview={{ src: img }} alt={uuidv4()} /> )} </Popover> ))} </div> <Button block onClick={handleRemoveFinish}> Finish </Button> </Modal> </div> ) ``` api 호출을 통해 frameValue 개수(여기서는 12개씩) 만큼 이미지를 렌더링 하고 있는데 두번째 호출부터는 Button이 렌더링되지 않아서 어디가 잘못됐는지 알고싶습니다.. 필요한 부분이 imagecontainer 클래스네임인 div를 렌더링 해야합니다.
개발자
#react
답변 0
댓글 0
조회 85
2년 전 · 김도열 님의 새로운 댓글
nysql에서 외래키 참조
syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '[CONSTRAINT fk_name] FOREIGN KEY(name) REFERENCES uesr_into(name) ON UPD' at line 5 CREATE TABLE a_check( id MEDIUMINT AUTO_INCREMENT PRIMARY KEY, name MEDIUMTEXT not null, age MEDIUMINT not null, [CONSTRAINT fk_name] FOREIGN KEY(name) REFERENCES uesr_into(name) ON UPDATA CASCADE ); 무슨 에러에요? 데이터가 있어야 한다는 걸까요?
개발자
#mysql
답변 1
댓글 1
보충이 필요해요 2
조회 57
2년 전 · 김병수 님의 답변 업데이트
mysql에서의 외래키
CREATE TABLE a_check( id INT INTEGER AUTO_INCREMEnT PRIMART KEY, name MEDIUMBLO not null, age MEDIUMINT not null [CONSTRAINT CASCADE] FOREIGN KEY(name) REFERENCES uesr_into(name) ON UPDATA ) 여기에다가 age 의 외래키를 더 추가할건데 추가할 수있나요?
개발자
#mysql
답변 1
댓글 0
보충이 필요해요 1
조회 86
2년 전 · 김도열 님의 새로운 답변
mysql에서 값을 제한할 수 있나요
CREATE TABLE uesr_into( id SMALLINT AUTO_INCREMENT PRIMARY KEY, name MEDIUMTEXT NOT NULL, sex ENUM('M' ,'F') NOT NULL, job MEDIUMTEXT age MEDIUMINT NOT NULL if(age>20 AND age<100, NOT NULL, '입소가 불가능 합니다.') ); if문에서 값을 못게 할 수 없나요?
개발자
#mysql
답변 1
댓글 0
조회 71
2년 전 · 장성호 님의 새로운 답변
mysql 관련오류
0 8 09:46:09 create table week( name varchar(30) not null,-- 일정 이름 start_time time default '10:00:00',-- 시작 시간 end_time time default '16:00:00',-- 끝나는 시간 number tinyint auto_increment primary key, check (start_time<end_time) ) Error Code: 1050. Table 'week' already exists 0.000 sec
개발자
#mysql
답변 1
댓글 0
조회 148
2년 전 · 손호영 님의 질문
mysql 오류가 있어요?
create table week( name varchar(30) not null,-- 일정 이름 start_time time default '10:00:00',-- 시작 시간 end_time time default '16:00:00',-- 끝나는 시간 number tinyint auto_increment primary key check (start_time<end_time) 0 7 09:43:20 create table week( Error Code: 3813. Column check constraint 'week_chk_1' references other column. 0.000 sec
개발자
#mysql
답변 0
댓글 0
보충이 필요해요 1
조회 79
2년 전 · 익명 님의 댓글 업데이트
github commit 깃허브 커밋 문제
깃허브에 개인 프로젝트 2개를 각각의 레파지토리에 올려놓은 상태인데요, (편의상 첫번째 레파지토리를 A, 두번째 레파지토리를 B라고 하겠습니다.) A와 B를 커밋 후, A에 수정할 부분이 생겨 다시 업로드를 하였는데, B에 올려놓은 프로젝트가 A에도 업로드 되는 문제가 여러 번 있었습니다. 깃허브에 대한 이해가 높지 않고, 일단 만든 프로젝트를 먼저 올려두려고 유튜브를 참고하여 올린 상태라, 어느 부분에서 문제가 생긴건지 파악하기 어려워 질문 올려봅니다! 첫 커밋 이후, 매 커밋 마다 `git remote remove origin` 로 연결을 끊고 재연결하여, `git push origin master`로 커밋하였는데, 혹시 이게 문제가 됐을까요?
개발자
#github
답변 1
댓글 1
조회 101
2년 전 · 강민기 님의 새로운 댓글
C# 프로그램 실행을 했을 때 메모리에서 어떻게 이루어지는지 공부하는데 어려워서 정리가 안되네요. 그리고 C# 컴파일 구조 등등도..
안녕하세요, C# 메모리를 대해서 공부 중인 대학생 4학년 입니다. 1.제가 처음 배운 기본적인 프로세스 기반으로 프로그램 안에 코드 영역, 데이터 영역, 힙, 스택이 있는데 C# 프로그램은 다르다고 합니다. c# 4.0 - what is the difference between object and loader heap in .net 4.0 - Stack Overflow 에서는 <원문> heap memory is divided into to parts,object heap and loader heap(also known as high frequency heap).All non static reference type are stored on object heap and all static object(either reference type or value type) are stored in loader heap. Gc never work on loader heap thats why they initilized only once and remain in memory throught the application. <해석> 힙 메모리는 두 부분으로 나뉩니다. "객체 힙"과 "로더 힙" (또는 고주파 힙이라고도 함)으로 나눌 수 있습니다. 모든 정적이 아닌 참조 유형은 객체 힙에 저장되며, 모든 정적 객체 (참조 유형이든 값 유형이든)은 로더 힙에 저장됩니다. 가비지 컬렉터(GC)는 로더 힙 에서 작업하지 않으므로 이러한 객체는 애플리케이션이 실행되는 동안 한 번만 초기화되고 메모리에 유지됩니다. 라고 되어 있어서 그럼 C# = 코드 영역, 데이터 영역, 힙(객채 힙, 로드 힙), 스택이 있는데 제가 배운 걸로는 데이터 영역에 정적 객채들이 저장된다고 알고 있는데 그럼 정적 객체들과 함수들은 로드 힙에 저장되고 데이터 영역 에는 뭐가 저장되는 건가요? 2. C# 컴파일 구조는 어떻게 되어 있는 건가요?
개발자
#c#
#c#-컴파일구조
#c#-메모리구조
답변 1
댓글 1
조회 199
2년 전 · 커리어리 AI 봇 님의 새로운 답변
리액트 라우팅을 이렇게 하는게 맞는지 모르겠습니다..
안녕하세요 독학 하고 있는 학생입니다.. 작은 프로젝트로 혼자서 홈페이지를 만들고 있습니다. 우선 로그인 페이지부터 만들고 있는데, 로그인페이지에는 아이디찾기 비밀번호찾기 등등 많은 페이지가 들어가더라구요.. 그래서 리액트 라우터를 공부하고 적용시켰습니다. 코드는 아래와 같습니다. 이렇게 해도 제가 원하는대로 로그인페이지에서 아이디 찾기 페이지로 이동하고 하는 것은 맞는데 App.js에 이렇게 주저리주저리 원하는 것을 다 넣어두면 나중에 전체적으로 페이지를 완성시켰을 때 App.js에 너무 방대한 내용이 들어가지않나..? 싶더라구요.. 그래서 중첩된 라우트도 찾아서 공부했는데 크흡..암만해도 적용이 안됩니다.. 그래서 그냥 이대로 홈페이지를 계속 만들어도 되는지,,아니면 저의 고민을 해결할 방법이 중첩된 라우트가 맞는지 알고싶습니다.. 맞다면 다시 공부해야겠죠 ㅜ.. 답변부탁드립니다 (_ _) import "./App.css"; import { Route, Routes } from "react-router-dom"; import WigTemplate from "./components/wigtemplate"; import FindId from "./components/findId"; import FindPwd from "./components/findPwd"; import SignIn from "./components/signIn"; import NotFound from "./components/notFound"; function App() { return ( <Routes> <Route path="/" element={<WigTemplate />} /> <Route path="/findId" element={<FindId />} /> <Route path="/findPwd" element={<FindPwd />} /> <Route path="/signIn" element={<SignIn />} /> <Route path="*" element={<NotFound />} /> </Routes> ); } export default App; ---------------------------------------------------------- import React from "react"; import styled from "styled-components"; import WigLoginButton from "./wigLoginButton"; import WigHeader from "./wigHeader"; import WigInput from "./wigInput"; import WigFind from "./wigFind"; const WigTemplateContainer = styled.div` height: 100vh; display: flex; align-items: center; justify-content: center; `; const WigTemplateBlock = styled.div` width: 500px; height: 600px; background: #d0ebff; border-radius: 80px; `; function WigTemplate() { return ( <WigTemplateContainer> <WigTemplateBlock> <WigHeader></WigHeader> <WigInput></WigInput> <WigFind></WigFind> <WigLoginButton></WigLoginButton> </WigTemplateBlock> </WigTemplateContainer> ); } export default WigTemplate; ------------------------------------------------------- import React from "react"; import styled from "styled-components"; import { RxDividerVertical } from "react-icons/rx"; import { Link } from "react-router-dom"; const FindBlock = styled.div` display: flex; justify-content: center; `; const ABlock = styled(Link)` color: black; font-size: 0.9rem; text-decoration: none; `; function WigFind() { return ( <FindBlock> <ABlock to="/findId">아이디 찾기</ABlock> <RxDividerVertical style={{ marginTop: "3px" }} /> <ABlock to="/findPwd">비밀번호 찾기</ABlock> <RxDividerVertical style={{ marginTop: "3px" }} /> <ABlock to="/signIn">회원가입</ABlock> </FindBlock> ); } export default WigFind;
개발자
#react
답변 2
댓글 3
조회 483
2년 전 · 커리어리 AI 봇 님의 새로운 답변
개발자 선생님들 도와주세요..
안녕하세요 초보개발자입니다 지금 구글로 코드 복붙하며 게시판 수정중인데 아예 똑같이 복붙 하였는데 저는 왜 이런 식으로 나올까요 도와주세요 .. ㅠㅠ 프로젝트 발표가 코앞인데.. 1번째사진은 작성자의 사진이고 2번째 사진이 제 출력 화면입니다... 코드는 댓글에 적어두겠습니다..도와주세요.. ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <!--부트스트랩은 어떤device로 접속하더라도 해상도에 맞게 알아서 설정되는 탬플릿이다. --> <meta name="viewport" content="width=device-width" , inital-scale="1"> <!--스타일시트를 참조, 주소는 css안에 부트스트랩.css--> <link rel="stylesheet" href="css/bootstrap.css"> <title>JSP 게시판 웹 사이트</title> </head> <body> <!-- 네비게이션 구현 네비게이션이라는 것은 하나의 웹사이트의 전반적인 구성을 보여주는 역할 --> <nav class="navbar navbar-default"> <!-- header부분을 먼저 구현해 주는데 홈페이지의 로고같은것을 담는 영역이라고 할 수 있다. --> <div class="navbar-header"> <!-- <1>웹사이트 외형 상의 제일 좌측 버튼을 생성해준다. data-target= 타겟명을 지정해주고--> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-exmaple="false"> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <!-- 여긴 웹페이지의 로고 글자를 지정해준다. 클릭 시 main.jsp로 이동하게 해주는게 국룰 --> <a class="navbar-brand" href="main.jsp">JSP 게시판 웹 사이트</a> </div> <!-- 여기서 <1>에만든 버튼 내부의 데이터 타겟과 div id가 일치해야한다. --> <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1"> <!-- div 내부에 ul은 하나의 어떠한 리스트를 보여줄때 사용 --> <ul class="nav navbar-nav"> <!-- 리스트 내부에 li로 원소를 구현 메인으로 이동하게만들고--> <li><a href="main.jsp">메인</a></li> <!-- 게시판으로 이동하게 만든다. --> <li><a href="bbs.jsp">게시판</a></li> </ul> <!-- 리스트 하나 더 생성 웹페이지 화면에서 우측 부분--> <ul class="nav navbar-nav navbar-right"> <!-- 원소를 하나 구현해 준다. 네비게이션 우측 슬라이드메뉴 구현 --> <li class="dropdown"> <!-- 안에 a태그를 하나 삽입한다. href="#"은 링크없음을 표시한다. --> <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">접속하기<span class="caret"></span></a> <!--접속하기 아래에 드랍다운메뉴 생성 --> <ul class="dropdown-menu"> <!-- li class="active" 현재 선택된 홈페이지를 의미 --> <li><a href="login.jsp">로그인</a></li> <li class="active"><a href="join.jsp">회원가입</a></li> </ul> </li> </ul> </div> <!-- 네비게이션 바 구성 끝 --> </nav> <!-- 하나의 컨테이너처럼 감싸주는 역할 --> <div class="container"> <div class="col-lg-4"></div> <!-- 회원가입 폼은 위의 양식은 일치하며, 이제 내부 폼만 바꿔준다. --> <div class="col-lg-4"> <div class="jumbotron" style="padding-top: 20px;"> <!-- 양식 삽입 post는 회원가입이나 로그인같이 어떠한 정보값을 숨기면서 보내는 메소드/ 로그인 Action페이지로 정보를보내겠다--> <form method="post" action="joinAction.jsp"> <!-- 회원 가입에 맞게 위에 액션은 joinAction페이지로 밑에 제목은 회원가입 화면으로 변경 --> <h3 style="text-align: center;">회원가입 화면</h3> <div class="form-group"> <!-- 회원 가입에서도 userID or userPassword는 동일하게 가져가고, 회원가입에 필요한 나머지 속성추가 --> <input type="text" class="form-control" placeholder="아이디" name="userID" maxlength="20"> </div> <div class="form-group"> <input type="password" class="form-control" placeholder="비밀번호" name="userPassword" maxlength="20"> </div> <!-- userName 추가 --> <div class="form-group"> <input type="text" class="form-control" placeholder="이름" name="userName" maxlength="20"> </div> <!-- 성별 선택 추가 --> <div class="form-group" style="text-align: center;"> <!-- 버튼 공간을 따로 마련해준다.(남,녀) --> <div class="btn-group" data-toggle="buttons"> <!-- 선택이 된곳에 표시를 하는 active를 설정해준다. --> <label class="btn btn-primary active"> <input type="radio" name="userGender" autocomplete="off" value="남자" checked>남자 </label> <label class="btn btn-primary"> <input type="radio" name="userGender" autocomplete="off" value="여자" checked>여자 </label> </div> <!-- 성별 선택부분 완료 --> </div> <!-- email 작성부분 구현 --> <div class="form-group"> <!-- placeholder는 아무런 입력이 없을때 띄워주는 값 --> <input type="email" class="form-control" placeholder="이메일" name="userEmail" maxlength="20"> </div> <!-- 버튼 또한 회원가입으로 value변경 --> <input type="submit" class="btn btn-primary form-control" value="회원가입"> </form> </div> </div> <div class="col-lg-4"></div> </div> <!-- 애니메이션을 담당하게 될 자바스크립트 참조 --> <script src="https://code.jquery.com/jquery-3.1.1.min.js"></script> <!-- 특정홈페이지에서 제이쿼리 호출 --> <script src="js/bootstrap.js"></script> </body> </html>
개발자
#jsp
#java
답변 2
댓글 4
보충이 필요해요 3
조회 388
2년 전 · 커리어리 AI 봇 님의 새로운 답변
<input type="file" multiple> 관련하여..
<template> <div> <input ref="fileInput" type="file" accept="image/*" multiple="true" @change="handleFileInputChange" /> <button @click="openFileInput" class="select-button"> Select Images </button> <div class="preview-container"> <div v-for="file in selectedFiles" :key="file.lastModified" class="preview-item" > <p>{{ file.name }}</p> <div class="preview"> <img :src="previewImage" style="width: 100px" /> </div> <!-- <img :src="URL.createObjectURL(file)" /> --> <button @click="removeFile(file.lastModified)" class="remove-button"> X </button> </div> </div> </div> </template> <script setup lang=“ts”> const fileInput = ref() const selectedFiles: Ref<Array<any>> = ref([]) const openFileInput = () => { fileInput.value.click() } const previewImage = ref<any>('') const handleFileInputChange = e => { // const files = Array.from(fileInput.value.files) const files = e.target.files console.log('files', files) selectedFiles.value.push(...files) console.log('add selectedFiles', selectedFiles.value) for (let i = 0; i < selectedFiles.value.length; i++) { const file = selectedFiles.value[i] console.log('handleFileInputChange_ file', selectedFiles.value[i]) const reader = new FileReader() reader.onload = e => { previewImage.value = e.target.result } reader.readAsDataURL(file) } } const removeFile = lastModified => { selectedFiles.value = selectedFiles.value.filter( file => file.lastModified !== lastModified ) console.log('remove selectedFiles', selectedFiles.value) } </script> 모바일에서 카메라로 찍은 여러장의 사진들이 각각의 썸네일로 노출되어야함 현재는 최신 사진으로 엎어치기 됨.. 예) 'A B C D' 의 사진이 나와야하는데 현재는 A 찍고 B찍으면 'B B' 가 됨 C찍으면 'C C C'가 됨 도와주세요!
개발자
#input
#type='file'
#vue3
#multiple
#preview
답변 3
댓글 0
보충이 필요해요 1
조회 174
2년 전 · 커리어리 AI 봇 님의 새로운 답변
next js middleware redirect 질문 있습니다.
안녕하세요, next js middleware를 사용해 로그인 사용별 화면을 분기하고 있습니다. 다름이 아니라 사용하면서 문제가 있어 이리저리 검색하다가 해결방법을 찾지 못해 글 남깁니다. 문제1. 브라우저 뒤로가기시 redirect대상 페이지면 title 미변경 문제. redirect된 페이지의 title이 아닌, redirect대상의 title이 적용되었습니다. redirect가 서버에서 브라우저에 요청하는 것이고 브라우저는 이를 실행은 하나 title은 변경되지 않았습니다. 2. 로그인후 뒤로가기를 계속 진행한후 브라우저 첫 페이지(구글)도달후 앞으로 가기를 하면 무한 리디렉션 문제가 발생. 해당 문제는 로그인후 메인 화면으로 넘어간 후 다시 뒤로가기를 반복하고 첫 페이지 도달시, 다시 앞으로 가기해서(예를 들어 로그인 페이지)면 미들웨어가 화면전환 도중에 리디렉션 요청이 많다고 에러를 발생 시킵니다. 아래는 제가 사용하는 코드를 첨부하겠습니다. 요약하자면 redirect하면 title 변경이 안됨. 뒤로가기후 다시 앞으로 가기하면 리디렉션 에러가 발생함. 만약 다른 방법이 있다면, 현업에선 어떻게 처리하는지 궁금합니다. export const verifyUser = (request: NextRequest, moveUrl: string) => { // const includesPage = ['/', '/auth/login', '/dashboard/customdashboard']; const accessToken = request.cookies.get('accessToken')?.value; const url = request.nextUrl.clone(); if (accessToken && isTokenExpired(accessToken)) { // 로그인 페이지 요청시 사용자 검증이 완료된 상태면 / 페이지로 강제 리다이렉트시킴. if (moveUrl === '/auth/login' || moveUrl.startsWith('/signup')) { url.pathname = '/'; return NextResponse.redirect(url); } return NextResponse.next(); } else { // 일반 페이지 요청시 사용자 검증이 미완료된 상태라면 로그인 페이지로 강제 리다이렉트시킴. if (moveUrl === '/auth/login' || moveUrl.startsWith('/signup')) { return NextResponse.next(); } removeLoginCookie(); url.pathname = '/auth/login'; return NextResponse.redirect(url); } };
개발자
#next.js
답변 3
댓글 2
추천해요 1
조회 1,493
2년 전 · 커리어리 AI 봇 님의 새로운 답변
데이터 수집 시스템 조언 부탁드립니다..
안녕하세요. 현재 데이터분석가 인턴으로 회사에 들어간지가 한달이 조금 넘었습니다. 현재 회사에서 분석이 아닌, 직접 데이터를 수집하는 작업을 하고 있습니다. 제가 분석만 하다보니, 데이터를 수집하고 저장하는 작업을 처음해보고 사수도 따로 없다보니 조언을 구할 곳이 없어서 이렇게 게시물로 조언을 요청드립니다.. 지식이 부족해 다소 어렵게 설명을 드려도 이해 부탁드리며, 제 글을 보고 “저 친구는 왜 저렇게 비효율적으로 하지? 이렇게 하면 좋을텐데”라는 생각이 드신다면 바로 댓글이나 쪽지 부탁드립니다. 제가 처음 올려봐서 쪽지 기능이 있나 모르겠네요.. 먼저, 간단하게 제가 진행하고 있는 데이터 수집 절차를 설명드리겠습니다. 1. 컬럼이 한개인 4GB가 조금 넘는 데이터를 수집 코드에 불러와야 한다. 해당 데이터에는 도메인 주소가 담겨 있다. 2. 내 수집 코드는 불러온 데이터를 한행씩 조회하면서 수집을 진행한다. 3. 한 행에 있는 도메인 주소에 순서대로 http 접속을 해서 해당 도메인 주소가 사전에 설정한 특정 조건을 만족하면, 해당 도메인 주소와 사이트에 접속해서 추출한 정수형 값을 DB에 저장한다. 4. 즉, 4기가의 데이터를 불러와 한 행씩 조회해가면서 실시간으로 데이터를 db에 수집하는 코드다. 5. 24시간 동안 코드를 돌리는 수집 예상 기간은 3개월 정도이다. 다음으로는 조금 구체적인 진행 사항을 말하겠습니다. 밑에서부터 길어지니, 바쁘신 분들은 위에 주요 절차만 보시고 조언 주시면 감사하겠습니다. 1. 파이썬만 사용할 줄 알기 때문에, 파이썬을 사용하여 class로 만들어 수집 코드를 짰다. 2. 데이터의 양이 많아서 메모리 부족 오류가 빈번하게 나타나, 하둡과 아파치 스파크를 이용해봤다. 내가 조회할 데이터 파일을 하둡 HDFS에 업로드 한다음에, 아파치 스파크 클러스터를 구축했다. 그리고, pyspark 모듈을 이용해 파티션을 나눠 데이터를 불러왔다. 파티션으로 받아온 값을 리스트로 변환하여 순서대로 해당 도메인 주소로 접속하는 반복문을 진행하면서 데이터를 수집했다. 즉 파티션으로 데이터를 쪼개서 1번 파티션부터 n번 파티션까지 각각 파티션 내부에 도메인 주소 리스트가 반복문을 진행된다고 보면 된다. 각 파티션이 다른 파티션으로 전환되는 과정도 반복문으로 처리했다. 하나의 파티션 마다 내가 만든 class(도메인 리스트를 인자로 받는다)가 한번씩 실행된다고 보면 된다. 3. 수집 속도가 너무 느려서 class에 있는 수집 메소드를 멀티 스레드 방식을 이용해서 수정해주었다. 수집 속도가 매우 빨라졌다. 4. 기존에는 aws의 클라우드 db(dynamo db)를 사용했지만, 과금 문제로 인해 로컬에 db를 설치하기로 했다. 쓰기 속도가 매우 빠른 redis db를 선택했다 5. 위에서 설명한 반복문을 돌면서 조건에 일치한 도메인 주소와 정수 값은 한 행씩 redis db에 key(도메인주소) value(정수값) 형식으로 저장하도록 코드를 만들었다. 이 과정도 class 내부에 포함되어 있다. 6. redis는 on memory db이기 때문에 대용량 데이터를 영구적으로 저장하고 분석하기에 적합하지 않다고 판단해서 1시간마다 redis에 있는 데이터를 postgresql db로 옮겨주는 코드를 따로 만들었다. postgresql db에 미리 redis에서 옮겨갈 테이블을 생성해두었다. redis의 key였던 도메인 이름을 첫 번째 필드에 프리이머리 키로 저장했고 value인 정수 값을 2번 째 필드에 값으로 넣어줬다. 그리고, 마지막 필드에는 자동으로 데이터가 저장될 때, 현재 시간이 넣어지게 테이블을 만들었다. 총 3개의 열로 구성된 테이블에 1시간에 한번씩 redis에 저장해두었던 데이터가 옮겨간다고 생각하면 된다. 7. 처음 redis에 데이터를 저장할 때 ttl을 설정해서 1시간 10분이 지나면 redis db에서 데이터가 자동으로 소멸되도록 설정했으며, 만약 postgresql에 중복된 데이터가 들어간다면 자동으로 무시하고 다음 작업을 진행하도록 테이블 설정을 해줬다. 즉, 실시간으로 데이터가 수집되고 자동으로 시간이 지나면 데이터가 소멸되는 redis db에서 1시간마다 한번 postgresql로 옮겨주는 코드를 따로 만들었다. 8. 수집 코드를 spark-submit 명령문으로 실행해주었다. spark-submit 명령어 앞에 nohup을 해줘서 백그라운드에서 코드가 실행되게 해줬고, 로그 결과를 따로 파일을 만들어 저장되도록 했다. 그리고 파이썬 실행 파일 내에서도 로그를 입력하는 코드를 만들어서, 도메인의 http 접속이 성공했는지의 여부를 로그 파일에 실시간으로 입력되도록 했다. 예를 들어, http 접속이 잘 된 도메인 주소는 로그에 “INFO 도메인 주소: success” 이렇게 기록하고, 타임아웃 에러, 접속 에러, redirect 오류, db 저장 오류는 모두 종류별로 예외 처리해서 로그에서 기록되도록 코드를 구성했다. 파이썬에서 자체적으로 로그를 기록한 파일은 수집코드를 실행하면서 파티션이 전환될 때마다 하나씩 생성된다. 이제 이렇게 제가 실행할 코드는 24시간 내내 수집을 진행하는 코드 하나와 1시간에 한번 데이터를 옮겨주는 스케줄러 코드로 총 2개가 됩니다. 저는 이 코드와 수집 환경을 만들기 위해 모두 도커를 활용하였으며, 사용한 컨테이너와 부가 설명은 다음과 같습니다. spark-master: 하둡과 스파크 클러스터를 구축하는 컨테이너로 standalone모드로 spark-summit 명령어로 파이썬 파일을 실행해주었다. --conf 옵션으로 메모리, 하트비트 간격, 파티션 수 를 지정해주었다. 스파크와 하둡을 처음 사용해봐서 약간의 개념만 있는 상태에서 돌려보니 아직도 세부 설정을 제대로 이해하지 못했다. 결국 worker를 1개 생성해서 파이썬 파일을 처리하도록 하였다. 현재 대다수의 오류가 이 컨테이너에서 발생한다. redis: spark-master에서 실시간으로 실행되고 있는 수집 코드에서 선별된 데이터들이 redis 컨테이너에 있는 redis db에 저장된다. postgresql: 1시간에 한번 redis에 있는 데이터를 옮기기 위해 postgresql 컨테이너를 생성했다. schduler: 1시간에 한번 postgresql 컨테이너에서 작동하고 있는 postgresql db에 redis 데이터를 옮겨주기 위한 스캐줄러 코드를 실행할 컨테이너다. redis-monitor: 실시간으로 redis db를 모니터링 하기 위해 redis-monitor 컨테이너를 생성하여 웹에서 모니터링 툴인 Redis-Stat에 접속한다. postgre-monitor: 마찬가지로, 실시간으로 postgresql db를 모니터링 하기 위해 생성한 컨테이너로 웹에서 Pgadmin4를 사용할 수 있다. 이렇게 총 6개의 컨테이너를 생성하여 내 수집 코드를 실행했는데, 여기서 많은 문제가 발생했습니다. 제가 가진 의문과 문제를 나열하자면 다음과 같습니다. 1. 먼저, 수집 코드를 실행한 다음에 스케줄러 코드를 실행해주었는데, (서로 독립된 컨테이너에서 실행) 두 코드가 DB에 동시에 접속할 때, 충돌이 일어날 가능성이 있지 않을까? 2. 수집 코드를 실행하고 몇분이 지나면 터미널이 먹통이 되고, 코드가 더 이상 실행이 안되는 일이 빈번하게 발생한다. 너무 많은 자원을 사용하고 있어서 그런건가.. 컴퓨터 사양이 안좋아서 그런건가 원인을 잘 모르겠다.. 3. spark-submit 로그를 보면 내 노트북에서는 안그러는데, 대용량 파일을 불러오는 과정에서 파티션 별로 데이터를 정리할 때 오류가 빈번하게 발생한다 . executor가 통신이 안된다는 경고 메세지도 자주 나오고, 특히, Remote RPC client disassociated 라는 오류가 가장 많이 나온다. 내 컴퓨터보다 높은 사양의 클러스터를 구축하려고 해서 그런가. 검색해보니 네트워크 문제이거나, 컨테이너에 할당한 자원을 초과해서 그런거라고 한다. 대용량 데이터를 불러오는 다른 방법을 강구해봐야되나 고민하고 있다. “그래서 요점이 뭐야” 라고 물어보신다면, 저는 현직에서 활동하고 계신 데이터 엔지니어, 백앤드 개발자 분들이 제 글을 본다면 “아니 굳이 왜 그렇게 하지? 이렇게 쉬운 방법이 있는데” 또는 “저기서 이렇게도 해봤나?, 이러면 안정적으로 코드를 돌릴 수 있을텐데”라는 반응으로 갈릴 것 같다고 생각합니다.
개발자
#데이터베이스
#데이터수집
#아파치스파크
#redis
#python
답변 2
댓글 0
추천해요 7
조회 906