///
Search
😎

QNA

상태
위켄 QNA 페이지

Q : 마켓앱에서는 타임리프를 사용하나요?

네 맞습니다.

Q : 리더앱은 언제 구현해야 하나요?

3주차 이후로 진행이 될 예정입니다.

Q : 리더앱은 별도의 프로젝트로 진행해야 하나요?

네 맞습니다.
인텔레제이에서 새 프로젝트를 만들어서 진행하시면 됩니다.

Q : 리더앱의 구현에서 훈련생들은 REST API 부분만 구현하면 되나요?

네 맞습니다.
클라이언트 부분, 즉 리액트 부분은 강사가 구현하여 제공합니다.

Q : 글을 편집하기 위한 에디터는 어떤걸 사용해야 하나요?

토스트에디터를 추천합니다.

Q : 4주간의 미션을 수월하게 수행한다면 어느정도의 실력을 갖추었다고 볼 수 있나요?

백엔드 개발자 1년차에 준하는 실력을 가졌다고 볼 수 있습니다.

Q : 요구사항 정의서의 ERD는 초안인가요?

네 초안입니다.
필요하다고 판단되는 엔티티를 추가해주세요.

Q : 요구사항 정의서의 ERD를 절대 고치면 안되나요?

그렇지 않습니다.
필요하다고 판단이 된다면 고쳐도 됩니다.

Q : 요구사항에 명시적으로 구현하라고 되어있지는 않지만 필요하다고 판단되는 기능들은 추가구현을 하면 되나요?

네 맞습니다.
단 오버엔지니어링과 과한 추상화는 피해주세요.

Q : 테스트케이스는 다다익선인가요?

네 맞습니다.

Q : 정해진 시간보다 빨리 끝냈습니다. 뭘 더 하면 될까요?

코드 퀄리티 개선(가독성 개선)과 테스트케이스를 조금 더 촘촘하게 구성하는 작업을 하시면 됩니다.

Q : 코드 퀄리티 개선과 테스트케이스 추가도 다 했다면 뭘 더 하면될까요?

또 다른 프로젝트 진행하시면 됩니다.
개인적으로 해도 되고 팀을 꾸려서 진행해도 됩니다.
이미 많은 분들이 별도의 프로젝트를 진행하고 계십니다.

Q : 가입시 nickname 을 입력하지 않으면 작가회원이 아닌 일반회원이 되나요?

네 맞습니다.
로그인 후 프로필 페이지에서 작가명을 입력하거나 변경할 수 있습니다.
작가명이 있어야 작가회원입니다.

Q : 프론트엔드 UI를 어떻게 구현할지는 개발자의 재량에 맡기나요?

네 맞습니다.

Q : 아이디찾기와 비밀번호찾기 페이지를 팝업창으로 구현해도 되는지 궁금합니다.

넵! 그렇게 해주시면 됩니다.

Q : 사용자에게 더 편하고 좋을 것 같은 방식이나 기능이 생각났을 때 그것을 프로젝트에 적용해도 되나요?

네. 좋습니다.

Q : 프론트엔드 UI를 예쁘게 잘 구현해야 하나요?

다른 우선순위 높은 작업들을 우선적으로 처리하고 여력이 되시면 UI 퀄리티를 높히는 작업을 하셔도 좋습니다.
UI 퀄리티는 낮아도 문제가 없습니다.

Q : ERD에 아주 사소한 문제가 있습니다. 이상하다고 느껴지더라도 그냥 진행해야 하나요?

아닙니다. ERD가 요구사항과 상충된다면, 요구사항 위주로 설계를 하시고 ERD를 변경해도 됩니다.

Q : 작가가 여러개의 상품을 등록할 수 있나요? ERD에서는 작가와 회원이 1:1 관계로 나와 있는 것 같아서요.

작가는 여러개의 상품을 등록할 수 있습니다.
ERD는 참고만 해주세요.

Q : 글과 관련된 테이블들의 관계가 궁금합니다.

글(Post)은 여러개의 글키워드(PostKeyword)를 가질 수 있습니다.
글과 글키워드를 연결해주는 중간 엔티티는 글태그(PostTag) 입니다.
하나의 postKeywordId 와 authorId 를 조합하면 특정회원이 특정 키워드에 관련해서 쓴 글을 알아낼 수 있습니다.
그 때문에 상품테이블에 authorId 와 postKeywordId 칼럼이 존재합니다.

Q : 각 주차별로 PR이 1개만 생성되어야 하나요?

네 맞습니다.
실무에서는 PR이 여러개 생기는게 더 바람직 하지만, 종합프로젝트 특성상 1개만 만드는 걸로 하겠습니다.

Q : 2주차 작업을 시작하기 전에, 깃 리포지터리에 2Week_Mission 폴더와 2Week_Record 폴더를 만들고 시작해야 하나요?

네 맞습니다.
본인의 1주차 작업물로 부터 작업을 이어 나가도 되고, 강사의 1주차 정답코드에서 이어 나가도 됩니다.

Q : 타임리프 부분, 즉 UI 부분도 꼭 구현해야 하나요?

네 맞습니다.
사용자가 이용하는게 가능하게 만들어야 합니다.
백엔드 개발자라도 기초적인 UI 구현은 무조건 할 수 있어야 합니다.
다만 부트스트랩이나 데이지UI는 사용하지 않아도 됩니다.
CSS 작업도 안해도 괜찮습니다.

