묻고 답해요
158만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결내 업무를 대신 할 파이썬(Python) 웹크롤링 & 자동화 (feat. 주식, 부동산 데이터 / 인스타그램)
셀레니움 변경점
https://selenium-python.readthedocs.io/locating-elements.htmlfind_element/s 함수에 변경점이 생겨 현재 교재로는 코드가 작동하지 않습니다.위 페이지 참고하시면 되겠습니다.
-
미해결인공지능 기초수학
강의교안 부탁드립니다
수강신청하였습니다! 강의교안 부탁드립니다. rhaxodl1104@gmail.com
-
해결됨홍정모의 따라하며 배우는 C++
얕은 복사시 소유권 박탈에 관한 질문
#include <iostream> //#include "autoptr.h" #include "autoptr2.h" #include "resource.h" #include "Timer.h" AutoPtr<Resource> generateResource() // AutoPtr<Resource> 타입을 리턴하는 함수 { // 10000000 의 length를 가진 Resource타입의 멤버를 가지는 AutoPtr 객체 생성 AutoPtr<Resource> res(new Resource(10000000)); return res; } int main() { using namespace std; streambuf* orig_buf = cout.rdbuf(); // cout.rdbuf(NULL); 화면에 출력되는 메세지들 끄기. 시간 어마어마하게 걸릴테니까 😎 Timer timer; { AutoPtr<Resource> main_res; main_res = generateResource(); // ⭐ generateResource() 리턴값은 R-value } cout.rdbuf(orig_buf); //cout << timer.elapsed() << endl; timer.elapsed();//실행시간 재서 출력 } 메인.cpp#pragma once #include <iostream> using namespace std; template<typename T> class AutoPtr { public: T* m_ptr; public: AutoPtr(T* ptr = nullptr) :m_ptr(ptr) { cout << "AutoPtr default constructor" << endl; } ~AutoPtr() { cout << "AutoPtr destructor" << endl; if (m_ptr != nullptr) delete m_ptr; } AutoPtr(AutoPtr&& a) // ⭐이동생성자⭐ : m_ptr(a.m_ptr) // ⭐얕은 복사⭐ 그냥 대입만 하면 땡이다! { cout << "AutoPtr move constructor" << endl; a.m_ptr = nullptr; // really necessary? } AutoPtr& operator = (AutoPtr&& a) //R-value 레퍼런스 , ⭐*이동 대입 연산자 오버로딩⭐ { cout << "AutoPtr move assignment" << endl; if (&a == this) return *this; // 공간은 비워줘야하는 것 똑같고 (delete 안하고 그냥 대입하면 메모리 누수가 발생할 수 있다) if (m_ptr != nullptr) delete m_ptr; m_ptr = a.m_ptr; // ⭐얕은 복사⭐ 그냥 대입만 하면 땡이다! a.m_ptr = nullptr; // 소유권 박탈 return *this; } T& operator *() const { return *m_ptr; } T* operator ->() const { return m_ptr; } bool inNull() const { return m_ptr == nullptr; } };AutoPtr.h#pragma once #include <iostream> using namespace std; class Resource { public: int* m_data = nullptr; unsigned m_length = 0; public: Resource() // 기본 생성자 { cout << "Resource constructed" << endl; } Resource(unsigned length) // 일반 매개변수 1개 생성자 { cout << "Resource length constructed" << endl; this->m_data = new int[length]; this->m_length = length; } Resource(const Resource& res) // 💎복사 생성자💎 { cout << "Resource copy constructed" << endl; Resource(res.m_length); for (unsigned i = 0; i < m_length; ++i) // 내용물을 전부 깊은 복사 (시간이 꽤 걸림) m_data[i] = res.m_data[i]; } ~Resource() // 소멸자 { cout << "Resource destroyed" << endl; } Resource& operator = (Resource& res) // 💎대입 연산자 오버로딩💎 { cout << "Resource copy assignment" << endl; if (&res == this) return *this; // 대입하려는게 자기 자신이면 아무것도 안함 if (this->m_data != nullptr) delete[] m_data; // 1. 내 자신의 m_data 비워주기 m_length = res.m_length; // 2. 대입으로 넘겨받은 res의 length 로 내 length 갱신 m_data = new int[m_length]; // 3. 비워진 내 자신의 m_data에 새로운 공간 할당받기 for (unsigned i = 0; i < m_length; ++i) // 4. m_data내용물 넣기. m_data[i] = res.m_data[i]; // 대입으로 넘겨받은 res의 m_data 내용물들을 **내 m_data**에 깊은 복사 return *this; } };Resource.h 위 3코드는 수업에 나온 코드입니다. 얕은 복사시에 강사님께서 소유권 박탈의 목적으로 매개변수로 받은 참조 객체의 private변수인 포인터변수를 꼭 nullptr로 초기화를 해주는것이 깔끔하다고 하셨습니다.예를 들면AutoPtr(AutoPtr&& a) // ⭐이동생성자⭐ : m_ptr(a.m_ptr) // ⭐얕은 복사⭐ 그냥 대입만 하면 땡이다! { cout << "AutoPtr move constructor" << endl; a.m_ptr = nullptr; // really necessary? }이나AutoPtr& operator = (AutoPtr&& a) //R-value 레퍼런스 , ⭐*이동 대입 연산자 오버로딩⭐ { cout << "AutoPtr move assignment" << endl; if (&a == this) return *this; // 공간은 비워줘야하는 것 똑같고 (delete 안하고 그냥 대입하면 메모리 누수가 발생할 수 있다) if (m_ptr != nullptr) delete m_ptr; m_ptr = a.m_ptr; // ⭐얕은 복사⭐ 그냥 대입만 하면 땡이다! a.m_ptr = nullptr; // 소유권 박탈 return *this; }이 부분에서 a.m_ptr=nullptr;이렇게요. 질문1. nullptr로 초기화를 안시키면(소유권 박탈을 안하면) 문제가 생기나요?2.제가 찾아보니까 "박탈 시키지 않으면 대입 연산자 인수로 이 인스턴스를 참조 하게 된 매개 변수 AutoPtr && a가 대입 연산자 호출이 종료됨에 따라 소멸자가 호출되어 delete될 수 있기 때문이다." 라는 글을 어디서 봤는데 이게 무슨말인지 모르겠는데 맞는 말인가요??3.저 위의 코드에서 혹시 매개변수로 기능하는AutoPtr && a같은 매개변수 객체도 함수 호출시에정식적인 객체 처럼 생성자와 소멸자를 호출하나요?안하는걸로 알고있고 안하기 때문에 2번 질문이 이해가 안되서 질문하는거거든요.혹시 제가 햇갈리고 있나 싶어서 다시 질문드립니다.
-
미해결홍정모의 따라하며 배우는 C언어
재귀함수에서 출력이 왜 연속으로 이루어지는지 모르겠습니다
void print_binary_rc(unsigned long n){int i = n % 2;if (n > 1)print_binary_rc(n / 2);printf("%d", i);}이게 강의에서 설명해주신 코드였습니다 강의에서 쓰신 print_binary 재귀함수를 그냥 Print_Binary_by_ReCursion의 약어로 pbrc로 표현했습니다.이건 재귀함수가 이루어지는 과정을 제가 생각한 방식대로 도식화 한 것입니다. 인셉션을 예로 들어 설명해주신 것철머 함수 안의 함수 안의 함수 안의 함수가 이루어진다는 것을 확인했습니다.제가 궁금한 것은 위 그림에도 적었듯이 n=1까지 와서 더 이상 n>=2가 되지 않아 if문을 탈출하고 pritnf("%d", i);를 만나게 되는데 그때 맨처음으로 i=1이 출력되는 것은 이해가 되었습니다. 하지만 위 도식의 화살표가 가르키는 것처럼 왜 그 다음 i=0이 출력되는 것인지 모르겠습니다.if 문을 탈출한 것은 n=1인 순간 뿐인데 왜 그 위 과정에서도 i=0을 프린트하게 되는 것인지 궁금합니다. 디버거로 찍어도 잘 안 보여서 질문드립니다. 만약 pbrc(2)가 pbrc(1)의 과정도 포함하고 있어서 프린트를 하는 것이라면pbrc(1)에서 i=1이 출력되고pbrc(2)에서 i=1 i=0이 출력되고pbrc(3)에서 i=1 i=0 i=1이 출력되고pbrc(4)에서 i=1 i=0 i=1 i=0이 출력되어버려서총 1 10 101 1010 라는 10자리 숫자가 출력되어야 한다고 생각이 들어서 이해를 도와주시면 감사하겠습니다 ++ 혼자 고민을 더하다가 제 나름의 답을 얻었는데 혹시 pbrc(1)에서 i=1을 출력하고 나면 이제 그 상위의 pbrc(2)의 단계에서 if문의 반복을 모두 마쳤으니 i=0을 출력하고 그리고 나서 pbrc(5)의 단계에서 if문 반복을 모두 마쳤으니 if를 탈출해 밑에 있는 i=1을 출력하고 마지막으로 pbrc(10)의 영역에서 if문을 모두 마쳤으니 밑의 i=0을 출력한다고 봐야 할까요? 이해가 될 듯하면서도 물고늘어지면 이해가 안됩니다
-
해결됨웹 게임을 만들며 배우는 React
강의 3-4. 컴포넌트 분리와 props에서 분리된 컴포넌트에 this바인딩이 되나요?
Try.jsx 에서 {this.props.value}를 사용하는데 이때 this는 Try컴포넌트에 바인딩 된다고 생각하는데 NumberBaseball.jsx 컴포넌트의 render함수에서 상위로 스코프가 체이닝 되나요? 정리하면 컴포넌트를 import 해서 사용할 때 this바인딩이 <Try />컴포넌트의 this는 어떻게 바인딩 이루어져서 props를 받을 수 있는지 궁금합니다 ㅠ
-
미해결화이트해커가 되기 위한 8가지 웹 해킹 기술
칼리리눅스 eth1 ip
etc/network/interfaces에 강의에서 설명하신 부분을 추가하였는데도 ip addr로 확인해보면eth1에는 ip가 할당되지 않습니다ㅠㅠ 어떻게 해야하나요? systemctl restart networking으로 네트워크를 재시작해도 안되고 아예 재부팅해도 안되네요...
-
해결됨홍정모의 따라하며 배우는 C++
수업시간 코드인데 결과값이 왜 이렇게 나오는지 궁금합니다.
#include <iostream> #include "autoptr.h" //#include "autoptr2.h" #include "resource.h" #include "Timer.h" AutoPtr<Resource> generateResource() // AutoPtr<Resource> 타입을 리턴하는 함수 { // 10000000 의 length를 가진 Resource타입의 멤버를 가지는 AutoPtr 객체 생성 AutoPtr<Resource> res(new Resource(10000000)); return res; } int main() { using namespace std; streambuf* orig_buf = cout.rdbuf(); // cout.rdbuf(NULL); 화면에 출력되는 메세지들 끄기. 시간 어마어마하게 걸릴테니까 😎 Timer timer; { AutoPtr<Resource> main_res; main_res = generateResource(); // ⭐ generateResource() 리턴값은 R-value } cout.rdbuf(orig_buf); //cout << timer.elapsed() << endl; timer.elapsed();//실행시간 재서 출력 }메인.cpp#pragma once #include <iostream> using namespace std; template<typename T> class AutoPtr { public: T* m_ptr; public: AutoPtr(T* ptr = nullptr) :m_ptr(ptr) { cout << "AutoPtr default constructor" << endl; } ~AutoPtr() { cout << "AutoPtr destructor" << endl; if (m_ptr != nullptr) delete m_ptr; } AutoPtr(const AutoPtr& a) // 💎복사 생성자💎 { cout << "AutoPtr copy constructor" << endl; // deep copy m_ptr = new T; // T가 Resource 타입으로 들어오면 m_ptr은 Resource 타입의 포인터 *m_ptr = *a.m_ptr; // ⭐Resource의 '대입 연산자 오버로딩 호출 , deep copy } AutoPtr& operator = (const AutoPtr& a) //L-value 레퍼런스 , 💎대입 연산자 오버로딩💎 { cout << "AutoPtr copy assignment" << endl; if (&a == this) return *this; if (m_ptr != nullptr) delete m_ptr; // deep copy m_ptr = new T; // 새로운 빈 공간 할당 받기. T가 Resource 타입으로 들어오면 m_ptr은 Resource 타입의 포인터 *m_ptr = *a.m_ptr; // ⭐Resource의 '대입 연산자 오버로딩' 호출 , deep copy return *this; } T& operator *() const { return *m_ptr; } T* operator ->() const { return m_ptr; } bool inNull() const { return m_ptr == nullptr; } };AutoPtr 헤더파일#pragma once #include <iostream> using namespace std; class Resource { public: int* m_data = nullptr; unsigned m_length = 0; public: Resource() // 기본 생성자 { cout << "Resource constructed" << endl; } Resource(unsigned length) // 일반 매개변수 1개 생성자 { cout << "Resource length constructed" << endl; this->m_data = new int[length]; this->m_length = length; } Resource(const Resource& res) // 💎복사 생성자💎 { cout << "Resource copy constructed" << endl; Resource(res.m_length); for (unsigned i = 0; i < m_length; ++i) // 내용물을 전부 깊은 복사 (시간이 꽤 걸림) m_data[i] = res.m_data[i]; } ~Resource() // 소멸자 { cout << "Resource destroyed" << endl; } Resource& operator = (Resource& res) // 💎대입 연산자 오버로딩💎 { cout << "Resource copy assignment" << endl; if (&res == this) return *this; // 대입하려는게 자기 자신이면 아무것도 안함 if (this->m_data != nullptr) delete[] m_data; // 1. 내 자신의 m_data 비워주기 m_length = res.m_length; // 2. 대입으로 넘겨받은 res의 length 로 내 length 갱신 m_data = new int[m_length]; // 3. 비워진 내 자신의 m_data에 새로운 공간 할당받기 for (unsigned i = 0; i < m_length; ++i) // 4. m_data내용물 넣기. m_data[i] = res.m_data[i]; // 대입으로 넘겨받은 res의 m_data 내용물들을 **내 m_data**에 깊은 복사 return *this; } };Resource헤더파일 결과값이AutoPtr default constructorResource length constructedAutoPtr default constructorAutoPtr copy assignmentResource constructedResource copy assignmentAutoPtr destructorResource destroyedAutoPtr destructorResource destroyed 이렇게 나왔습니다.여기서 궁금한점은 소멸자 출력문구 순서인데요디버깅을 해봤는데Timer timer;{AutoPtr<Resource> main_res;main_res = generateResource();}이 지역범위를 벗어나고 소멸자 호출을 시작하는데 정확히 main_res = generateResource(); 이부분에서AutoPtr destructorResource destroyedAutoPtr destructorResource destroyed이 4번의 소멸자가 호출됩니다. 그에 대한 설명을 나름 추리해봤는데 제 설명이 맞는지 확인해주시고 혹시 틀렸다면 정확히 어떤점에서 틀렸고 어떠한 근거로 저 소멸자호출문구가 출력 되는건지 알려주실 수 있나요? 저의 설명==================================AutoPtr destructor >>> generateResource() 함수의 리턴 값인 res를 블럭이 끝나면서 소멸자로 할당값을 해제해주는 과정에서 소멸자 호출 Resource destroyed >>> 소멸자 호출 문구 출력 이후 if (m_ptr != nullptr) delete m_ptr; 구문 실행과정에서 m_ptr이 resource타입이니까 삭제시에 resource 소멸자 호출 AutoPtr destructor >>> main_res 역시 해제하기 위해 autoptr의 소멸자 호출 Resource destroyed >>>소멸자 호출 문구 출력 이후 if (m_ptr != nullptr) delete m_ptr; 구문 실행과정에서m_ptr이 resource타입이니까 삭제시에 resource 소멸자 호출
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part2: 게임 수학과 DirectX12
삼각형 띄우기 Shader Create Failed ! 에러 관련.
삼각형 띄우기 학습후 코드 실행시"Shader Create Failed !"라는 메시지가 뜨는 경우가 있습니다.이 경우 혹시 .hlsli 파일을 저장할때인코딩 하여 저장 -> "유니코드(서명 있는 UTF08) - 코드 페이지 65001"로 저장하지 않았는지 확인해 보시면 좋을것 같습니다.이경우 에러가 발생하며,"한국어 - 코드페이지 949" 로 저장시 에러가 발생하지 않더군요.멀티바이트와 유니코드 관련 문제 인것 같고D3DCompileFromFile 을 사용할때 아마 셰이더 파일을 읽어서 Blob 이라는 버퍼에 이진데이터로 직렬화하여 저장을 하는거 같은데,그때 멀티바이트를 직렬화 할때랑 유니코드를 직렬화 할때 값이 달라서 발생하는 문제인것 같은데, 이게 맞는건지. 다른분들은 어떠신지, 같은 문제가 발생하는지 궁금합니다.
-
미해결홍정모의 따라하며 배우는 C언어
10.12 2중포인터의 작동원리 질문
10.12 에서 이중포인터 설명하실때int a = 7;int *ptr = &a;*ptr = 8;int *pptr = &ptr;**pptr = 9; 라고 자료화면이 나오면서 설명하시는데y = &x 일때 *y = x , y = &x 라고 알고있는데그렇다면 a = 7 일때 ptr = 7이고 *pptr 도 7이 되야 맞는 문법아닌가요 ?? 제가 잘못알고있는건가요??
-
해결됨스프링 시큐리티
SessionCreationPolicy의 IF_REQUIRED와 NEVER 속성에 대해서
- 학습 관련 질문을 남겨주세요. 상세히 작성하면 더 좋아요! - 먼저 유사한 질문이 있었는지 검색해보세요. - 서로 예의를 지키며 존중하는 문화를 만들어가요. - 잠깐! 인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요. IF_REQUIRED의 설명 중 "필요시"라고 되어있는 부분이 있는데 어떤 상황이 "필요시"에 해당할까요??NEVER의 설명 중 스프링 시큐리티가 생성하지 않지만 "이미 존재"하면 사용이라고 써놓으셨는데, 애초에 생성하지 않았는데 어떻게 이미 존재할 수 있나요??
-
미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part2: 자료구조와 알고리즘
Environment.TickCount & Int32.MaxValue; 코드 질문
안녕하세요 강사님! 강의 잘 듣고 있습니다.질문 게시판 글도 간단히 보면서 강의를 보고 있는데요.int currentTick = Environment.TickCount & Int32.MaxValue;위의 코드를 답변으로 주신 내용이 있던데c#강의에 다시 가서 &비트 연산을 봐도코드 이해를 못해서요.부호가 제거된다는 것 같은데 왜 부호가 없어지고 코드가 정상으로 돌아가는지 잘 모르겠습니다.답변 부탁드립니다.
-
해결됨처음하는 딥러닝과 파이토치(Pytorch) 부트캠프 (쉽게! 기본부터 챗GPT 핵심 트랜스포머까지) [데이터분석/과학 Part3]
from_pretrained 에 관한 질문입니다
강의 4:53 에 나오는 from_pretrained 함수에 관한 질문입니다.공식 문서를 아무리 찾아봐도, 더 미궁 속으로 빠지는 듯한 느낌만 들어서(...) 질문 올립니다. from_pretrained 메소드는 huggingface에서 제공하는 그 어떠한 클래스에도 공통적으로 적용이 가능한 것인지 궁금합니다.공식 문서에서 from_pretrained를 검색해본 결과, 각 검색 페이지마다 from_pretrained의 파라미터가 다르게 나오고, 그에 대한 설명조차도 찾을 수가 없었습니다...예를 들어, FeatureExtractionMixin 의 from_pretrained 메소드의 파라미터는 9개인 반면, AutoTokenizer의 from_pretrained 메소드의 파라미터는 13개 라고 서술되어 있는 경우를 볼 수 있었습니다.또한, 강의에서 사용하였던feature_extractor = ViTFeatureExtractor.from_pretrained("google/vit-base-patch16-224-in21k") feature_extractor이 코드와,model = ViTForImageClassification.from_pretrained('google/vit-base-patch16-224-in21k', num_labels=10, # 10개의 클래스로 분류를 해야 함 id2label=id2label, label2id=label2id)이 코드에서도 역시 from_pretrained 메소드가 사용되었는데,공식 문서에서 ViTFeatureExtractor와 ViTForImageClassification을 아무리 찾아보아도 from_pretrained 메소드에 관한 설명은 볼 수가 없었으며, 각각의 경우에 적용되는 파라미터에 관한 내용 역시 찾아볼 수 없었습니다.이런 경우, 다른 코드에 from_pretrained 메소드를 적용할 때에는 해당되는 내용을 어떻게 찾아야 하는 것인지 궁금합니다.
-
미해결스프링 배치
ItemStream의 open 메서드 관련 궁금합니다
안녕하세요 강사님~먼저 질좋은 강의를 만들어주셔서 감사합니다 :)ItemStream 관련 궁금증이 생겨 질문드리게 되었는데요!public void open(ExecutionContext executionContext)위 메서드의 ExecutionContext 는 Step의 ExecutionContext 로 이해했습니다.그런데 Step 중간에 오류가 발생할 경우. 전체 Job이 실패하고.JobExecution & JobExecutionContext 가 새로 생성되며, 해당 Step의 StepExecution & StepExecutionContext 또한 새로 생성되어. 재시작전의 StepExecutionContext 에 저장해둔 index 는 꺼내어 사용 못하는게 아닌가요..?!재시작 후에 ExecutionContext 에서 index를 가져올 수 있는 부분이 헷갈립니다ㅜ추가로 index 예제는 ItemStream 통한 복구대비를 해두어. 재시작시 오류가 발생한 Chunk의 item부터 이어서 처리할 수 있었는데요.ItemStream 없이 ItemReader 만 사용할 경우는 트랜잭션 커밋되어 반영된 Chunk 가 있어도 무시하고 처음 Chunk 부터 다시 작업을 하게되는걸까요?
-
해결됨토비의 스프링 부트 - 이해와 원리
안녕 하세요~~
강의 내용과 관련 없는 내용이기는 한데...너무 궁금한게 있어서요~~토비님은 스프링으로 실무를 하실 때 테스트를 어떻게 하시나요?컨트롤러, 서비스, 도메인 그외 등등 있을 때각자 다 테스트를 하시는지...고전파로 하시는지 런던파로 하시는지...좀 궁금합니다~~ 감사합니다
-
미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
jpa 1:n 조인
=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/)[질문 내용]일대다 관계의 테이블에서 조인을 하면 데이터가 뻥튀기 되는건 당연한건데 이걸 자바 객체 입장에선 리스트로 어차피 한번에 다 들고있으니까 뻥튀기가 될 필요가 없다고 생각하면 될까요 ? (그래서 distinct를 사용하고 )
-
해결됨넓고 얕게 외워서 컴공 전공자 되기
Stack과 heap
stack은 thread가 사용하고 heap은 process가 사용한다고 말씀하셨고 각 stack별로 용도가 다르고 heap은 공용으로 사용하는 주거 공간이라고 설명해주셨습니다.비유적으로 설명해주셔서 실제로 다른 곳에서는 어떻게 정리되어있는지 궁금해서 찾아봤는데 stack은 함수가 호출되면서 지역 변수와 매개변수가 저장되는 영역, heap은 사용자에 의해 메모리 공간이 동적으로 할당되고 해제되는 영역이라고 설명이 되어있었습니다.(찾아본 글: https://junghyun100.github.io/%ED%9E%99-%EC%8A%A4%ED%83%9D%EC%B0%A8%EC%9D%B4%EC%A0%90/)두 가지의 설명을 어떻게 연결(?)시켜서 이해할 수 있을지 모르겠습니다.
-
미해결모바일 웹 퍼블리싱 포트폴리오 with Figma
상품디테일 하단 아코디언 질문이요~
안녕하세요. 선생님~상품디테일 하단 아코디언 진행중에 처음에 타이틀 +일때 클릭하면 -로 변경되고 디테일이 나오는데요, 다시 타이틀 -를 누르면 디테일이 사라지면서 타이틀이 +로 바뀌어야 하는거 아닐까요?클릭하면 계속 active만 추가되었다 빠졌다해서 디테일은 그대로 있고 타이틀 부분만 +, -변경되서 질문드립니다~혹시 js 이렇게 변경해서 사용해도 되는걸까요? 확인부탁드립니다~
-
미해결스프링 핵심 원리 - 기본편
getInstance()와 DIP
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)[질문 내용]싱글톤은 DIP를 위반한다는 설명에서(기존)public MemberService memberService(){ return new MemberServiceImpl(memberserviceRepository());}(싱글톤 패턴 적용 시)public MemberService memberService(){ return MemberServiceImpl.getInstance();}에서 구체 클래스에 의존하기 때문에 DIP를 위반한다고 하셨습니다. 하지만 AppConfig에는 객체 인스턴스를 연결하기 위해 어차피 구체클래스를 사용하는데, DIP를 위반한다고 하는 이유가 뭔지 궁금합니다!
-
미해결스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술
gradlew.bat 파일이 안보입니다. 또한 어떻게 실행해야될지 감이안잡히네요
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]gradlew.bat 위치는 인텔리제이 상에서 C:\test\hello-spring\hello-spring 있다고는 하는데 폴더에 없어요
-
미해결스프링 시큐리티
접근이 거부되었습니다. 예외가 발생합니다.
5) 웹 기반 인가처리 DB 연동 - FilterInvocationSecurityMetadataSource (2) 강의 관련 질문입니다. 참고로, 현재 SecurityConfig 파일이 파일명으로 구분해서 Ajax 인증용과 폼인증 두개 입니다.문제는 로그인까지 성공하고 /mypage 로 들어가면 접근 거부 예외가 생깁니다.'org.springframework.security.access.AccessDeniedException: 접근이 거부되었습니다.' SecurityConfig , AjaxSecurityConfig 설정파일명으로 구분했고 마지막에 설정 코드도 올렸지만 authenticationManager 같은 Bean 메서드들도 이름으로 구분했습니다. 사용자정보, 권한정보등 제대로 갖고 왔는데 어디가 잘못된건지 잘모르겠네요..혹시 시큐리티 설정파일에서 서비스 클래스 두가지를 사용해서 그런지 의심도 되고 그렇네요..private final SecurityResourceService securityResourceService;private final UserDetailsService userDetailsService; 아래에 도움이 될까 해서 디버깅화면 캡쳐해서 올렸습니다.감사합니다. AbstractSecurityInterceptor 클래스UrlFilterInvocationSecurityMetadataSource 클래스 RoleVoter 클래스ExceptionTranslationFilter 클래스FormAccessDeniedHandler 클래스AccessDeniedException 클래스 웹페이지에는 흰 배경만 나타나고 302 코드를 반환하네요.Request URL:http://localhost:8080/mypageRequest Method:GETStatus Code:302Remote Address:[::1]:8080Referrer Policy:strict-origin-when-cross-orig 시큐리티 설정파일 @Configuration@RequiredArgsConstructor@Order(1)public class SecurityConfig { @Bean public WebSecurityCustomizer configure() { return (web) -> web.ignoring().mvcMatchers( "/css/**", "/js/**", "/error" ); } private final AuthenticationConfiguration authenticationConfiguration; private final AuthenticationDetailsSource authenticationDetailsSource; private final AuthenticationSuccessHandler formAuthenticationSuccessHandler; private final AuthenticationFailureHandler formAuthenticationFailureHandler; private final SecurityResourceService securityResourceService; private final UserDetailsService userDetailsService; public PasswordEncoder passwordEncoder() { return PasswordEncoderFactories.createDelegatingPasswordEncoder(); } @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/", "/users", "user/login/**", "/login*").permitAll() .antMatchers("/mypage").hasRole("USER") .antMatchers("/messages").hasRole("MANAGER") .antMatchers("/config").hasRole("ADMIN") .anyRequest().authenticated() .and() .exceptionHandling() //.accessDeniedPage("/denied") .accessDeniedHandler(accessDeniedHandler()) .and() .addFilterBefore(customFilterSecurityInterceptor(), FilterSecurityInterceptor.class) ; http .formLogin() .loginPage("/login") .loginProcessingUrl("/login_proc") .authenticationDetailsSource(authenticationDetailsSource) .defaultSuccessUrl("/") .successHandler(formAuthenticationSuccessHandler) .failureHandler(formAuthenticationFailureHandler) .permitAll() ; //http.csrf().disable(); return http.build(); } public FormAuthenticationProvider formAuthenticationProvider() { return new FormAuthenticationProvider(userDetailsService, passwordEncoder()); } @Bean public AccessDeniedHandler accessDeniedHandler(){ FormAccessDeniedHandler accessDeniedHandler = new FormAccessDeniedHandler(); accessDeniedHandler.setErrorPage("/denied"); return accessDeniedHandler; } @Bean public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception { ProviderManager authenticationManager = (ProviderManager) authenticationConfiguration.getAuthenticationManager(); authenticationManager.getProviders().add(formAuthenticationProvider()); return authenticationManager; } @Bean public FilterSecurityInterceptor customFilterSecurityInterceptor() throws Exception { FilterSecurityInterceptor filterSecurityInterceptor = new FilterSecurityInterceptor(); filterSecurityInterceptor.setSecurityMetadataSource(urlFilterInvocationSecurityMetadataSource()); filterSecurityInterceptor.setAccessDecisionManager(affirmativeBased()); filterSecurityInterceptor.setAuthenticationManager(authenticationManager(authenticationConfiguration)); return filterSecurityInterceptor; } public AccessDecisionManager affirmativeBased() { AffirmativeBased affirmativeBased = new AffirmativeBased(getAccessDecisionVoters()); return affirmativeBased; } private List<AccessDecisionVoter<?>> getAccessDecisionVoters() { return Arrays.asList(new RoleVoter()); } /** * 자원/권한 정보를 저장하고 있는 클래스를 빈으로 생성 * @return * @throws Exception */ @Bean public FilterInvocationSecurityMetadataSource urlFilterInvocationSecurityMetadataSource() throws Exception { return new UrlFilterInvocationSecurityMetadataSource(urlResourcesMapFactoryBean().getObject()); } private UrlResourcesMapFactoryBean urlResourcesMapFactoryBean() { UrlResourcesMapFactoryBean urlResourcesMapFactoryBean = new UrlResourcesMapFactoryBean(); urlResourcesMapFactoryBean.setSecurityResourceService(securityResourceService); return urlResourcesMapFactoryBean; }}