ellie
수강평 작성수
-
평균평점
-
블로그
전체 4![[워밍업 BE 프로젝트 3기] 4주차 발자국](https://cdn.inflearn.com/public/main/blog/default_thumbnail.png?w=260)
2025. 03. 30.
0
[워밍업 BE 프로젝트 3기] 4주차 발자국
학습 4주차에는 남은 강의를 모두 학습했습니다.Spring security로 로그인 개발Docker로 MySQL 실행 및 프로젝트 빌드민감 정보인 DB 패스워드는 Jasypt로 암호화 GCP에 Compute Engine 인스턴스 생성, 컨테이너 실행도메인 연결 및 HTTPS 적용 미션 이번 주 미션 2개는 미니 프로젝트가 아니라서 강의의 마지막 부분을 잘 따라하면 완성할 수 있었습니다.포트폴리오에 내 데이터 넣기내 포트폴리오 도메인 공유하기 4주차 후기 항상 인프라 설정할 때마다 하나씩 막히는 부분이 생기는 것 같습니다. 잘 모르는 부분이다 보니 따라 치기 바빠서인 것 같아요. 😓배포하고 도메인 연결도 해보니 어드민 쪽 뷰 개발하지 못한 부분이 아쉽습니다. 접속 로그 확인해보고 싶었는데, 지금은 직접 컨테이너에 접속해야 한다는 번거로움이 .. 이번에 배포 된 컨테이너에서 명령어 입력할 때 마다 동작이 너무너무 느려서 속 터지는 줄 알았습니다. ㅎ특히 mysql 에 접속할 때 ..에러가 뜨는데도 한세월이 걸렸고, 왜 에러인지도 잘 몰랐습니다. 원인은 명령어를 강의 노트에서 붙여넣기한 부분인 것 같은데, 명령어를 직접 입력했더니 잘 되더라고요.스페이스가 뭔가 다르게 인식 된 건지.. 너무 억까 당했다고 생각했습니다 🫨 강의가 오래된 건 아니지만 그 사이에 도메인 설정 중 개인정보 보호 옵션에서 이 제거되었다고 합니다.제가 만드는 화면에서는 저런 경고창이 안 떠서 어떤걸 할지 고민하다, 강의 화면에 나오는 경고문 대로 공개될 정보 제한으로 설정했습니다. 개인적으로 도메인을 구입해보고 싶었는데, 후회 없을 도메인을 구회하기 위해 항상 고민만 하다가 미루고 있었습니다.그래서 이번 기회에 구입해본 것도 좋았습니다. ㅎㅎ 언젠간 포트폴리오 뿐만 아니라 추가 정보를 담은 제 서버를 구축해서 배포해보고 싶습니다. 워밍업 클럽 3기 후기 1달 간 참여하면서 가장 좋았던 부분은 수강에 동기부여가 된 점입니다. 강의만 구입했다면, 그리 길지 않은 강의임에도 불구하고 한 달 동안 수강하기 어려웠을 것 같습니다. 게다가 나 혼자 듣는 게 아니라 같이 나아가고 있다는 생각이 들어서 더욱 끝까지 해낼 수 있었습니다.백엔드 개발을 하다 보면 시각적으로 잘 안 보이는 부분이 많은데, 여러 무료 템플릿들과 Thymeleaf로 간단한 뷰는 개발할 수 있었습니다. 덕분에 화면으로 결과물을 확인해서 좋았습니다.강의를 통해 웹 기초, Git 사용, API 개발, 뷰 개발, 테스트코드 작성, 시큐리티 설정, Jasypt 사용, Docker 빌드, 클라우드 배포까지 한 플로우를 거쳐보았습니다. 앞으로 필요한 서버가 있다면 어렵지 않게 올릴 수 있을 것 같은 자신감이 들었습니다. !!3주차 부터는 바쁜 일이 많아 미니 프로젝트에 시간을 쏟지 못한 부분이 아쉽습니다. 😞 그리고 미션 6을 놓치는 바람에 중간에 의지를 잃기도 했지만.. ! 유예 기간 덕분에 다시 도전하게 되었고 끝까지 마무리했습니다.중간점검 2차 때는 이력서 피드백을 받을 수 있었습니다. 제가 한번도 고려하지 못한 부분이라 도움이 많이 되었고, 남 이력서에 피드백을 달아주는 게 보통 일이 아닌데 꼼꼼한 리뷰 너무 감사했습니다. 그동안 이력서를 남에게 공개하는 것 자체도 너무 부끄러웠는데, 좋은 방향으로 나아갈 수 있도록 앞으로 많이 피드백 받고 개선해야겠습니다.아쉬운 점도 있지만 마지막 날까지 잘 해냈다고 스스로에게 칭찬하고 싶습니다. 저 뿐만 아니라 모든 완주한 분들, 사정 상 중간에 포기하신 분들도 그동안 고생하셨습니다. 👏
![[워밍업 BE 프로젝트 3기] 3주차 발자국](https://cdn.inflearn.com/public/main/blog/default_thumbnail.png?w=260)
2025. 03. 23.
0
[워밍업 BE 프로젝트 3기] 3주차 발자국
학습 3주차는 섹션 5에 대해 학습합니다. 공통 개발 - Exception/Advice컨트롤러에서 @ExceptionHandler로 선언된 메서드가 있으면 해당 컨트롤러에서 발생한 에러를 처리함하지만 @GetMapping 같은 실제 API랑 핸들러랑 같이 있으면 보기에도 좋지 않으며, 중복 코드 발생예외 핸들러를 @RestControllerAdvice가 달린 클래스에 모아두는 것 공통 개발 - DTOKotlin에는 static이 없어서 companion object를 이용해서 정적 메서드 구현vararg 키워드: Python에서 나머지 파라미터 긁어오는 것과 비슷한 기능 조회 개발Kotlin에서 삼항연산자는 없지만, 비슷한 문법으로 if (condition) A else B 로 사용 가능 -> Python이랑 비슷하다고 느낌 삽입, 수정, 삭제 개발1:N 관계에서 cascade 옵션 때문에 experience만 저장해도 detail까지 저장됨Map 을 생성할 때 x to y 로 Pair를 표현할 수 있음experience.details.map { it.id to it }.toMap()JPA의 자동 변경분 적용 기능NestJS+TypeORM을 사용할때면 무조건 코드 마지막줄에 save()를 작성해서 그런지 익숙하지 않았다.Spring, JPA를 사용한 경험이 많지 않다 보니 자꾸 까먹는다. . 뷰 개발, 대시보드 개발템플릿이 유료로 전환되어 사용할 수 없었음더이상 무료 템플릿이 아닌데 강사님의 코드를 붙여넣기 하는 건 괜찮을까..? 라는 생각이 들어서 우선 실습을 건너뜀 추가 탐구 bindingResult.fieldErrors vs. bindingResult.fieldErrore.bindingResult. 까지 쳤을 때 자동완성으로 fieldErrors와 fieldError가 존재했다.두 개의 차이가 무엇일지 궁금해졌다. getFieldErrors()는 전체 에러를 리스트로 반환하고, getFieldError()는 첫 번째 에러를 반환한다.실습 때 진행한 것처럼 [0] 으로 첫 번째에 접근하는 경우에는 리스트가 비어서 에러가 날 수도 있으니 안전하게 getFieldError()로 사용하면 되겠다고 생각한다. equals() vs. ==IDE에서 equals() 대신 == 로 바꿔 쓸 것을 추천했다.이유는 잘 모르겠습니다. . OptionalexperienceRepository.findById(id) .orElseThrow { throw AdminBadRequestException("ID ${id}에 해당하는 데이터를 찾을 수 없습니다.") } .detailsOptional 덕분에 orElseThrow()에서 예외가 던져지지 않았다면 데이터가 존재한다는 걸 의미한다.그래서 details에 바로 접근할 수 있었다. Validate 옵션 확인코드 내 import문에서 control+원하는 부분을 선택하면 사용할 수 있는 데코레이터, 클래스 등을 확인할 수 있었다. 사실 조금만 IDE를 써봐도 당연했던 건데 코드에서만 따라가봤지 import문에서 선택한다는 생각을 못했어서 신기했다.그 전에는 어떤 옵션이 있을지 IDE 자동완성이나 코파일럿 추천을 기다리고 있었다. 🥲 미션 과제에 대한 마지막 미션으로 를 진행했습니다. 삽입, 수정 시에는 @Transactional을 꼭 빼먹지 않도록 유의했습니다. 그리고 추가로 필요한 조회 요청이 있어 구현했습니다.GET 요청 할 때 쿼리 파라미터를 여러 개 전달하기를 원했는데 이를 컨트롤러에서 여러 개의 @RequestParam을 쓰기보다는 클래스로 지정해서 객체 형태로 받고 싶었습니다.이렇게 하니 400 에러가 발생했고, @ModelAttribute로 해결하게 되었습니다.디테일하게 해당 어노테이션을 탐구해본건 아니지만, 주로 폼데이터에서 여러 파라미터를 객체에 바인딩할 때 사용됩니다. 제약사항으로 Setter나 모든 필드를 받는 생성자가 존재해야 했는데, 후자로 해결하였습니다.@GetMapping("/v1/transactions") fun getTransactions(@ModelAttribute request: FindTransactionRecordsRequest): List { return presentationService.getTransactions(request) }data class FindTransactionRecordsRequest( @field:NotEmpty val userId: Long, val categoryId: Long?, @field:NotEmpty val year: Int, @field:NotEmpty val month: Int, ) 삭제 로직의 경우, Soft delete로 구현하면 좋을 것 같아서 해당 방법을 찾아보았습니다.@SQLRestriction("deleted_date_time is null") @SQLDelete(sql = "UPDATE transaction SET deleted_date_time = NOW() WHERE id = ?")저는 엔티티마다 deleted_date_time을 두어서 삭제 날짜를 저장했습니다. 따라서 해당 값이 null이면 삭제되지 않은 데이터입니다.그래서 @SQLDelete로 deleted_date_time=NOW() 를 명시하여 삭제 시 해당 쿼리가 나가도록 작성했습니다. 그리고 남은 기간 동안 개선해보면 좋을 점을 몇 개 작성해보았습니다.필드 유효성 검사 에러 핸들링 로직 - 현재 에러 메시지가 제대로 응답에 나가지 않음로그인 기반으로 헤더에서 정보 추출 - 로그인 기능이 없어 유저 아이디를 바디로 함께 보내고 있음컨트롤러 분리 - PresentationApiController에서 여러 엔티티에 대한 CRUD를 하고 있어 적절하게 분리 필요 바쁜 한 주여서 강의도 몰아듣느라 과제 제출에 필요한 최소한의 기능만 구현했습니다.시작할 땐 욕심이 많았는데 점점 타협하게 되는것 같아서 아쉽지만, 마지막 주는 커리큘럼 상 강의가 이틀만 있어서 남은 기간은 디테일에 집중해보려고 합니다.마지막까지 화이팅 !! 💪🏻
![[워밍업 BE 프로젝트 3기] 2주차 발자국](https://cdn.inflearn.com/public/main/blog/default_thumbnail.png?w=260)
2025. 03. 16.
0
[워밍업 BE 프로젝트 3기] 2주차 발자국
학습 2주차는 섹션 3 뒷부분부터 섹션 4까지 진행합니다. 모르는 부분 위주로 기록하며 학습했습니다. 데이터베이스 초기화하기스프링 건설 작업 이후 수행되는 데이터 초기화 기능 작성 리포지토리 개발 / 테스트 / 성능 개선 @DataJpaTest에는 @Transactional이 있어 메서드 하나마다 트랜잭션이 적용되며 종료 시 롤백됨@TestInstance를 적용하여 인스턴스의 라이프사이클 변경 가능for (i in 1..n) {} 같은 문법도 알게 됨N+1 문제 해결을 위해 JPQL로 직접 쿼리 지정default_batch_fetch_size 를 지정하여 페치 사이즈 지정 가능 컨트롤러 클래스 생성@RestController는 지정한 응답을 그대로 반환@Controller는 /resources/templates 하위의 html 파일을 반환 DTO 개발DTO 생성할 때 필터링을 수행함 -> 데이터 조회 쿼리에서 조건을 추가할 순 있지만, JPA 원칙상 지양해야 함 Presentation Layer 개발 / 테스트여러 서비스에서 레포지터리를 주입받다보면 관리가 복잡해짐 -> 필요한 레포지터리를 한번에 래핑해서 사용함 (퍼사드패턴)@Transactional(readOnly=true) → JPA에서 스냅샷 뜨고 비교하는 작업 생략테스트 시 모킹 인스턴스 주입 방식@InjectMocks -> 강의에서는 서비스 주입에 사용. @Mock으로 생성된 객체를 주입하여 실제 객체를 생성함@Mock -> 강의에서는 레포지터리 주입에 사용. 단순히 가짜 객체를 만듦lateinit -> 초기화를 늦춤@AutoConfigureMockMvc → 자동으로 MockMvc 관련 설정 추가 Thymeleaf 부트스트랩 템플릿 추가: 파일을 수정하여 사용할 부분 코드만 정리 -> 해당 파일에서 아이디가 navigation인 컴포넌트를 찾아 로드 인터셉터 개발: HandlerInterceptor의 메서드를 오버라이딩preHandle: 컨트롤러까지 요청이 가기 전에 동작postHandle: 컨트롤러가 응답을 리턴한 이후에 동작 - 예외 시 동작 XafterCompletion: '' - 예외 시 동작 O 미션 1주차에 이어서 2주차 미션도 2가지입니다.Rest API 설계조회 API 만들기 API 문서는 사용해본 도구가 많이 없어서, Postman에서 제공하는 Documentation을 이용했습니다. 다 하고 뭐가 부족하다 싶었는데 응답을 설정하지 않았더라고요. 제출을 먼저 해버렸지만 Mock Server 같이 응답 폼을 미리 명시할 수 있는 방법을 더 찾아봐야겠습니다. 여기까지는 대부분 설계한 산출물을 제출하는 작업이었습니다. 하지만 바로 API를 하나 만들게 되면서 그동안 강의에서 배운 모든 작업이 필요했습니다.application.yml 설정레포지터리, 서비스, 컨트롤러 구현더미데이터 추가 클래스 구현 단순히 과제를 제출하는데 의의를 두었다면 조회 기능만 간단하게 구현했을 것 같습니다.하지만 저는 이번 워밍업을 하면서 그 전에 해보지 않았던 걸 해보며 한 단계 나아가는 경험을 하고 싶었습니다.그래서 강의에서 나왔던 더미데이터 추가, 테스트 코드 작성도 완료하여 제출하려고 합니다. 테스트 코드를 작성하면서 겪은 문제가 크게 2가지 있었습니다. (상세한 내용은 리드미에 작성할 예정입니다.)먼저 레포지터리를 추가할 수 없다는 문제를 맞았는데, 해결하며 문제와 관련해서 스프링에서 엔티티를 찾는 원리, 컴포넌트 스캔, ApplicationContext 등에 대해 찾아보게 되었습니다.두 번째로는 테이블을 생성하는 DDL이 자동으로 실행되면서 생긴 에러입니다. 생각보다 간단한 문제였고 테이블 이름을 지을 때 신중해야겠다고 느꼈습니다. 🥲 확실히 직접 해보면서 강의에서는 마주하지 않은 문제들을 해결해보니 더욱 흥미가 생겼고, 시간 가는 줄 모르게 작업한 것 같습니다.이제 절반 조금 넘게 달렸는데, 힘내서 꼭 완주하겠습니다. !!
![[워밍업 BE 프로젝트 3기] 1주차 발자국 - 안녕 코프링](https://cdn.inflearn.com/public/main/blog/default_thumbnail.png?w=260)
2025. 03. 08.
0
[워밍업 BE 프로젝트 3기] 1주차 발자국 - 안녕 코프링
안녕 ?Bye 아니고, Hi 입니다. 요즘 가장 핫한 스택 같아서 경험해보고 싶은 욕구는 있었는데, 타이밍 좋게 워밍업을 알게되어 참가했습니다.스프링을 아예 처음 접하는 건 아니라서 다른 언어들과 코틀린이 어떤 차이가 있는지, 특히 자바(+스프링)와 어떻게 다를지도 궁금합니다.또 그동안 몰랐던 개념이 있다면 보완해나가는 시간이 될 것 같습니다.개인적으로 테스트 코드 작성 경험이 없는데, 관련 내용도 다루는 것 같아 더욱 기대하고 있습니다. 학습 1주차는 처음부터 섹션 3의 일부까지 진행합니다.기본 이론: 웹서비스 구성 요소, Spring, HTTP, REST API, DB, 테이블 설계, Git/Github프로젝트 세팅: 프로젝트 생성, 개발환경 및 환경변수 설정, Github 연결엔티티 개발: 설계한 테이블을 클래스로 정의, 엔티티 간 관계 설정, 필요한 메서드 구현 이론 강의들을 통해 기억에서 흐려지던 기본 개념들을 다시 짚어보았습니다.처음 접한 코틀린 문법에서 신기한 점도 많아서, 알아가는 재미가 있었습니다.생성자의 위치 - 클래스명 바로 옆에 있다. !map 함수 사용 문법 - 괄호가 아니라 중괄호가 나온다. ! it은 어디서 나오는 걸까?MutableList - 수정 가능한 리스트 같은데 ArrayList랑 뭐가 다를까? 본격 기능 개발은 커리큘럼 상 다음 주부터 진행되기 때문에 다음 강의가 기대됩니다. 😁 미션 1주차 미션은 2가지입니다.깃허브 레포지터리 생성테이블 설계 레포지터리 생성 미션은 강의에 나온 대로 하면 어렵지 않게 할 수 있었습니다.테이블 설계의 경우, 관계를 먼저 생각하지 않고 하고 싶은 프로젝트를 먼저 생각하다 보니 관계가 바로 떠오르지는 않았습니다.오히려 고민 포인트가 더 생겨서 좋았는데요, 저는 미니 가계부를 프로젝트 주제로 잡았고, 다음과 같이 관계를 정의했습니다.사용자가 필요한 카테고리(ex. 식비, 생필품)를 만들수 있습니다. -> 사용자와 카테고리는 1:N 입니다.사용자는 여러 거래를 기록합니다. -> 사용자와 거래는 1:N입니다.거래에는 하나의 카테고리가 지정됩니다. -> 카테고리와 거래는 1:N입니다. 여기서, '거래에서 카테고리를 타고 가면 사용자가 특정될 텐데 거래에서도 사용자를 가지고 있어야 할까?' 라는 생각이 들었습니다.물론 거래에 미리 정의된 카테고리만 지정 가능하도록 만든다면, 사용자와의 관계가 끊기기 때문에 간단하게 없어질 고민이죠. . . 유혹이 생기긴 합니다. 🥲발자국 작성 시점이 테이블 설계 미션 제출 전이라, 좀 더 고민해보기로 했습니다. 이번 워밍업을 통해 틀리더라도 다양한 고민을 해보면서 많이 배우는 시간이 되었으면 좋겠습니다.이왕이면 꼭 완주할 수 있기를 .. 아좌좟 ..! 💪🏻