Q : 작가가 책 판매 1권당 정산받을 금액을 산정하는 로직은 어떻게 되나요?

도매가격(wholesalePrice) - PG수수료(pgFee) 입니다.

Q : 요구사항 정의서 설명영상이 있나요?

Q : 스프링 DOC 힌트코드가 있나요?

package com.ll.exam.final__2022_10_08.app.springDoc; import io.swagger.v3.oas.annotations.OpenAPIDefinition; import io.swagger.v3.oas.annotations.enums.SecuritySchemeType; import io.swagger.v3.oas.annotations.info.Info; import io.swagger.v3.oas.annotations.security.SecurityScheme; import org.springframework.context.annotation.Configuration; @Configuration @OpenAPIDefinition(info = @Info(title = "MBOOKS API", version = "v1")) @SecurityScheme( name = "bearerAuth", type = SecuritySchemeType.HTTP, bearerFormat = "JWT", scheme = "bearer" ) public class SpringDocConfig { }
Java
복사
package com.ll.exam.final__2022_10_08.app.myBook.controller; import com.ll.exam.final__2022_10_08.app.base.dto.RsData; import com.ll.exam.final__2022_10_08.app.base.rq.Rq; import com.ll.exam.final__2022_10_08.app.myBook.dto.*; import com.ll.exam.final__2022_10_08.app.myBook.entity.MyBook; import com.ll.exam.final__2022_10_08.app.myBook.service.MyBookService; import com.ll.exam.final__2022_10_08.util.Ut; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.List; import static org.springframework.http.MediaType.ALL_VALUE; import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; @RestController @RequestMapping(value = "/api/v1/myBooks", consumes = APPLICATION_JSON_VALUE, produces = APPLICATION_JSON_VALUE) @RequiredArgsConstructor @Tag(name = "ApiV1MyBooksController", description = "로그인 된 회윈이 구매한 책 정보") public class ApiV1MyBooksController { private final MyBookService myBookService; private final Rq rq; @GetMapping(value = "", consumes = ALL_VALUE) @Operation(summary = "로그인된 회원이 보유한 도서 목록", security = @SecurityRequirement(name = "bearerAuth")) public ResponseEntity<RsData<MyBooksResponse>> myBooks() { ... } .... }
Java
복사

Q : 스프링 시큐리티 힌트코드가 있나요?

package com.ll.exam.final__2022_10_08.app.security; import com.ll.exam.final__2022_10_08.app.security.filter.JwtAuthorizationFilter; import com.ll.exam.final__2022_10_08.app.security.handler.ApiAuthenticationEntryPoint; import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Bean; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.CorsConfigurationSource; import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import static org.springframework.security.config.http.SessionCreationPolicy.STATELESS; @EnableWebSecurity @RequiredArgsConstructor public class ApiSecurityConfig { private final JwtAuthorizationFilter jwtAuthorizationFilter; private final ApiAuthenticationEntryPoint authenticationEntryPoint; @Bean public SecurityFilterChain apiFilterChain(HttpSecurity http) throws Exception { http .antMatcher("/api/**") .exceptionHandling(exceptionHandling -> exceptionHandling .authenticationEntryPoint(authenticationEntryPoint) ) .httpBasic().disable() .csrf().disable() .cors(cors -> cors .configurationSource(corsConfigurationSource()) ) .authorizeRequests( authorizeRequests -> authorizeRequests .antMatchers("/api/*/member/login").permitAll() .anyRequest() .authenticated() // 최소자격 : 로그인 ) .sessionManagement(sessionManagement -> sessionManagement .sessionCreationPolicy(STATELESS) ) .formLogin().disable() .addFilterBefore( jwtAuthorizationFilter, UsernamePasswordAuthenticationFilter.class ) .logout().disable(); return http.build(); } @Bean public CorsConfigurationSource corsConfigurationSource() { CorsConfiguration corsConfiguration = new CorsConfiguration(); corsConfiguration.addAllowedOrigin("*"); corsConfiguration.addAllowedHeader("*"); corsConfiguration.addAllowedMethod("*"); UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource(); urlBasedCorsConfigurationSource.registerCorsConfiguration("/api/**", corsConfiguration); return urlBasedCorsConfigurationSource; } }
Java
복사
package com.ll.exam.final__2022_10_08.app.security; import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Bean; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.authentication.AuthenticationFailureHandler; import org.springframework.security.web.authentication.AuthenticationSuccessHandler; @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) @RequiredArgsConstructor public class SecurityConfig { private final AuthenticationSuccessHandler authenticationSuccessHandler; private final AuthenticationFailureHandler authenticationFailureHandler; @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http .httpBasic().disable() .formLogin( formLogin -> formLogin .loginPage("/member/login") // GET .loginProcessingUrl("/member/login") // POST .successHandler(authenticationSuccessHandler) .failureHandler(authenticationFailureHandler) ) .authorizeRequests( authorizeRequests -> authorizeRequests .antMatchers("/v3/api-docs/**", "/swagger-ui/**", "/swagger-ui.html") .hasAuthority("ADMIN") .anyRequest() .permitAll() ) .logout( logout -> logout .logoutUrl("/member/logout") ); return http.build(); } }
Java
복사